32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
248 if (Subtarget.is64Bit())
251 if (!Subtarget.hasBasicD()) {
253 if (Subtarget.is64Bit()) {
262 if (Subtarget.hasBasicD()) {
295 if (Subtarget.is64Bit())
301 if (Subtarget.hasExtLSX()) {
316 for (
MVT VT : LSXVTs) {
330 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
358 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
360 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
362 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
366 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
390 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
391 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
406 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
408 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
415 if (Subtarget.hasExtLASX()) {
416 for (
MVT VT : LASXVTs) {
431 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
460 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
462 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
464 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
468 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
487 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
492 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
499 if (Subtarget.hasBasicF()) {
510 if (Subtarget.hasExtLSX()) {
518 if (Subtarget.hasExtLASX()) {
545 if (Subtarget.hasLAMCAS())
548 if (Subtarget.hasSCQ()) {
568 switch (
Op.getOpcode()) {
570 return lowerATOMIC_FENCE(
Op, DAG);
572 return lowerEH_DWARF_CFA(
Op, DAG);
574 return lowerGlobalAddress(
Op, DAG);
576 return lowerGlobalTLSAddress(
Op, DAG);
578 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
580 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
582 return lowerINTRINSIC_VOID(
Op, DAG);
584 return lowerBlockAddress(
Op, DAG);
586 return lowerJumpTable(
Op, DAG);
588 return lowerShiftLeftParts(
Op, DAG);
590 return lowerShiftRightParts(
Op, DAG,
true);
592 return lowerShiftRightParts(
Op, DAG,
false);
594 return lowerConstantPool(
Op, DAG);
596 return lowerFP_TO_SINT(
Op, DAG);
598 return lowerBITCAST(
Op, DAG);
600 return lowerUINT_TO_FP(
Op, DAG);
602 return lowerSINT_TO_FP(
Op, DAG);
604 return lowerVASTART(
Op, DAG);
606 return lowerFRAMEADDR(
Op, DAG);
608 return lowerRETURNADDR(
Op, DAG);
610 return lowerWRITE_REGISTER(
Op, DAG);
612 return lowerINSERT_VECTOR_ELT(
Op, DAG);
614 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
616 return lowerBUILD_VECTOR(
Op, DAG);
618 return lowerCONCAT_VECTORS(
Op, DAG);
620 return lowerVECTOR_SHUFFLE(
Op, DAG);
622 return lowerBITREVERSE(
Op, DAG);
624 return lowerSCALAR_TO_VECTOR(
Op, DAG);
626 return lowerPREFETCH(
Op, DAG);
628 return lowerSELECT(
Op, DAG);
630 return lowerBRCOND(
Op, DAG);
632 return lowerFP_TO_FP16(
Op, DAG);
634 return lowerFP16_TO_FP(
Op, DAG);
636 return lowerFP_TO_BF16(
Op, DAG);
638 return lowerBF16_TO_FP(
Op, DAG);
640 return lowerVECREDUCE_ADD(
Op, DAG);
643 return lowerRotate(
Op, DAG);
651 return lowerVECREDUCE(
Op, DAG);
653 return lowerConstantFP(
Op, DAG);
655 return lowerSETCC(
Op, DAG);
657 return lowerFP_ROUND(
Op, DAG);
659 return lowerFP_EXTEND(
Op, DAG);
661 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
663 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
672 EVT VT = V.getValueType();
678 return V.getOperand(0);
682 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
684 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
694 if (!V->isOnlyUserOf(SplatValue.getNode()))
698 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
706 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
734 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
735 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
742 if (Opcode0 != Opcode1)
745 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
752 EVT VT =
N.getValueType();
766 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
767 SSVT0 == MVT::v4f64) {
786 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
787 N->getOpcode() == LoongArchISD::VPERMI) &&
788 Opcode0 == LoongArchISD::VFCVT) {
793 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
796 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
797 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
803 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
819 MVT VT =
Op.getSimpleValueType();
820 MVT SVT =
In.getSimpleValueType();
822 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
835 EVT VT =
Op.getValueType();
837 EVT SVT = Src.getValueType();
840 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
842 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
843 if (!V2F32ToV2F64 && !V4F32ToV4F64)
855 const uint64_t
Imm =
Op.getConstantOperandVal(1);
870 if (
SDValue V = CheckVecHighPart(Src)) {
872 "Unexpected wide vector");
873 Opcode = LoongArchISD::VFCVTH;
876 Opcode = LoongArchISD::VFCVTL;
878 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
883 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
889 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
901 EVT VT =
Op.getValueType();
906 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
907 (VT == MVT::f64 && Subtarget.hasBasicD()));
924 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
934 if (Subtarget.is64Bit())
936 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
937 : LoongArchISD::MOVGR2FR_W,
941 if (Subtarget.is64Bit()) {
943 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
947 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
959 EVT ResultVT =
Op.getValueType();
960 EVT OperandVT =
Op.getOperand(0).getValueType();
965 if (ResultVT == SetCCResultVT)
968 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
969 "SETCC operands must have the same type!");
973 Op.getOperand(1),
Op.getOperand(2));
975 if (ResultVT.
bitsGT(SetCCResultVT))
977 else if (ResultVT.
bitsLT(SetCCResultVT))
989SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
993 MVT SrcVT = Src.getSimpleValueType();
994 MVT DstVT =
Op.getSimpleValueType();
1005 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1025 MVT OpVT =
Op.getSimpleValueType();
1032 unsigned LegalVecSize = 128;
1033 bool isLASX256Vector =
1043 if (isLASX256Vector) {
1048 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1051 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1054 if (isLASX256Vector) {
1080 MVT OpVT =
Op.getSimpleValueType();
1093 MVT GRLenVT = Subtarget.getGRLenVT();
1095 for (
int i = NumEles; i > 1; i /= 2) {
1098 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1107 unsigned IsData =
Op.getConstantOperandVal(4);
1112 return Op.getOperand(0);
1119 MVT VT =
Op.getSimpleValueType();
1125 unsigned Opcode =
Op.getOpcode();
1128 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1134 CstSplatValue =
C->getAPIntValue();
1142 APInt CstSplatValue;
1143 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1147 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1163 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1179 if (
LHS == LHS2 &&
RHS == RHS2) {
1184 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1192 return std::nullopt;
1200 MVT VT =
N->getSimpleValueType(0);
1231 if (~TrueVal == FalseVal) {
1271 unsigned SelOpNo = 0;
1281 unsigned ConstSelOpNo = 1;
1282 unsigned OtherSelOpNo = 2;
1289 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1294 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1300 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1302 std::swap(NewConstOps[0], NewConstOps[1]);
1314 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1316 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1319 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1320 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1340 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1354 int64_t
C = RHSC->getSExtValue();
1397 MVT VT =
Op.getSimpleValueType();
1398 MVT GRLenVT = Subtarget.getGRLenVT();
1403 if (
Op.hasOneUse()) {
1404 unsigned UseOpc =
Op->user_begin()->getOpcode();
1406 SDNode *BinOp = *
Op->user_begin();
1413 return lowerSELECT(NewSel, DAG);
1430 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1453 if (TrueVal - 1 == FalseVal)
1455 if (TrueVal + 1 == FalseVal)
1462 RHS == TrueV &&
LHS == FalseV) {
1487 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1494 MVT GRLenVT = Subtarget.getGRLenVT();
1505 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1506 Op.getOperand(0),
LHS,
RHS, TargetCC,
1509 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1510 Op.getOperand(0), CondV,
Op.getOperand(2));
1514 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1520LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1523 MVT OpVT =
Op.getSimpleValueType();
1534 EVT ResTy =
Op->getValueType(0);
1539 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1549 for (
unsigned int i = 0; i < NewEltNum; i++) {
1552 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1553 ? (
unsigned)LoongArchISD::BITREV_8B
1571 for (
unsigned int i = 0; i < NewEltNum; i++)
1572 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1573 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1591 if (EltBits > 32 || EltBits == 1)
1619 int MaskOffset,
const APInt &Zeroable) {
1620 int Size = Mask.size();
1621 unsigned SizeInBits =
Size * ScalarSizeInBits;
1623 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1624 for (
int i = 0; i <
Size; i += Scale)
1625 for (
int j = 0; j < Shift; ++j)
1626 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1634 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1635 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1640 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1641 for (
int i = 0; i !=
Size; i += Scale) {
1642 unsigned Pos =
Left ? i + Shift : i;
1643 unsigned Low =
Left ? i : i + Shift;
1644 unsigned Len = Scale - Shift;
1649 int ShiftEltBits = ScalarSizeInBits * Scale;
1650 bool ByteShift = ShiftEltBits > 64;
1651 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1652 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1653 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1657 Scale = ByteShift ? Scale / 2 : Scale;
1663 return (
int)ShiftAmt;
1666 unsigned MaxWidth = 128;
1667 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1668 for (
int Shift = 1; Shift != Scale; ++Shift)
1669 for (
bool Left : {
true,
false})
1670 if (CheckZeros(Shift, Scale,
Left)) {
1671 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1696 const APInt &Zeroable) {
1697 int Size = Mask.size();
1711 Mask,
Size, Zeroable);
1719 "Illegal integer vector type");
1728template <
typename ValType>
1731 unsigned CheckStride,
1733 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1737 if (*
I != -1 && *
I != ExpectedIndex)
1739 ExpectedIndex += ExpectedIndexStride;
1743 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1755 int Size = Mask.size();
1765 int ScalarSizeInBits = VectorSizeInBits /
Size;
1766 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1767 (void)ScalarSizeInBits;
1769 for (
int i = 0; i <
Size; ++i) {
1775 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1792 RepeatedMask.
assign(LaneSize, -1);
1793 int Size = Mask.size();
1794 for (
int i = 0; i <
Size; ++i) {
1795 assert(Mask[i] == -1 || Mask[i] >= 0);
1798 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1805 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1806 if (RepeatedMask[i % LaneSize] < 0)
1808 RepeatedMask[i % LaneSize] = LocalM;
1809 else if (RepeatedMask[i % LaneSize] != LocalM)
1826 int NumElts = RepeatedMask.
size();
1828 int Scale = 16 / NumElts;
1830 for (
int i = 0; i < NumElts; ++i) {
1831 int M = RepeatedMask[i];
1832 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1833 "Unexpected mask index.");
1838 int StartIdx = i - (M % NumElts);
1845 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1848 Rotation = CandidateRotation;
1849 else if (Rotation != CandidateRotation)
1853 SDValue MaskV = M < NumElts ? V1 : V2;
1864 else if (TargetV != MaskV)
1869 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1870 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1879 return Rotation * Scale;
1898 if (ByteRotation <= 0)
1905 int LoByteShift = 16 - ByteRotation;
1906 int HiByteShift = ByteRotation;
1929 const APInt &Zeroable) {
1943 for (
int i = 0; i < NumElements; i++) {
1947 if (i % Scale != 0) {
1958 SDValue V = M < NumElements ? V1 : V2;
1959 M = M % NumElements;
1962 Offset = M - (i / Scale);
1965 if (
Offset % (NumElements / Scale))
1967 }
else if (InputV != V)
1970 if (M != (
Offset + (i / Scale)))
1980 unsigned VilVLoHi = LoongArchISD::VILVL;
1981 if (
Offset >= (NumElements / 2)) {
1982 VilVLoHi = LoongArchISD::VILVH;
1983 Offset -= (NumElements / 2);
1990 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1994 }
while (Scale > 1);
2000 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2001 NumExtElements *= 2) {
2021 int SplatIndex = -1;
2022 for (
const auto &M : Mask) {
2029 if (SplatIndex == -1)
2032 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2034 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2064 unsigned SubVecSize = 4;
2065 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2068 int SubMask[4] = {-1, -1, -1, -1};
2069 for (
unsigned i = 0; i < SubVecSize; ++i) {
2070 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2076 M -= 4 * (j / SubVecSize);
2077 if (M < 0 || M >= 4)
2083 if (SubMask[i] == -1)
2087 else if (M != -1 && M != SubMask[i])
2094 for (
int i = SubVecSize - 1; i >= 0; --i) {
2107 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2108 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2111 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
2129 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2138 for (
int i = 0; i < WidenNumElts; ++i)
2139 WidenMask[i] = WidenNumElts - 1 - i;
2147 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2171 const auto &Begin = Mask.begin();
2172 const auto &End = Mask.end();
2173 SDValue OriV1 = V1, OriV2 = V2;
2189 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
2211 const auto &Begin = Mask.begin();
2212 const auto &End = Mask.end();
2213 SDValue OriV1 = V1, OriV2 = V2;
2229 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2252 const auto &Begin = Mask.begin();
2253 const auto &End = Mask.end();
2254 unsigned HalfSize = Mask.size() / 2;
2255 SDValue OriV1 = V1, OriV2 = V2;
2272 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2295 const auto &Begin = Mask.begin();
2296 const auto &End = Mask.end();
2297 SDValue OriV1 = V1, OriV2 = V2;
2313 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2335 const auto &Begin = Mask.begin();
2336 const auto &Mid = Mask.begin() + Mask.size() / 2;
2337 const auto &End = Mask.end();
2338 SDValue OriV1 = V1, OriV2 = V2;
2355 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2377 const auto &Begin = Mask.begin();
2378 const auto &Mid = Mask.begin() + Mask.size() / 2;
2379 const auto &End = Mask.end();
2380 SDValue OriV1 = V1, OriV2 = V2;
2396 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2422 if (Mask.size() != NumElts)
2425 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2428 for (
unsigned i = 0; i < NumElts; ++i) {
2431 if (Mask[i] !=
int(
Base + i)) {
2444 int DiffMask = Mask[DiffPos];
2445 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2451 if (
unsigned(DiffMask) < NumElts) {
2456 SrcIdx =
unsigned(DiffMask) - NumElts;
2472 if (
SDValue Result = tryLowerToExtrAndIns(0))
2474 return tryLowerToExtrAndIns(NumElts);
2482 unsigned &MaskImm) {
2483 unsigned MaskSize = Mask.size();
2485 auto isValid = [&](
int M,
int Off) {
2486 return (M == -1) || (M >= Off && M < Off + 4);
2489 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2490 auto immPart = [&](
int M,
unsigned Off) {
2491 return (M == -1 ? 0 : (M - Off)) & 0x3;
2493 MaskImm |= immPart(MLo, Off) << (
I * 2);
2494 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2497 for (
unsigned i = 0; i < 4; i += 2) {
2499 int MHi = Mask[i + 1];
2501 if (MaskSize == 8) {
2502 int M2Lo = Mask[i + 4];
2503 int M2Hi = Mask[i + 5];
2504 if (M2Lo != MLo + 4 || M2Hi != MHi + 4)
2510 buildImm(MLo, MHi, 0, i);
2513 buildImm(MLo, MHi, MaskSize, i);
2543 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2548 unsigned MaskImm = 0;
2552 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2579 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2592 "Vector type is unsupported for lsx!");
2594 "Two operands have different types!");
2596 "Unexpected mask size for shuffle!");
2597 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2599 APInt KnownUndef, KnownZero;
2601 APInt Zeroable = KnownUndef | KnownZero;
2674 int SplatIndex = -1;
2675 for (
const auto &M : Mask) {
2682 if (SplatIndex == -1)
2685 const auto &Begin = Mask.begin();
2686 const auto &End = Mask.end();
2687 int HalfSize = Mask.size() / 2;
2689 if (SplatIndex >= HalfSize)
2692 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2696 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2710 if (Mask.size() == 4) {
2711 unsigned MaskImm = 0;
2712 for (
int i = 1; i >= 0; --i) {
2714 int MHi = Mask[i + 2];
2715 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2716 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2718 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2723 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2725 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2728 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2741 unsigned MaskSize = Mask.size();
2746 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2748 unsigned MaskImm = 0;
2752 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2757 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2758 unsigned MaskImm = 0;
2759 for (
unsigned i = 0; i < MaskSize; ++i) {
2762 if (Mask[i] >= (
int)MaskSize)
2764 MaskImm |= Mask[i] << (i * 2);
2767 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2779 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2783 unsigned HalfSize = NumElts / 2;
2784 bool FrontLo =
true, FrontHi =
true;
2785 bool BackLo =
true, BackHi =
true;
2787 auto inRange = [](
int val,
int low,
int high) {
2788 return (val == -1) || (val >= low && val < high);
2791 for (
unsigned i = 0; i < HalfSize; ++i) {
2792 int Fronti = Mask[i];
2793 int Backi = Mask[i + HalfSize];
2795 FrontLo &=
inRange(Fronti, 0, HalfSize);
2796 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2797 BackLo &=
inRange(Backi, 0, HalfSize);
2798 BackHi &=
inRange(Backi, HalfSize, NumElts);
2804 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2809 for (
unsigned i = 0; i < NumElts; ++i)
2814 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2836 const auto &Begin = Mask.begin();
2837 const auto &End = Mask.end();
2838 unsigned HalfSize = Mask.size() / 2;
2839 unsigned LeftSize = HalfSize / 2;
2840 SDValue OriV1 = V1, OriV2 = V2;
2847 Mask.size() + HalfSize - LeftSize, 1) &&
2849 Mask.size() + HalfSize + LeftSize, 1))
2860 Mask.size() + HalfSize - LeftSize, 1) &&
2862 Mask.size() + HalfSize + LeftSize, 1))
2867 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2875 const auto &Begin = Mask.begin();
2876 const auto &End = Mask.end();
2877 unsigned HalfSize = Mask.size() / 2;
2878 SDValue OriV1 = V1, OriV2 = V2;
2885 Mask.size() + HalfSize, 1))
2896 Mask.size() + HalfSize, 1))
2901 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2909 const auto &Begin = Mask.begin();
2910 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2911 const auto &Mid = Mask.begin() + Mask.size() / 2;
2912 const auto &RightMid = Mask.end() - Mask.size() / 4;
2913 const auto &End = Mask.end();
2914 unsigned HalfSize = Mask.size() / 2;
2915 SDValue OriV1 = V1, OriV2 = V2;
2936 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2944 const auto &Begin = Mask.begin();
2945 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2946 const auto &Mid = Mask.begin() + Mask.size() / 2;
2947 const auto &RightMid = Mask.end() - Mask.size() / 4;
2948 const auto &End = Mask.end();
2949 unsigned HalfSize = Mask.size() / 2;
2950 SDValue OriV1 = V1, OriV2 = V2;
2972 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2981 int HalfSize = NumElts / 2;
2985 if ((
int)Mask.size() != NumElts)
2988 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
2990 for (
int i = 0; i < NumElts; ++i) {
2993 if (Mask[i] !=
Base + i) {
2995 if (DiffPos.
size() > 2)
3003 if (DiffPos.
size() == 1) {
3004 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3005 DiffPos.
push_back(DiffPos[0] + HalfSize);
3006 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3007 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3011 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3015 int DiffMaskLo = Mask[DiffPos[0]];
3016 int DiffMaskHi = Mask[DiffPos[1]];
3017 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3018 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3019 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3020 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3022 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3023 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3025 if (DiffMaskHi != DiffMaskLo + HalfSize)
3029 SDValue SrcVec = (DiffMaskLo < HalfSize) ? V1 : V2;
3031 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3052 if (
SDValue Result = tryLowerToExtrAndIns(0))
3054 return tryLowerToExtrAndIns(NumElts);
3063 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3068 int MaskSize = Mask.size();
3074 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3076 for (
int i = 0; i < MaskSize; ++i) {
3077 if (Mask[i] ==
Base + i || Mask[i] == -1)
3079 if (Mask[i] != Replaced)
3090 int Idx = checkReplaceOne(0, MaskSize);
3092 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
3096 Idx = checkReplaceOne(MaskSize, 0);
3098 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
3109 int MaskSize = Mask.size();
3110 int HalfSize = Mask.size() / 2;
3111 const auto &Begin = Mask.begin();
3112 const auto &Mid = Mask.begin() + HalfSize;
3113 const auto &End = Mask.end();
3125 for (
auto it = Begin; it < Mid; it++) {
3128 else if ((*it >= 0 && *it < HalfSize) ||
3129 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3130 int M = *it < HalfSize ? *it : *it - HalfSize;
3135 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3137 for (
auto it = Mid; it < End; it++) {
3140 else if ((*it >= HalfSize && *it < MaskSize) ||
3141 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3142 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3147 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3151 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
3179 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3181 int MaskSize = Mask.size();
3182 int HalfSize = Mask.size() / 2;
3185 HalfMaskType preMask =
None, postMask =
None;
3187 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3188 return M < 0 || (M >= 0 && M < HalfSize) ||
3189 (M >= MaskSize && M < MaskSize + HalfSize);
3191 preMask = HighLaneTy;
3192 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3193 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3194 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3196 preMask = LowLaneTy;
3198 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3199 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3200 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3202 postMask = LowLaneTy;
3203 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3204 return M < 0 || (M >= 0 && M < HalfSize) ||
3205 (M >= MaskSize && M < MaskSize + HalfSize);
3207 postMask = HighLaneTy;
3215 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3218 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3220 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3226 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3231 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3232 *it = *it < 0 ? *it : *it - HalfSize;
3234 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3235 *it = *it < 0 ? *it : *it + HalfSize;
3237 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3239 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3245 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3250 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3251 *it = *it < 0 ? *it : *it - HalfSize;
3253 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3255 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3261 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3266 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3267 *it = *it < 0 ? *it : *it + HalfSize;
3292 int Size = Mask.size();
3293 int LaneSize =
Size / 2;
3295 bool LaneCrossing[2] = {
false,
false};
3296 for (
int i = 0; i <
Size; ++i)
3297 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3298 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3301 if (!LaneCrossing[0] && !LaneCrossing[1])
3305 InLaneMask.
assign(Mask.begin(), Mask.end());
3306 for (
int i = 0; i <
Size; ++i) {
3307 int &M = InLaneMask[i];
3310 if (((M %
Size) / LaneSize) != (i / LaneSize))
3311 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3316 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3331 "Vector type is unsupported for lasx!");
3333 "Two operands have different types!");
3335 "Unexpected mask size for shuffle!");
3336 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3337 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3339 APInt KnownUndef, KnownZero;
3341 APInt Zeroable = KnownUndef | KnownZero;
3428 ArrayRef<int> OrigMask = SVOp->
getMask();
3431 MVT VT =
Op.getSimpleValueType();
3435 bool V1IsUndef = V1.
isUndef();
3436 bool V2IsUndef = V2.
isUndef();
3437 if (V1IsUndef && V2IsUndef)
3450 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3451 SmallVector<int, 8> NewMask(OrigMask);
3452 for (
int &M : NewMask)
3453 if (M >= NumElements)
3459 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3460 (void)MaskUpperLimit;
3462 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3463 "Out of bounds shuffle index");
3485 std::tie(Res, Chain) =
3486 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3487 if (Subtarget.is64Bit())
3488 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3500 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3504 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3505 CallOptions,
DL, Chain);
3511 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3517 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3518 if (Subtarget.is64Bit())
3519 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3525 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3526 MVT VT =
Op.getSimpleValueType();
3531 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3552 "Unsupported vector type for broadcast.");
3555 bool IsIdeneity =
true;
3557 for (
int i = 0; i !=
NumOps; i++) {
3559 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3571 auto ExtType = LN->getExtensionType();
3576 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3581 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3599 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3613 EVT ResTy,
unsigned first) {
3616 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3619 Node->op_begin() + first + NumElts);
3628 MVT VT =
Node->getSimpleValueType(0);
3629 EVT ResTy =
Op->getValueType(0);
3632 APInt SplatValue, SplatUndef;
3633 unsigned SplatBitSize;
3636 bool UseSameConstant =
true;
3641 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3642 (!Subtarget.hasExtLASX() || !Is256Vec))
3648 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3650 SplatBitSize <= 64) {
3652 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3656 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3663 if ((Is128Vec && ResTy == MVT::v4i32) ||
3664 (Is256Vec && ResTy == MVT::v8i32))
3670 switch (SplatBitSize) {
3674 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3677 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3680 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3683 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3691 if (ViaVecTy != ResTy)
3700 for (
unsigned i = 0; i < NumElts; ++i) {
3705 ConstantValue = Opi;
3706 else if (ConstantValue != Opi)
3707 UseSameConstant =
false;
3712 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3714 for (
unsigned i = 0; i < NumElts; ++i) {
3732 BitVector UndefElements;
3733 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3734 UndefElements.
count() == 0) {
3738 EVT FillTy = Is256Vec
3744 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3747 unsigned SplatLen = NumElts / SeqLen;
3753 if (SplatEltTy == MVT::i128)
3754 SplatTy = MVT::v4i64;
3762 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3763 : LoongArchISD::XVREPLVE0,
3764 DL, SplatTy, SrcVec);
3766 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3779 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3780 ResTy == MVT::v4f64) {
3781 unsigned NonUndefCount = 0;
3782 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3783 if (!
Node->getOperand(i).isUndef()) {
3785 if (NonUndefCount > 1)
3789 if (NonUndefCount == 1)
3802 VecTy, NumElts / 2);
3813 MVT ResVT =
Op.getSimpleValueType();
3817 unsigned NumFreezeUndef = 0;
3818 unsigned NumZero = 0;
3819 unsigned NumNonZero = 0;
3820 unsigned NonZeros = 0;
3821 SmallSet<SDValue, 4> Undefs;
3822 for (
unsigned i = 0; i != NumOperands; ++i) {
3837 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3844 if (NumNonZero > 2) {
3848 Ops.slice(0, NumOperands / 2));
3850 Ops.slice(NumOperands / 2));
3863 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3865 for (
unsigned i = 0; i != NumOperands; ++i) {
3866 if ((NonZeros & (1 << i)) == 0)
3877LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3879 MVT EltVT =
Op.getSimpleValueType();
3884 MVT GRLenVT = Subtarget.getGRLenVT();
3912 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3916 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3918 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3927 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3936LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3938 MVT VT =
Op.getSimpleValueType();
3961 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3963 for (
unsigned i = 0; i < NumElts; ++i) {
3971 for (
unsigned i = 0; i < NumElts; ++i) {
3980 for (
unsigned i = 0; i < NumElts; ++i)
4012 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4014 "On LA64, only 64-bit registers can be written.");
4015 return Op.getOperand(0);
4018 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4020 "On LA32, only 32-bit registers can be written.");
4021 return Op.getOperand(0);
4031 "be a constant integer");
4037 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4038 EVT VT =
Op.getValueType();
4041 unsigned Depth =
Op.getConstantOperandVal(0);
4042 int GRLenInBytes = Subtarget.getGRLen() / 8;
4045 int Offset = -(GRLenInBytes * 2);
4057 if (
Op.getConstantOperandVal(0) != 0) {
4059 "return address can only be determined for the current frame");
4065 MVT GRLenVT = Subtarget.getGRLenVT();
4077 auto Size = Subtarget.getGRLen() / 8;
4085 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4095 MachinePointerInfo(SV));
4100 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4101 !Subtarget.hasBasicD() &&
"unexpected target features");
4107 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4111 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4121 EVT RetVT =
Op.getValueType();
4127 std::tie(Result, Chain) =
4134 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4135 !Subtarget.hasBasicD() &&
"unexpected target features");
4146 EVT RetVT =
Op.getValueType();
4152 std::tie(Result, Chain) =
4161 EVT VT =
Op.getValueType();
4165 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4166 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4168 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4170 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4173 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4187 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4188 !Subtarget.hasBasicD()) {
4190 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4212 N->getOffset(), Flags);
4220template <
class NodeTy>
4223 bool IsLocal)
const {
4234 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4315 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4317 const GlobalValue *GV =
N->getGlobal();
4329 unsigned Opc,
bool UseGOT,
4333 MVT GRLenVT = Subtarget.getGRLenVT();
4347 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4385 Args.emplace_back(Load, CallTy);
4388 TargetLowering::CallLoweringInfo CLI(DAG);
4403 const GlobalValue *GV =
N->getGlobal();
4417LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4424 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4427 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4440 return getDynamicTLSAddr(
N, DAG,
4441 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4442 : LoongArch::PseudoLA_TLS_GD,
4449 return getDynamicTLSAddr(
N, DAG,
4450 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4451 : LoongArch::PseudoLA_TLS_LD,
4456 return getStaticTLSAddr(
N, DAG,
4457 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4458 : LoongArch::PseudoLA_TLS_IE,
4465 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4469 return getTLSDescAddr(
N, DAG,
4470 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4471 : LoongArch::PseudoLA_TLS_DESC,
4475template <
unsigned N>
4480 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4481 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4483 ": argument out of range.");
4490LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4492 switch (
Op.getConstantOperandVal(0)) {
4495 case Intrinsic::thread_pointer: {
4499 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4500 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4501 case Intrinsic::loongarch_lsx_vreplvei_d:
4502 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4504 case Intrinsic::loongarch_lsx_vreplvei_w:
4505 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4506 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4507 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4508 case Intrinsic::loongarch_lasx_xvpickve_d:
4509 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4511 case Intrinsic::loongarch_lasx_xvinsve0_d:
4513 case Intrinsic::loongarch_lsx_vsat_b:
4514 case Intrinsic::loongarch_lsx_vsat_bu:
4515 case Intrinsic::loongarch_lsx_vrotri_b:
4516 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4517 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4518 case Intrinsic::loongarch_lsx_vsrlri_b:
4519 case Intrinsic::loongarch_lsx_vsrari_b:
4520 case Intrinsic::loongarch_lsx_vreplvei_h:
4521 case Intrinsic::loongarch_lasx_xvsat_b:
4522 case Intrinsic::loongarch_lasx_xvsat_bu:
4523 case Intrinsic::loongarch_lasx_xvrotri_b:
4524 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4525 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4526 case Intrinsic::loongarch_lasx_xvsrlri_b:
4527 case Intrinsic::loongarch_lasx_xvsrari_b:
4528 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4529 case Intrinsic::loongarch_lasx_xvpickve_w:
4530 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4532 case Intrinsic::loongarch_lasx_xvinsve0_w:
4534 case Intrinsic::loongarch_lsx_vsat_h:
4535 case Intrinsic::loongarch_lsx_vsat_hu:
4536 case Intrinsic::loongarch_lsx_vrotri_h:
4537 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4538 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4539 case Intrinsic::loongarch_lsx_vsrlri_h:
4540 case Intrinsic::loongarch_lsx_vsrari_h:
4541 case Intrinsic::loongarch_lsx_vreplvei_b:
4542 case Intrinsic::loongarch_lasx_xvsat_h:
4543 case Intrinsic::loongarch_lasx_xvsat_hu:
4544 case Intrinsic::loongarch_lasx_xvrotri_h:
4545 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4546 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4547 case Intrinsic::loongarch_lasx_xvsrlri_h:
4548 case Intrinsic::loongarch_lasx_xvsrari_h:
4549 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4551 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4552 case Intrinsic::loongarch_lsx_vsrani_b_h:
4553 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4554 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4555 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4556 case Intrinsic::loongarch_lsx_vssrani_b_h:
4557 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4558 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4559 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4560 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4561 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4562 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4563 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4564 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4565 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4566 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4567 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4568 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4569 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4570 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4571 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4572 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4573 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4574 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4576 case Intrinsic::loongarch_lsx_vsat_w:
4577 case Intrinsic::loongarch_lsx_vsat_wu:
4578 case Intrinsic::loongarch_lsx_vrotri_w:
4579 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4580 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4581 case Intrinsic::loongarch_lsx_vsrlri_w:
4582 case Intrinsic::loongarch_lsx_vsrari_w:
4583 case Intrinsic::loongarch_lsx_vslei_bu:
4584 case Intrinsic::loongarch_lsx_vslei_hu:
4585 case Intrinsic::loongarch_lsx_vslei_wu:
4586 case Intrinsic::loongarch_lsx_vslei_du:
4587 case Intrinsic::loongarch_lsx_vslti_bu:
4588 case Intrinsic::loongarch_lsx_vslti_hu:
4589 case Intrinsic::loongarch_lsx_vslti_wu:
4590 case Intrinsic::loongarch_lsx_vslti_du:
4591 case Intrinsic::loongarch_lsx_vbsll_v:
4592 case Intrinsic::loongarch_lsx_vbsrl_v:
4593 case Intrinsic::loongarch_lasx_xvsat_w:
4594 case Intrinsic::loongarch_lasx_xvsat_wu:
4595 case Intrinsic::loongarch_lasx_xvrotri_w:
4596 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4597 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4598 case Intrinsic::loongarch_lasx_xvsrlri_w:
4599 case Intrinsic::loongarch_lasx_xvsrari_w:
4600 case Intrinsic::loongarch_lasx_xvslei_bu:
4601 case Intrinsic::loongarch_lasx_xvslei_hu:
4602 case Intrinsic::loongarch_lasx_xvslei_wu:
4603 case Intrinsic::loongarch_lasx_xvslei_du:
4604 case Intrinsic::loongarch_lasx_xvslti_bu:
4605 case Intrinsic::loongarch_lasx_xvslti_hu:
4606 case Intrinsic::loongarch_lasx_xvslti_wu:
4607 case Intrinsic::loongarch_lasx_xvslti_du:
4608 case Intrinsic::loongarch_lasx_xvbsll_v:
4609 case Intrinsic::loongarch_lasx_xvbsrl_v:
4611 case Intrinsic::loongarch_lsx_vseqi_b:
4612 case Intrinsic::loongarch_lsx_vseqi_h:
4613 case Intrinsic::loongarch_lsx_vseqi_w:
4614 case Intrinsic::loongarch_lsx_vseqi_d:
4615 case Intrinsic::loongarch_lsx_vslei_b:
4616 case Intrinsic::loongarch_lsx_vslei_h:
4617 case Intrinsic::loongarch_lsx_vslei_w:
4618 case Intrinsic::loongarch_lsx_vslei_d:
4619 case Intrinsic::loongarch_lsx_vslti_b:
4620 case Intrinsic::loongarch_lsx_vslti_h:
4621 case Intrinsic::loongarch_lsx_vslti_w:
4622 case Intrinsic::loongarch_lsx_vslti_d:
4623 case Intrinsic::loongarch_lasx_xvseqi_b:
4624 case Intrinsic::loongarch_lasx_xvseqi_h:
4625 case Intrinsic::loongarch_lasx_xvseqi_w:
4626 case Intrinsic::loongarch_lasx_xvseqi_d:
4627 case Intrinsic::loongarch_lasx_xvslei_b:
4628 case Intrinsic::loongarch_lasx_xvslei_h:
4629 case Intrinsic::loongarch_lasx_xvslei_w:
4630 case Intrinsic::loongarch_lasx_xvslei_d:
4631 case Intrinsic::loongarch_lasx_xvslti_b:
4632 case Intrinsic::loongarch_lasx_xvslti_h:
4633 case Intrinsic::loongarch_lasx_xvslti_w:
4634 case Intrinsic::loongarch_lasx_xvslti_d:
4636 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4637 case Intrinsic::loongarch_lsx_vsrani_h_w:
4638 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4639 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4640 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4641 case Intrinsic::loongarch_lsx_vssrani_h_w:
4642 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4643 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4644 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4645 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4646 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4647 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4648 case Intrinsic::loongarch_lsx_vfrstpi_b:
4649 case Intrinsic::loongarch_lsx_vfrstpi_h:
4650 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4651 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4652 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4653 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4654 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4655 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4656 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4657 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4658 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4659 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4660 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4661 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4662 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4663 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4665 case Intrinsic::loongarch_lsx_vsat_d:
4666 case Intrinsic::loongarch_lsx_vsat_du:
4667 case Intrinsic::loongarch_lsx_vrotri_d:
4668 case Intrinsic::loongarch_lsx_vsrlri_d:
4669 case Intrinsic::loongarch_lsx_vsrari_d:
4670 case Intrinsic::loongarch_lasx_xvsat_d:
4671 case Intrinsic::loongarch_lasx_xvsat_du:
4672 case Intrinsic::loongarch_lasx_xvrotri_d:
4673 case Intrinsic::loongarch_lasx_xvsrlri_d:
4674 case Intrinsic::loongarch_lasx_xvsrari_d:
4676 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4677 case Intrinsic::loongarch_lsx_vsrani_w_d:
4678 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4679 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4680 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4681 case Intrinsic::loongarch_lsx_vssrani_w_d:
4682 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4683 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4684 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4685 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4686 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4687 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4688 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4689 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4690 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4691 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4692 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4693 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4694 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4695 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4696 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4697 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4698 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4699 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4701 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4702 case Intrinsic::loongarch_lsx_vsrani_d_q:
4703 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4704 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4705 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4706 case Intrinsic::loongarch_lsx_vssrani_d_q:
4707 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4708 case Intrinsic::loongarch_lsx_vssrani_du_q:
4709 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4710 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4711 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4712 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4713 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4714 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4715 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4716 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4717 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4718 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4719 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4720 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4721 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4722 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4723 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4724 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4726 case Intrinsic::loongarch_lsx_vnori_b:
4727 case Intrinsic::loongarch_lsx_vshuf4i_b:
4728 case Intrinsic::loongarch_lsx_vshuf4i_h:
4729 case Intrinsic::loongarch_lsx_vshuf4i_w:
4730 case Intrinsic::loongarch_lasx_xvnori_b:
4731 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4732 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4733 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4734 case Intrinsic::loongarch_lasx_xvpermi_d:
4736 case Intrinsic::loongarch_lsx_vshuf4i_d:
4737 case Intrinsic::loongarch_lsx_vpermi_w:
4738 case Intrinsic::loongarch_lsx_vbitseli_b:
4739 case Intrinsic::loongarch_lsx_vextrins_b:
4740 case Intrinsic::loongarch_lsx_vextrins_h:
4741 case Intrinsic::loongarch_lsx_vextrins_w:
4742 case Intrinsic::loongarch_lsx_vextrins_d:
4743 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4744 case Intrinsic::loongarch_lasx_xvpermi_w:
4745 case Intrinsic::loongarch_lasx_xvpermi_q:
4746 case Intrinsic::loongarch_lasx_xvbitseli_b:
4747 case Intrinsic::loongarch_lasx_xvextrins_b:
4748 case Intrinsic::loongarch_lasx_xvextrins_h:
4749 case Intrinsic::loongarch_lasx_xvextrins_w:
4750 case Intrinsic::loongarch_lasx_xvextrins_d:
4752 case Intrinsic::loongarch_lsx_vrepli_b:
4753 case Intrinsic::loongarch_lsx_vrepli_h:
4754 case Intrinsic::loongarch_lsx_vrepli_w:
4755 case Intrinsic::loongarch_lsx_vrepli_d:
4756 case Intrinsic::loongarch_lasx_xvrepli_b:
4757 case Intrinsic::loongarch_lasx_xvrepli_h:
4758 case Intrinsic::loongarch_lasx_xvrepli_w:
4759 case Intrinsic::loongarch_lasx_xvrepli_d:
4761 case Intrinsic::loongarch_lsx_vldi:
4762 case Intrinsic::loongarch_lasx_xvldi:
4778LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4781 MVT GRLenVT = Subtarget.getGRLenVT();
4782 EVT VT =
Op.getValueType();
4784 const StringRef ErrorMsgOOR =
"argument out of range";
4785 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4786 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4788 switch (
Op.getConstantOperandVal(1)) {
4791 case Intrinsic::loongarch_crc_w_b_w:
4792 case Intrinsic::loongarch_crc_w_h_w:
4793 case Intrinsic::loongarch_crc_w_w_w:
4794 case Intrinsic::loongarch_crc_w_d_w:
4795 case Intrinsic::loongarch_crcc_w_b_w:
4796 case Intrinsic::loongarch_crcc_w_h_w:
4797 case Intrinsic::loongarch_crcc_w_w_w:
4798 case Intrinsic::loongarch_crcc_w_d_w:
4800 case Intrinsic::loongarch_csrrd_w:
4801 case Intrinsic::loongarch_csrrd_d: {
4802 unsigned Imm =
Op.getConstantOperandVal(2);
4805 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4808 case Intrinsic::loongarch_csrwr_w:
4809 case Intrinsic::loongarch_csrwr_d: {
4810 unsigned Imm =
Op.getConstantOperandVal(3);
4813 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4814 {Chain,
Op.getOperand(2),
4817 case Intrinsic::loongarch_csrxchg_w:
4818 case Intrinsic::loongarch_csrxchg_d: {
4819 unsigned Imm =
Op.getConstantOperandVal(4);
4822 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4823 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4826 case Intrinsic::loongarch_iocsrrd_d: {
4828 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4831#define IOCSRRD_CASE(NAME, NODE) \
4832 case Intrinsic::loongarch_##NAME: { \
4833 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4834 {Chain, Op.getOperand(2)}); \
4840 case Intrinsic::loongarch_cpucfg: {
4841 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4842 {Chain,
Op.getOperand(2)});
4844 case Intrinsic::loongarch_lddir_d: {
4845 unsigned Imm =
Op.getConstantOperandVal(3);
4850 case Intrinsic::loongarch_movfcsr2gr: {
4851 if (!Subtarget.hasBasicF())
4853 unsigned Imm =
Op.getConstantOperandVal(2);
4856 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4859 case Intrinsic::loongarch_lsx_vld:
4860 case Intrinsic::loongarch_lsx_vldrepl_b:
4861 case Intrinsic::loongarch_lasx_xvld:
4862 case Intrinsic::loongarch_lasx_xvldrepl_b:
4866 case Intrinsic::loongarch_lsx_vldrepl_h:
4867 case Intrinsic::loongarch_lasx_xvldrepl_h:
4871 Op,
"argument out of range or not a multiple of 2", DAG)
4873 case Intrinsic::loongarch_lsx_vldrepl_w:
4874 case Intrinsic::loongarch_lasx_xvldrepl_w:
4878 Op,
"argument out of range or not a multiple of 4", DAG)
4880 case Intrinsic::loongarch_lsx_vldrepl_d:
4881 case Intrinsic::loongarch_lasx_xvldrepl_d:
4885 Op,
"argument out of range or not a multiple of 8", DAG)
4896 return Op.getOperand(0);
4902 MVT GRLenVT = Subtarget.getGRLenVT();
4904 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4906 const StringRef ErrorMsgOOR =
"argument out of range";
4907 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4908 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4909 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4911 switch (IntrinsicEnum) {
4915 case Intrinsic::loongarch_cacop_d:
4916 case Intrinsic::loongarch_cacop_w: {
4917 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4919 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4928 case Intrinsic::loongarch_dbar: {
4935 case Intrinsic::loongarch_ibar: {
4942 case Intrinsic::loongarch_break: {
4949 case Intrinsic::loongarch_movgr2fcsr: {
4950 if (!Subtarget.hasBasicF())
4960 case Intrinsic::loongarch_syscall: {
4967#define IOCSRWR_CASE(NAME, NODE) \
4968 case Intrinsic::loongarch_##NAME: { \
4969 SDValue Op3 = Op.getOperand(3); \
4970 return Subtarget.is64Bit() \
4971 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4972 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4973 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4974 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4981 case Intrinsic::loongarch_iocsrwr_d: {
4982 return !Subtarget.is64Bit()
4989#define ASRT_LE_GT_CASE(NAME) \
4990 case Intrinsic::loongarch_##NAME: { \
4991 return !Subtarget.is64Bit() \
4992 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4997#undef ASRT_LE_GT_CASE
4998 case Intrinsic::loongarch_ldpte_d: {
4999 unsigned Imm =
Op.getConstantOperandVal(3);
5000 return !Subtarget.is64Bit()
5005 case Intrinsic::loongarch_lsx_vst:
5006 case Intrinsic::loongarch_lasx_xvst:
5010 case Intrinsic::loongarch_lasx_xvstelm_b:
5015 case Intrinsic::loongarch_lsx_vstelm_b:
5020 case Intrinsic::loongarch_lasx_xvstelm_h:
5025 Op,
"argument out of range or not a multiple of 2", DAG)
5027 case Intrinsic::loongarch_lsx_vstelm_h:
5032 Op,
"argument out of range or not a multiple of 2", DAG)
5034 case Intrinsic::loongarch_lasx_xvstelm_w:
5039 Op,
"argument out of range or not a multiple of 4", DAG)
5041 case Intrinsic::loongarch_lsx_vstelm_w:
5046 Op,
"argument out of range or not a multiple of 4", DAG)
5048 case Intrinsic::loongarch_lasx_xvstelm_d:
5053 Op,
"argument out of range or not a multiple of 8", DAG)
5055 case Intrinsic::loongarch_lsx_vstelm_d:
5060 Op,
"argument out of range or not a multiple of 8", DAG)
5071 EVT VT =
Lo.getValueType();
5112 EVT VT =
Lo.getValueType();
5166 return LoongArchISD::DIV_W;
5168 return LoongArchISD::DIV_WU;
5170 return LoongArchISD::MOD_W;
5172 return LoongArchISD::MOD_WU;
5174 return LoongArchISD::SLL_W;
5176 return LoongArchISD::SRA_W;
5178 return LoongArchISD::SRL_W;
5181 return LoongArchISD::ROTR_W;
5183 return LoongArchISD::CTZ_W;
5185 return LoongArchISD::CLZ_W;
5204 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5205 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5209 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5215 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5242 StringRef ErrorMsg,
bool WithChain =
true) {
5247 Results.push_back(
N->getOperand(0));
5250template <
unsigned N>
5255 const StringRef ErrorMsgOOR =
"argument out of range";
5256 unsigned Imm =
Node->getConstantOperandVal(2);
5290 switch (
N->getConstantOperandVal(0)) {
5293 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5295 LoongArchISD::VPICK_SEXT_ELT);
5297 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5298 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5300 LoongArchISD::VPICK_SEXT_ELT);
5302 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5304 LoongArchISD::VPICK_SEXT_ELT);
5306 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5308 LoongArchISD::VPICK_ZEXT_ELT);
5310 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5311 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5313 LoongArchISD::VPICK_ZEXT_ELT);
5315 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5317 LoongArchISD::VPICK_ZEXT_ELT);
5319 case Intrinsic::loongarch_lsx_bz_b:
5320 case Intrinsic::loongarch_lsx_bz_h:
5321 case Intrinsic::loongarch_lsx_bz_w:
5322 case Intrinsic::loongarch_lsx_bz_d:
5323 case Intrinsic::loongarch_lasx_xbz_b:
5324 case Intrinsic::loongarch_lasx_xbz_h:
5325 case Intrinsic::loongarch_lasx_xbz_w:
5326 case Intrinsic::loongarch_lasx_xbz_d:
5328 LoongArchISD::VALL_ZERO);
5330 case Intrinsic::loongarch_lsx_bz_v:
5331 case Intrinsic::loongarch_lasx_xbz_v:
5333 LoongArchISD::VANY_ZERO);
5335 case Intrinsic::loongarch_lsx_bnz_b:
5336 case Intrinsic::loongarch_lsx_bnz_h:
5337 case Intrinsic::loongarch_lsx_bnz_w:
5338 case Intrinsic::loongarch_lsx_bnz_d:
5339 case Intrinsic::loongarch_lasx_xbnz_b:
5340 case Intrinsic::loongarch_lasx_xbnz_h:
5341 case Intrinsic::loongarch_lasx_xbnz_w:
5342 case Intrinsic::loongarch_lasx_xbnz_d:
5344 LoongArchISD::VALL_NONZERO);
5346 case Intrinsic::loongarch_lsx_bnz_v:
5347 case Intrinsic::loongarch_lasx_xbnz_v:
5349 LoongArchISD::VANY_NONZERO);
5357 assert(
N->getValueType(0) == MVT::i128 &&
5358 "AtomicCmpSwap on types less than 128 should be legal");
5362 switch (
MemOp->getMergedOrdering()) {
5366 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5370 Opcode = LoongArch::PseudoCmpXchg128;
5377 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5378 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5379 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5380 NewVal.first, NewVal.second,
N->getOperand(0)};
5383 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5394 EVT VT =
N->getValueType(0);
5395 switch (
N->getOpcode()) {
5400 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5401 "Unexpected custom legalisation");
5408 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5409 "Unexpected custom legalisation");
5411 Subtarget.hasDiv32() && VT == MVT::i32
5418 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5419 "Unexpected custom legalisation");
5427 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5428 "Unexpected custom legalisation");
5435 MVT VT =
N->getSimpleValueType(0);
5436 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5437 "Unexpected custom legalisation");
5439 "Unexpected type action!");
5444 Ld->getPointerInfo(), Ld->getBaseAlign(),
5445 Ld->getMemOperand()->getFlags());
5456 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5457 "Unexpected custom legalisation");
5464 if (Src.getValueType() == MVT::f16)
5475 EVT OpVT = Src.getValueType();
5479 std::tie(Result, Chain) =
5486 EVT SrcVT = Src.getValueType();
5487 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5488 Subtarget.hasBasicF()) {
5490 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5492 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5494 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5502 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5503 "Unexpected custom legalisation");
5506 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5511 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5512 "Unexpected custom legalisation");
5518 if (OpVT == MVT::v2f64) {
5528 assert((VT == MVT::i16 || VT == MVT::i32) &&
5529 "Unexpected custom legalization");
5530 MVT GRLenVT = Subtarget.getGRLenVT();
5537 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5542 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5550 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5551 "Unexpected custom legalization");
5552 MVT GRLenVT = Subtarget.getGRLenVT();
5559 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5562 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5570 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5571 "Unexpected custom legalisation");
5578 MVT GRLenVT = Subtarget.getGRLenVT();
5579 const StringRef ErrorMsgOOR =
"argument out of range";
5580 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5581 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5583 switch (
N->getConstantOperandVal(1)) {
5586 case Intrinsic::loongarch_movfcsr2gr: {
5587 if (!Subtarget.hasBasicF()) {
5597 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5604#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5605 case Intrinsic::loongarch_##NAME: { \
5606 SDValue NODE = DAG.getNode( \
5607 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5608 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5609 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5610 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5611 Results.push_back(NODE.getValue(1)); \
5620#undef CRC_CASE_EXT_BINARYOP
5622#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5623 case Intrinsic::loongarch_##NAME: { \
5624 SDValue NODE = DAG.getNode( \
5625 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5627 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5628 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5629 Results.push_back(NODE.getValue(1)); \
5634#undef CRC_CASE_EXT_UNARYOP
5635#define CSR_CASE(ID) \
5636 case Intrinsic::loongarch_##ID: { \
5637 if (!Subtarget.is64Bit()) \
5638 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5646 case Intrinsic::loongarch_csrrd_w: {
5653 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5660 case Intrinsic::loongarch_csrwr_w: {
5661 unsigned Imm =
N->getConstantOperandVal(3);
5667 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5675 case Intrinsic::loongarch_csrxchg_w: {
5676 unsigned Imm =
N->getConstantOperandVal(4);
5682 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5691#define IOCSRRD_CASE(NAME, NODE) \
5692 case Intrinsic::loongarch_##NAME: { \
5693 SDValue IOCSRRDResults = \
5694 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5695 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5696 Results.push_back( \
5697 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5698 Results.push_back(IOCSRRDResults.getValue(1)); \
5705 case Intrinsic::loongarch_cpucfg: {
5707 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5714 case Intrinsic::loongarch_lddir_d: {
5715 if (!Subtarget.is64Bit()) {
5725 if (Subtarget.is64Bit())
5727 "On LA64, only 64-bit registers can be read.");
5730 "On LA32, only 32-bit registers can be read.");
5732 Results.push_back(
N->getOperand(0));
5743 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5756 MVT VT =
N->getSimpleValueType(0);
5762 EVT InVT = In.getValueType();
5773 for (
unsigned I = 0;
I < MinElts; ++
I)
5774 TruncMask[
I] = Scale *
I;
5776 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5777 MVT SVT = In.getSimpleValueType().getScalarType();
5783 "Illegal vector type in truncation");
5795 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
5798 EVT DstVT =
N->getValueType(0);
5800 MVT SrcVT = Src.getSimpleValueType();
5814 unsigned WidenSrcElts = 128 / SrcEltBits;
5821 unsigned FirstStageEltBits = 128 / NumElts;
5825 SrcVT = FirstStageVT;
5826 SrcEltBits = FirstStageEltBits;
5833 while (SrcEltBits < DstEltBits) {
5834 unsigned NextEltBits = SrcEltBits * 2;
5837 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
5855 Blocks = std::move(NextBlocks);
5856 SrcVT = NextBlockVT;
5857 SrcEltBits = NextEltBits;
5869 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5871 MVT VT =
N->getSimpleValueType(0);
5890 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5894 unsigned MinSizeInBits) {
5902 unsigned SplatBitSize;
5905 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
5906 HasAnyUndefs, MinSizeInBits,
5916 EVT VT =
N->getValueType(0);
5982 if (
And.getOperand(0) ==
X) {
6011 if (ShiftVal != (SplatVal + 1))
6020 : LoongArchISD::VSRAR,
6030 SDValue FirstOperand =
N->getOperand(0);
6031 SDValue SecondOperand =
N->getOperand(1);
6032 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6033 EVT ValTy =
N->getValueType(0);
6036 unsigned SMIdx, SMLen;
6045 if (!Subtarget.has32S())
6101 NewOperand = FirstOperand;
6104 msb = lsb + SMLen - 1;
6108 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6121 if (!Subtarget.has32S())
6133 SDValue FirstOperand =
N->getOperand(0);
6135 EVT ValTy =
N->getValueType(0);
6138 unsigned MaskIdx, MaskLen;
6153 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6154 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6169 switch (Src.getOpcode()) {
6172 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6182 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6195 switch (Src.getOpcode()) {
6205 Src.getOpcode(),
DL, SExtVT,
6211 DL, SExtVT, Src.getOperand(0),
6223 EVT VT =
N->getValueType(0);
6225 EVT SrcVT = Src.getValueType();
6227 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6232 EVT CmpVT = Src.getOperand(0).getValueType();
6237 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6250 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6255 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6260 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6265 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6267 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6272 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6274 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6279 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6296 EVT VT =
N->getValueType(0);
6298 EVT SrcVT = Src.getValueType();
6315 bool UseLASX =
false;
6316 bool PropagateSExt =
false;
6318 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6319 EVT CmpVT = Src.getOperand(0).getValueType();
6328 SExtVT = MVT::v2i64;
6331 SExtVT = MVT::v4i32;
6333 SExtVT = MVT::v4i64;
6335 PropagateSExt =
true;
6339 SExtVT = MVT::v8i16;
6341 SExtVT = MVT::v8i32;
6343 PropagateSExt =
true;
6347 SExtVT = MVT::v16i8;
6349 SExtVT = MVT::v16i16;
6351 PropagateSExt =
true;
6355 SExtVT = MVT::v32i8;
6363 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6364 if (Src.getSimpleValueType() == MVT::v32i8) {
6372 }
else if (UseLASX) {
6378 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6391 EVT ValTy =
N->getValueType(0);
6392 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6396 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6398 bool SwapAndRetried =
false;
6401 if (!Subtarget.has32S())
6407 if (ValBits != 32 && ValBits != 64)
6422 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6425 (MaskIdx0 + MaskLen0 <= ValBits)) {
6446 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6447 (MaskIdx0 + MaskLen0 <= ValBits)) {
6464 (MaskIdx0 + MaskLen0 <= 64) &&
6472 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6473 : (MaskIdx0 + MaskLen0 - 1),
6489 (MaskIdx0 + MaskLen0 <= ValBits)) {
6512 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6513 : (MaskIdx0 + MaskLen0 - 1),
6528 unsigned MaskIdx, MaskLen;
6529 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6538 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6556 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
6562 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6570 if (!SwapAndRetried) {
6572 SwapAndRetried =
true;
6576 SwapAndRetried =
false;
6593 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6602 if (!SwapAndRetried) {
6604 SwapAndRetried =
true;
6614 switch (V.getNode()->getOpcode()) {
6626 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6634 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6711 SDNode *AndNode =
N->getOperand(0).getNode();
6719 SDValue CmpInputValue =
N->getOperand(1);
6728 if (!CN || !CN->
isZero())
6730 AndInputValue1 = AndInputValue1.
getOperand(0);
6734 if (AndInputValue2 != CmpInputValue)
6767 TruncInputValue1, TruncInputValue2);
6769 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6782 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6785 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6810 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6838 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6871 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6872 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6888 EVT VT =
N->getValueType(0);
6891 if (TrueV == FalseV)
6922 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6923 {LHS, RHS, CC, TrueV, FalseV});
6928template <
unsigned N>
6932 bool IsSigned =
false) {
6936 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6937 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6939 ": argument out of range.");
6945template <
unsigned N>
6949 EVT ResTy =
Node->getValueType(0);
6953 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6954 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6956 ": argument out of range.");
6961 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6967 EVT ResTy =
Node->getValueType(0);
6975 EVT ResTy =
Node->getValueType(0);
6984template <
unsigned N>
6987 EVT ResTy =
Node->getValueType(0);
6992 ": argument out of range.");
7002template <
unsigned N>
7005 EVT ResTy =
Node->getValueType(0);
7010 ": argument out of range.");
7019template <
unsigned N>
7022 EVT ResTy =
Node->getValueType(0);
7027 ": argument out of range.");
7036template <
unsigned W>
7039 unsigned Imm =
N->getConstantOperandVal(2);
7041 const StringRef ErrorMsg =
"argument out of range";
7043 return DAG.
getUNDEF(
N->getValueType(0));
7049 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7057 switch (
N->getConstantOperandVal(0)) {
7060 case Intrinsic::loongarch_lsx_vadd_b:
7061 case Intrinsic::loongarch_lsx_vadd_h:
7062 case Intrinsic::loongarch_lsx_vadd_w:
7063 case Intrinsic::loongarch_lsx_vadd_d:
7064 case Intrinsic::loongarch_lasx_xvadd_b:
7065 case Intrinsic::loongarch_lasx_xvadd_h:
7066 case Intrinsic::loongarch_lasx_xvadd_w:
7067 case Intrinsic::loongarch_lasx_xvadd_d:
7070 case Intrinsic::loongarch_lsx_vaddi_bu:
7071 case Intrinsic::loongarch_lsx_vaddi_hu:
7072 case Intrinsic::loongarch_lsx_vaddi_wu:
7073 case Intrinsic::loongarch_lsx_vaddi_du:
7074 case Intrinsic::loongarch_lasx_xvaddi_bu:
7075 case Intrinsic::loongarch_lasx_xvaddi_hu:
7076 case Intrinsic::loongarch_lasx_xvaddi_wu:
7077 case Intrinsic::loongarch_lasx_xvaddi_du:
7080 case Intrinsic::loongarch_lsx_vsub_b:
7081 case Intrinsic::loongarch_lsx_vsub_h:
7082 case Intrinsic::loongarch_lsx_vsub_w:
7083 case Intrinsic::loongarch_lsx_vsub_d:
7084 case Intrinsic::loongarch_lasx_xvsub_b:
7085 case Intrinsic::loongarch_lasx_xvsub_h:
7086 case Intrinsic::loongarch_lasx_xvsub_w:
7087 case Intrinsic::loongarch_lasx_xvsub_d:
7090 case Intrinsic::loongarch_lsx_vsubi_bu:
7091 case Intrinsic::loongarch_lsx_vsubi_hu:
7092 case Intrinsic::loongarch_lsx_vsubi_wu:
7093 case Intrinsic::loongarch_lsx_vsubi_du:
7094 case Intrinsic::loongarch_lasx_xvsubi_bu:
7095 case Intrinsic::loongarch_lasx_xvsubi_hu:
7096 case Intrinsic::loongarch_lasx_xvsubi_wu:
7097 case Intrinsic::loongarch_lasx_xvsubi_du:
7100 case Intrinsic::loongarch_lsx_vneg_b:
7101 case Intrinsic::loongarch_lsx_vneg_h:
7102 case Intrinsic::loongarch_lsx_vneg_w:
7103 case Intrinsic::loongarch_lsx_vneg_d:
7104 case Intrinsic::loongarch_lasx_xvneg_b:
7105 case Intrinsic::loongarch_lasx_xvneg_h:
7106 case Intrinsic::loongarch_lasx_xvneg_w:
7107 case Intrinsic::loongarch_lasx_xvneg_d:
7111 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7113 SDLoc(
N),
N->getValueType(0)),
7115 case Intrinsic::loongarch_lsx_vmax_b:
7116 case Intrinsic::loongarch_lsx_vmax_h:
7117 case Intrinsic::loongarch_lsx_vmax_w:
7118 case Intrinsic::loongarch_lsx_vmax_d:
7119 case Intrinsic::loongarch_lasx_xvmax_b:
7120 case Intrinsic::loongarch_lasx_xvmax_h:
7121 case Intrinsic::loongarch_lasx_xvmax_w:
7122 case Intrinsic::loongarch_lasx_xvmax_d:
7125 case Intrinsic::loongarch_lsx_vmax_bu:
7126 case Intrinsic::loongarch_lsx_vmax_hu:
7127 case Intrinsic::loongarch_lsx_vmax_wu:
7128 case Intrinsic::loongarch_lsx_vmax_du:
7129 case Intrinsic::loongarch_lasx_xvmax_bu:
7130 case Intrinsic::loongarch_lasx_xvmax_hu:
7131 case Intrinsic::loongarch_lasx_xvmax_wu:
7132 case Intrinsic::loongarch_lasx_xvmax_du:
7135 case Intrinsic::loongarch_lsx_vmaxi_b:
7136 case Intrinsic::loongarch_lsx_vmaxi_h:
7137 case Intrinsic::loongarch_lsx_vmaxi_w:
7138 case Intrinsic::loongarch_lsx_vmaxi_d:
7139 case Intrinsic::loongarch_lasx_xvmaxi_b:
7140 case Intrinsic::loongarch_lasx_xvmaxi_h:
7141 case Intrinsic::loongarch_lasx_xvmaxi_w:
7142 case Intrinsic::loongarch_lasx_xvmaxi_d:
7145 case Intrinsic::loongarch_lsx_vmaxi_bu:
7146 case Intrinsic::loongarch_lsx_vmaxi_hu:
7147 case Intrinsic::loongarch_lsx_vmaxi_wu:
7148 case Intrinsic::loongarch_lsx_vmaxi_du:
7149 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7150 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7151 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7152 case Intrinsic::loongarch_lasx_xvmaxi_du:
7155 case Intrinsic::loongarch_lsx_vmin_b:
7156 case Intrinsic::loongarch_lsx_vmin_h:
7157 case Intrinsic::loongarch_lsx_vmin_w:
7158 case Intrinsic::loongarch_lsx_vmin_d:
7159 case Intrinsic::loongarch_lasx_xvmin_b:
7160 case Intrinsic::loongarch_lasx_xvmin_h:
7161 case Intrinsic::loongarch_lasx_xvmin_w:
7162 case Intrinsic::loongarch_lasx_xvmin_d:
7165 case Intrinsic::loongarch_lsx_vmin_bu:
7166 case Intrinsic::loongarch_lsx_vmin_hu:
7167 case Intrinsic::loongarch_lsx_vmin_wu:
7168 case Intrinsic::loongarch_lsx_vmin_du:
7169 case Intrinsic::loongarch_lasx_xvmin_bu:
7170 case Intrinsic::loongarch_lasx_xvmin_hu:
7171 case Intrinsic::loongarch_lasx_xvmin_wu:
7172 case Intrinsic::loongarch_lasx_xvmin_du:
7175 case Intrinsic::loongarch_lsx_vmini_b:
7176 case Intrinsic::loongarch_lsx_vmini_h:
7177 case Intrinsic::loongarch_lsx_vmini_w:
7178 case Intrinsic::loongarch_lsx_vmini_d:
7179 case Intrinsic::loongarch_lasx_xvmini_b:
7180 case Intrinsic::loongarch_lasx_xvmini_h:
7181 case Intrinsic::loongarch_lasx_xvmini_w:
7182 case Intrinsic::loongarch_lasx_xvmini_d:
7185 case Intrinsic::loongarch_lsx_vmini_bu:
7186 case Intrinsic::loongarch_lsx_vmini_hu:
7187 case Intrinsic::loongarch_lsx_vmini_wu:
7188 case Intrinsic::loongarch_lsx_vmini_du:
7189 case Intrinsic::loongarch_lasx_xvmini_bu:
7190 case Intrinsic::loongarch_lasx_xvmini_hu:
7191 case Intrinsic::loongarch_lasx_xvmini_wu:
7192 case Intrinsic::loongarch_lasx_xvmini_du:
7195 case Intrinsic::loongarch_lsx_vmul_b:
7196 case Intrinsic::loongarch_lsx_vmul_h:
7197 case Intrinsic::loongarch_lsx_vmul_w:
7198 case Intrinsic::loongarch_lsx_vmul_d:
7199 case Intrinsic::loongarch_lasx_xvmul_b:
7200 case Intrinsic::loongarch_lasx_xvmul_h:
7201 case Intrinsic::loongarch_lasx_xvmul_w:
7202 case Intrinsic::loongarch_lasx_xvmul_d:
7205 case Intrinsic::loongarch_lsx_vmadd_b:
7206 case Intrinsic::loongarch_lsx_vmadd_h:
7207 case Intrinsic::loongarch_lsx_vmadd_w:
7208 case Intrinsic::loongarch_lsx_vmadd_d:
7209 case Intrinsic::loongarch_lasx_xvmadd_b:
7210 case Intrinsic::loongarch_lasx_xvmadd_h:
7211 case Intrinsic::loongarch_lasx_xvmadd_w:
7212 case Intrinsic::loongarch_lasx_xvmadd_d: {
7213 EVT ResTy =
N->getValueType(0);
7218 case Intrinsic::loongarch_lsx_vmsub_b:
7219 case Intrinsic::loongarch_lsx_vmsub_h:
7220 case Intrinsic::loongarch_lsx_vmsub_w:
7221 case Intrinsic::loongarch_lsx_vmsub_d:
7222 case Intrinsic::loongarch_lasx_xvmsub_b:
7223 case Intrinsic::loongarch_lasx_xvmsub_h:
7224 case Intrinsic::loongarch_lasx_xvmsub_w:
7225 case Intrinsic::loongarch_lasx_xvmsub_d: {
7226 EVT ResTy =
N->getValueType(0);
7231 case Intrinsic::loongarch_lsx_vdiv_b:
7232 case Intrinsic::loongarch_lsx_vdiv_h:
7233 case Intrinsic::loongarch_lsx_vdiv_w:
7234 case Intrinsic::loongarch_lsx_vdiv_d:
7235 case Intrinsic::loongarch_lasx_xvdiv_b:
7236 case Intrinsic::loongarch_lasx_xvdiv_h:
7237 case Intrinsic::loongarch_lasx_xvdiv_w:
7238 case Intrinsic::loongarch_lasx_xvdiv_d:
7241 case Intrinsic::loongarch_lsx_vdiv_bu:
7242 case Intrinsic::loongarch_lsx_vdiv_hu:
7243 case Intrinsic::loongarch_lsx_vdiv_wu:
7244 case Intrinsic::loongarch_lsx_vdiv_du:
7245 case Intrinsic::loongarch_lasx_xvdiv_bu:
7246 case Intrinsic::loongarch_lasx_xvdiv_hu:
7247 case Intrinsic::loongarch_lasx_xvdiv_wu:
7248 case Intrinsic::loongarch_lasx_xvdiv_du:
7251 case Intrinsic::loongarch_lsx_vmod_b:
7252 case Intrinsic::loongarch_lsx_vmod_h:
7253 case Intrinsic::loongarch_lsx_vmod_w:
7254 case Intrinsic::loongarch_lsx_vmod_d:
7255 case Intrinsic::loongarch_lasx_xvmod_b:
7256 case Intrinsic::loongarch_lasx_xvmod_h:
7257 case Intrinsic::loongarch_lasx_xvmod_w:
7258 case Intrinsic::loongarch_lasx_xvmod_d:
7261 case Intrinsic::loongarch_lsx_vmod_bu:
7262 case Intrinsic::loongarch_lsx_vmod_hu:
7263 case Intrinsic::loongarch_lsx_vmod_wu:
7264 case Intrinsic::loongarch_lsx_vmod_du:
7265 case Intrinsic::loongarch_lasx_xvmod_bu:
7266 case Intrinsic::loongarch_lasx_xvmod_hu:
7267 case Intrinsic::loongarch_lasx_xvmod_wu:
7268 case Intrinsic::loongarch_lasx_xvmod_du:
7271 case Intrinsic::loongarch_lsx_vand_v:
7272 case Intrinsic::loongarch_lasx_xvand_v:
7275 case Intrinsic::loongarch_lsx_vor_v:
7276 case Intrinsic::loongarch_lasx_xvor_v:
7279 case Intrinsic::loongarch_lsx_vxor_v:
7280 case Intrinsic::loongarch_lasx_xvxor_v:
7283 case Intrinsic::loongarch_lsx_vnor_v:
7284 case Intrinsic::loongarch_lasx_xvnor_v: {
7289 case Intrinsic::loongarch_lsx_vandi_b:
7290 case Intrinsic::loongarch_lasx_xvandi_b:
7293 case Intrinsic::loongarch_lsx_vori_b:
7294 case Intrinsic::loongarch_lasx_xvori_b:
7297 case Intrinsic::loongarch_lsx_vxori_b:
7298 case Intrinsic::loongarch_lasx_xvxori_b:
7301 case Intrinsic::loongarch_lsx_vsll_b:
7302 case Intrinsic::loongarch_lsx_vsll_h:
7303 case Intrinsic::loongarch_lsx_vsll_w:
7304 case Intrinsic::loongarch_lsx_vsll_d:
7305 case Intrinsic::loongarch_lasx_xvsll_b:
7306 case Intrinsic::loongarch_lasx_xvsll_h:
7307 case Intrinsic::loongarch_lasx_xvsll_w:
7308 case Intrinsic::loongarch_lasx_xvsll_d:
7311 case Intrinsic::loongarch_lsx_vslli_b:
7312 case Intrinsic::loongarch_lasx_xvslli_b:
7315 case Intrinsic::loongarch_lsx_vslli_h:
7316 case Intrinsic::loongarch_lasx_xvslli_h:
7319 case Intrinsic::loongarch_lsx_vslli_w:
7320 case Intrinsic::loongarch_lasx_xvslli_w:
7323 case Intrinsic::loongarch_lsx_vslli_d:
7324 case Intrinsic::loongarch_lasx_xvslli_d:
7327 case Intrinsic::loongarch_lsx_vsrl_b:
7328 case Intrinsic::loongarch_lsx_vsrl_h:
7329 case Intrinsic::loongarch_lsx_vsrl_w:
7330 case Intrinsic::loongarch_lsx_vsrl_d:
7331 case Intrinsic::loongarch_lasx_xvsrl_b:
7332 case Intrinsic::loongarch_lasx_xvsrl_h:
7333 case Intrinsic::loongarch_lasx_xvsrl_w:
7334 case Intrinsic::loongarch_lasx_xvsrl_d:
7337 case Intrinsic::loongarch_lsx_vsrli_b:
7338 case Intrinsic::loongarch_lasx_xvsrli_b:
7341 case Intrinsic::loongarch_lsx_vsrli_h:
7342 case Intrinsic::loongarch_lasx_xvsrli_h:
7345 case Intrinsic::loongarch_lsx_vsrli_w:
7346 case Intrinsic::loongarch_lasx_xvsrli_w:
7349 case Intrinsic::loongarch_lsx_vsrli_d:
7350 case Intrinsic::loongarch_lasx_xvsrli_d:
7353 case Intrinsic::loongarch_lsx_vsra_b:
7354 case Intrinsic::loongarch_lsx_vsra_h:
7355 case Intrinsic::loongarch_lsx_vsra_w:
7356 case Intrinsic::loongarch_lsx_vsra_d:
7357 case Intrinsic::loongarch_lasx_xvsra_b:
7358 case Intrinsic::loongarch_lasx_xvsra_h:
7359 case Intrinsic::loongarch_lasx_xvsra_w:
7360 case Intrinsic::loongarch_lasx_xvsra_d:
7363 case Intrinsic::loongarch_lsx_vsrai_b:
7364 case Intrinsic::loongarch_lasx_xvsrai_b:
7367 case Intrinsic::loongarch_lsx_vsrai_h:
7368 case Intrinsic::loongarch_lasx_xvsrai_h:
7371 case Intrinsic::loongarch_lsx_vsrai_w:
7372 case Intrinsic::loongarch_lasx_xvsrai_w:
7375 case Intrinsic::loongarch_lsx_vsrai_d:
7376 case Intrinsic::loongarch_lasx_xvsrai_d:
7379 case Intrinsic::loongarch_lsx_vclz_b:
7380 case Intrinsic::loongarch_lsx_vclz_h:
7381 case Intrinsic::loongarch_lsx_vclz_w:
7382 case Intrinsic::loongarch_lsx_vclz_d:
7383 case Intrinsic::loongarch_lasx_xvclz_b:
7384 case Intrinsic::loongarch_lasx_xvclz_h:
7385 case Intrinsic::loongarch_lasx_xvclz_w:
7386 case Intrinsic::loongarch_lasx_xvclz_d:
7388 case Intrinsic::loongarch_lsx_vpcnt_b:
7389 case Intrinsic::loongarch_lsx_vpcnt_h:
7390 case Intrinsic::loongarch_lsx_vpcnt_w:
7391 case Intrinsic::loongarch_lsx_vpcnt_d:
7392 case Intrinsic::loongarch_lasx_xvpcnt_b:
7393 case Intrinsic::loongarch_lasx_xvpcnt_h:
7394 case Intrinsic::loongarch_lasx_xvpcnt_w:
7395 case Intrinsic::loongarch_lasx_xvpcnt_d:
7397 case Intrinsic::loongarch_lsx_vbitclr_b:
7398 case Intrinsic::loongarch_lsx_vbitclr_h:
7399 case Intrinsic::loongarch_lsx_vbitclr_w:
7400 case Intrinsic::loongarch_lsx_vbitclr_d:
7401 case Intrinsic::loongarch_lasx_xvbitclr_b:
7402 case Intrinsic::loongarch_lasx_xvbitclr_h:
7403 case Intrinsic::loongarch_lasx_xvbitclr_w:
7404 case Intrinsic::loongarch_lasx_xvbitclr_d:
7406 case Intrinsic::loongarch_lsx_vbitclri_b:
7407 case Intrinsic::loongarch_lasx_xvbitclri_b:
7409 case Intrinsic::loongarch_lsx_vbitclri_h:
7410 case Intrinsic::loongarch_lasx_xvbitclri_h:
7412 case Intrinsic::loongarch_lsx_vbitclri_w:
7413 case Intrinsic::loongarch_lasx_xvbitclri_w:
7415 case Intrinsic::loongarch_lsx_vbitclri_d:
7416 case Intrinsic::loongarch_lasx_xvbitclri_d:
7418 case Intrinsic::loongarch_lsx_vbitset_b:
7419 case Intrinsic::loongarch_lsx_vbitset_h:
7420 case Intrinsic::loongarch_lsx_vbitset_w:
7421 case Intrinsic::loongarch_lsx_vbitset_d:
7422 case Intrinsic::loongarch_lasx_xvbitset_b:
7423 case Intrinsic::loongarch_lasx_xvbitset_h:
7424 case Intrinsic::loongarch_lasx_xvbitset_w:
7425 case Intrinsic::loongarch_lasx_xvbitset_d: {
7426 EVT VecTy =
N->getValueType(0);
7432 case Intrinsic::loongarch_lsx_vbitseti_b:
7433 case Intrinsic::loongarch_lasx_xvbitseti_b:
7435 case Intrinsic::loongarch_lsx_vbitseti_h:
7436 case Intrinsic::loongarch_lasx_xvbitseti_h:
7438 case Intrinsic::loongarch_lsx_vbitseti_w:
7439 case Intrinsic::loongarch_lasx_xvbitseti_w:
7441 case Intrinsic::loongarch_lsx_vbitseti_d:
7442 case Intrinsic::loongarch_lasx_xvbitseti_d:
7444 case Intrinsic::loongarch_lsx_vbitrev_b:
7445 case Intrinsic::loongarch_lsx_vbitrev_h:
7446 case Intrinsic::loongarch_lsx_vbitrev_w:
7447 case Intrinsic::loongarch_lsx_vbitrev_d:
7448 case Intrinsic::loongarch_lasx_xvbitrev_b:
7449 case Intrinsic::loongarch_lasx_xvbitrev_h:
7450 case Intrinsic::loongarch_lasx_xvbitrev_w:
7451 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7452 EVT VecTy =
N->getValueType(0);
7458 case Intrinsic::loongarch_lsx_vbitrevi_b:
7459 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7461 case Intrinsic::loongarch_lsx_vbitrevi_h:
7462 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7464 case Intrinsic::loongarch_lsx_vbitrevi_w:
7465 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7467 case Intrinsic::loongarch_lsx_vbitrevi_d:
7468 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7470 case Intrinsic::loongarch_lsx_vfadd_s:
7471 case Intrinsic::loongarch_lsx_vfadd_d:
7472 case Intrinsic::loongarch_lasx_xvfadd_s:
7473 case Intrinsic::loongarch_lasx_xvfadd_d:
7476 case Intrinsic::loongarch_lsx_vfsub_s:
7477 case Intrinsic::loongarch_lsx_vfsub_d:
7478 case Intrinsic::loongarch_lasx_xvfsub_s:
7479 case Intrinsic::loongarch_lasx_xvfsub_d:
7482 case Intrinsic::loongarch_lsx_vfmul_s:
7483 case Intrinsic::loongarch_lsx_vfmul_d:
7484 case Intrinsic::loongarch_lasx_xvfmul_s:
7485 case Intrinsic::loongarch_lasx_xvfmul_d:
7488 case Intrinsic::loongarch_lsx_vfdiv_s:
7489 case Intrinsic::loongarch_lsx_vfdiv_d:
7490 case Intrinsic::loongarch_lasx_xvfdiv_s:
7491 case Intrinsic::loongarch_lasx_xvfdiv_d:
7494 case Intrinsic::loongarch_lsx_vfmadd_s:
7495 case Intrinsic::loongarch_lsx_vfmadd_d:
7496 case Intrinsic::loongarch_lasx_xvfmadd_s:
7497 case Intrinsic::loongarch_lasx_xvfmadd_d:
7499 N->getOperand(2),
N->getOperand(3));
7500 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7502 N->getOperand(1),
N->getOperand(2),
7504 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7505 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7507 N->getOperand(1),
N->getOperand(2),
7509 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7510 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7512 N->getOperand(1),
N->getOperand(2),
7514 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7516 N->getOperand(1),
N->getOperand(2),
7518 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7519 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7520 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7521 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7522 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7523 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7524 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7525 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7526 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7529 case Intrinsic::loongarch_lsx_vreplve_b:
7530 case Intrinsic::loongarch_lsx_vreplve_h:
7531 case Intrinsic::loongarch_lsx_vreplve_w:
7532 case Intrinsic::loongarch_lsx_vreplve_d:
7533 case Intrinsic::loongarch_lasx_xvreplve_b:
7534 case Intrinsic::loongarch_lasx_xvreplve_h:
7535 case Intrinsic::loongarch_lasx_xvreplve_w:
7536 case Intrinsic::loongarch_lasx_xvreplve_d:
7537 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7541 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7545 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7546 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7550 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7554 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7558 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
7559 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
7563 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
7567 case Intrinsic::loongarch_lsx_bz_b:
7568 case Intrinsic::loongarch_lsx_bz_h:
7569 case Intrinsic::loongarch_lsx_bz_w:
7570 case Intrinsic::loongarch_lsx_bz_d:
7571 case Intrinsic::loongarch_lasx_xbz_b:
7572 case Intrinsic::loongarch_lasx_xbz_h:
7573 case Intrinsic::loongarch_lasx_xbz_w:
7574 case Intrinsic::loongarch_lasx_xbz_d:
7576 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
7579 case Intrinsic::loongarch_lsx_bz_v:
7580 case Intrinsic::loongarch_lasx_xbz_v:
7582 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7585 case Intrinsic::loongarch_lsx_bnz_b:
7586 case Intrinsic::loongarch_lsx_bnz_h:
7587 case Intrinsic::loongarch_lsx_bnz_w:
7588 case Intrinsic::loongarch_lsx_bnz_d:
7589 case Intrinsic::loongarch_lasx_xbnz_b:
7590 case Intrinsic::loongarch_lasx_xbnz_h:
7591 case Intrinsic::loongarch_lasx_xbnz_w:
7592 case Intrinsic::loongarch_lasx_xbnz_d:
7594 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7597 case Intrinsic::loongarch_lsx_bnz_v:
7598 case Intrinsic::loongarch_lasx_xbnz_v:
7600 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7603 case Intrinsic::loongarch_lasx_concat_128_s:
7604 case Intrinsic::loongarch_lasx_concat_128_d:
7605 case Intrinsic::loongarch_lasx_concat_128:
7607 N->getOperand(1),
N->getOperand(2));
7619 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
7631 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
7633 "Unexpected value type!");
7642 MVT VT =
N->getSimpleValueType(0);
7663 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
7676 APInt V =
C->getValueAPF().bitcastToAPInt();
7691 MVT VT =
N->getSimpleValueType(0);
7752 EVT VT =
N->getValueType(0);
7754 if (VT != MVT::f32 && VT != MVT::f64)
7756 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7758 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7781 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
7838 Subtarget.hasExtLASX() && N1.
hasOneUse())
7850 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
7860 EVT VT =
N.getValueType();
7877 switch (
N.getOpcode()) {
7893 EVT VT =
N->getValueType(0);
7908 EVT VT =
N->getValueType(0);
7910 if (VT.
isVector() &&
N->getNumOperands() == 2)
7923 EVT VT =
N->getValueType(0);
7935 SDValue TrueVal =
N->getOperand(1);
7936 SDValue FalseVal =
N->getOperand(2);
7970 if (FalseVal.getOpcode() !=
ISD::ADD)
7973 SDValue Add0 = FalseVal.getOperand(0);
7974 SDValue Add1 = FalseVal.getOperand(1);
8044 : LoongArchISD::VSRAR,
8051 switch (
N->getOpcode()) {
8072 case LoongArchISD::BITREV_W:
8074 case LoongArchISD::BR_CC:
8076 case LoongArchISD::SELECT_CC:
8080 case LoongArchISD::MOVGR2FR_W_LA64:
8082 case LoongArchISD::MOVFR2GR_S_LA64:
8084 case LoongArchISD::VMSKLTZ:
8085 case LoongArchISD::XVMSKLTZ:
8087 case LoongArchISD::SPLIT_PAIR_F64:
8089 case LoongArchISD::VANDN:
8095 case LoongArchISD::VPACKEV:
8096 case LoongArchISD::VPERMI:
8122 MF->
insert(It, BreakMBB);
8126 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8127 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
8139 MBB->addSuccessor(BreakMBB);
8140 MBB->addSuccessor(SinkMBB);
8146 BreakMBB->addSuccessor(SinkMBB);
8158 switch (
MI.getOpcode()) {
8161 case LoongArch::PseudoVBZ:
8162 CondOpc = LoongArch::VSETEQZ_V;
8164 case LoongArch::PseudoVBZ_B:
8165 CondOpc = LoongArch::VSETANYEQZ_B;
8167 case LoongArch::PseudoVBZ_H:
8168 CondOpc = LoongArch::VSETANYEQZ_H;
8170 case LoongArch::PseudoVBZ_W:
8171 CondOpc = LoongArch::VSETANYEQZ_W;
8173 case LoongArch::PseudoVBZ_D:
8174 CondOpc = LoongArch::VSETANYEQZ_D;
8176 case LoongArch::PseudoVBNZ:
8177 CondOpc = LoongArch::VSETNEZ_V;
8179 case LoongArch::PseudoVBNZ_B:
8180 CondOpc = LoongArch::VSETALLNEZ_B;
8182 case LoongArch::PseudoVBNZ_H:
8183 CondOpc = LoongArch::VSETALLNEZ_H;
8185 case LoongArch::PseudoVBNZ_W:
8186 CondOpc = LoongArch::VSETALLNEZ_W;
8188 case LoongArch::PseudoVBNZ_D:
8189 CondOpc = LoongArch::VSETALLNEZ_D;
8191 case LoongArch::PseudoXVBZ:
8192 CondOpc = LoongArch::XVSETEQZ_V;
8194 case LoongArch::PseudoXVBZ_B:
8195 CondOpc = LoongArch::XVSETANYEQZ_B;
8197 case LoongArch::PseudoXVBZ_H:
8198 CondOpc = LoongArch::XVSETANYEQZ_H;
8200 case LoongArch::PseudoXVBZ_W:
8201 CondOpc = LoongArch::XVSETANYEQZ_W;
8203 case LoongArch::PseudoXVBZ_D:
8204 CondOpc = LoongArch::XVSETANYEQZ_D;
8206 case LoongArch::PseudoXVBNZ:
8207 CondOpc = LoongArch::XVSETNEZ_V;
8209 case LoongArch::PseudoXVBNZ_B:
8210 CondOpc = LoongArch::XVSETALLNEZ_B;
8212 case LoongArch::PseudoXVBNZ_H:
8213 CondOpc = LoongArch::XVSETALLNEZ_H;
8215 case LoongArch::PseudoXVBNZ_W:
8216 CondOpc = LoongArch::XVSETALLNEZ_W;
8218 case LoongArch::PseudoXVBNZ_D:
8219 CondOpc = LoongArch::XVSETALLNEZ_D;
8234 F->insert(It, FalseBB);
8235 F->insert(It, TrueBB);
8236 F->insert(It, SinkBB);
8239 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
8268 MI.getOperand(0).getReg())
8275 MI.eraseFromParent();
8283 unsigned BroadcastOp;
8285 switch (
MI.getOpcode()) {
8288 case LoongArch::PseudoXVINSGR2VR_B:
8290 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8291 InsOp = LoongArch::XVEXTRINS_B;
8293 case LoongArch::PseudoXVINSGR2VR_H:
8295 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8296 InsOp = LoongArch::XVEXTRINS_H;
8308 unsigned Idx =
MI.getOperand(3).getImm();
8316 .
addReg(XSrc, {}, LoongArch::sub_128);
8318 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8319 : LoongArch::VINSGR2VR_B),
8327 .
addImm(LoongArch::sub_128);
8334 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8337 .
addImm(Idx >= HalfSize ? 48 : 18);
8342 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8345 MI.eraseFromParent();
8352 assert(Subtarget.hasExtLSX());
8360 unsigned BroadcastOp, CTOp, PickOp;
8361 switch (
MI.getOpcode()) {
8364 case LoongArch::PseudoCTPOP_B:
8365 BroadcastOp = LoongArch::VREPLGR2VR_B;
8366 CTOp = LoongArch::VPCNT_B;
8367 PickOp = LoongArch::VPICKVE2GR_B;
8369 case LoongArch::PseudoCTPOP_H:
8370 case LoongArch::PseudoCTPOP_H_LA32:
8371 BroadcastOp = LoongArch::VREPLGR2VR_H;
8372 CTOp = LoongArch::VPCNT_H;
8373 PickOp = LoongArch::VPICKVE2GR_H;
8375 case LoongArch::PseudoCTPOP_W:
8376 case LoongArch::PseudoCTPOP_W_LA32:
8377 BroadcastOp = LoongArch::VREPLGR2VR_W;
8378 CTOp = LoongArch::VPCNT_W;
8379 PickOp = LoongArch::VPICKVE2GR_W;
8381 case LoongArch::PseudoCTPOP_D:
8382 BroadcastOp = LoongArch::VREPLGR2VR_D;
8383 CTOp = LoongArch::VPCNT_D;
8384 PickOp = LoongArch::VPICKVE2GR_D;
8394 MI.eraseFromParent();
8408 unsigned EleBits = 8;
8409 unsigned NotOpc = 0;
8412 switch (
MI.getOpcode()) {
8415 case LoongArch::PseudoVMSKLTZ_B:
8416 MskOpc = LoongArch::VMSKLTZ_B;
8418 case LoongArch::PseudoVMSKLTZ_H:
8419 MskOpc = LoongArch::VMSKLTZ_H;
8422 case LoongArch::PseudoVMSKLTZ_W:
8423 MskOpc = LoongArch::VMSKLTZ_W;
8426 case LoongArch::PseudoVMSKLTZ_D:
8427 MskOpc = LoongArch::VMSKLTZ_D;
8430 case LoongArch::PseudoVMSKGEZ_B:
8431 MskOpc = LoongArch::VMSKGEZ_B;
8433 case LoongArch::PseudoVMSKEQZ_B:
8434 MskOpc = LoongArch::VMSKNZ_B;
8435 NotOpc = LoongArch::VNOR_V;
8437 case LoongArch::PseudoVMSKNEZ_B:
8438 MskOpc = LoongArch::VMSKNZ_B;
8440 case LoongArch::PseudoXVMSKLTZ_B:
8441 MskOpc = LoongArch::XVMSKLTZ_B;
8442 RC = &LoongArch::LASX256RegClass;
8444 case LoongArch::PseudoXVMSKLTZ_H:
8445 MskOpc = LoongArch::XVMSKLTZ_H;
8446 RC = &LoongArch::LASX256RegClass;
8449 case LoongArch::PseudoXVMSKLTZ_W:
8450 MskOpc = LoongArch::XVMSKLTZ_W;
8451 RC = &LoongArch::LASX256RegClass;
8454 case LoongArch::PseudoXVMSKLTZ_D:
8455 MskOpc = LoongArch::XVMSKLTZ_D;
8456 RC = &LoongArch::LASX256RegClass;
8459 case LoongArch::PseudoXVMSKGEZ_B:
8460 MskOpc = LoongArch::XVMSKGEZ_B;
8461 RC = &LoongArch::LASX256RegClass;
8463 case LoongArch::PseudoXVMSKEQZ_B:
8464 MskOpc = LoongArch::XVMSKNZ_B;
8465 NotOpc = LoongArch::XVNOR_V;
8466 RC = &LoongArch::LASX256RegClass;
8468 case LoongArch::PseudoXVMSKNEZ_B:
8469 MskOpc = LoongArch::XVMSKNZ_B;
8470 RC = &LoongArch::LASX256RegClass;
8485 if (
TRI->getRegSizeInBits(*RC) > 128) {
8495 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
8496 : LoongArch::BSTRINS_W),
8500 .
addImm(256 / EleBits - 1)
8508 MI.eraseFromParent();
8515 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
8516 "Unexpected instruction");
8528 MI.eraseFromParent();
8535 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
8536 "Unexpected instruction");
8552 MI.eraseFromParent();
8557 switch (
MI.getOpcode()) {
8560 case LoongArch::Select_GPR_Using_CC_GPR:
8596 if (
MI.getOperand(2).isReg())
8597 RHS =
MI.getOperand(2).getReg();
8598 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
8602 SelectDests.
insert(
MI.getOperand(0).getReg());
8606 SequenceMBBI !=
E; ++SequenceMBBI) {
8607 if (SequenceMBBI->isDebugInstr())
8610 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
8611 !SequenceMBBI->getOperand(2).isReg() ||
8612 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
8613 SequenceMBBI->getOperand(3).getImm() != CC ||
8614 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
8615 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
8617 LastSelectPseudo = &*SequenceMBBI;
8619 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
8622 if (SequenceMBBI->hasUnmodeledSideEffects() ||
8623 SequenceMBBI->mayLoadOrStore() ||
8624 SequenceMBBI->usesCustomInsertionHook())
8627 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
8642 F->insert(
I, IfFalseMBB);
8643 F->insert(
I, TailMBB);
8646 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
8652 TailMBB->
push_back(DebugInstr->removeFromParent());
8656 TailMBB->
splice(TailMBB->
end(), HeadMBB,
8666 if (
MI.getOperand(2).isImm())
8678 auto SelectMBBI =
MI.getIterator();
8679 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
8681 while (SelectMBBI != SelectEnd) {
8682 auto Next = std::next(SelectMBBI);
8686 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
8687 .
addReg(SelectMBBI->getOperand(4).getReg())
8689 .
addReg(SelectMBBI->getOperand(5).getReg())
8696 F->getProperties().resetNoPHIs();
8702 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
8705 switch (
MI.getOpcode()) {
8708 case LoongArch::DIV_W:
8709 case LoongArch::DIV_WU:
8710 case LoongArch::MOD_W:
8711 case LoongArch::MOD_WU:
8712 case LoongArch::DIV_D:
8713 case LoongArch::DIV_DU:
8714 case LoongArch::MOD_D:
8715 case LoongArch::MOD_DU:
8718 case LoongArch::WRFCSR: {
8720 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
8721 .
addReg(
MI.getOperand(1).getReg());
8722 MI.eraseFromParent();
8725 case LoongArch::RDFCSR: {
8726 MachineInstr *ReadFCSR =
8728 MI.getOperand(0).getReg())
8729 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
8731 MI.eraseFromParent();
8734 case LoongArch::Select_GPR_Using_CC_GPR:
8736 case LoongArch::BuildPairF64Pseudo:
8738 case LoongArch::SplitPairF64Pseudo:
8740 case LoongArch::PseudoVBZ:
8741 case LoongArch::PseudoVBZ_B:
8742 case LoongArch::PseudoVBZ_H:
8743 case LoongArch::PseudoVBZ_W:
8744 case LoongArch::PseudoVBZ_D:
8745 case LoongArch::PseudoVBNZ:
8746 case LoongArch::PseudoVBNZ_B:
8747 case LoongArch::PseudoVBNZ_H:
8748 case LoongArch::PseudoVBNZ_W:
8749 case LoongArch::PseudoVBNZ_D:
8750 case LoongArch::PseudoXVBZ:
8751 case LoongArch::PseudoXVBZ_B:
8752 case LoongArch::PseudoXVBZ_H:
8753 case LoongArch::PseudoXVBZ_W:
8754 case LoongArch::PseudoXVBZ_D:
8755 case LoongArch::PseudoXVBNZ:
8756 case LoongArch::PseudoXVBNZ_B:
8757 case LoongArch::PseudoXVBNZ_H:
8758 case LoongArch::PseudoXVBNZ_W:
8759 case LoongArch::PseudoXVBNZ_D:
8761 case LoongArch::PseudoXVINSGR2VR_B:
8762 case LoongArch::PseudoXVINSGR2VR_H:
8764 case LoongArch::PseudoCTPOP_B:
8765 case LoongArch::PseudoCTPOP_H:
8766 case LoongArch::PseudoCTPOP_W:
8767 case LoongArch::PseudoCTPOP_D:
8768 case LoongArch::PseudoCTPOP_H_LA32:
8769 case LoongArch::PseudoCTPOP_W_LA32:
8771 case LoongArch::PseudoVMSKLTZ_B:
8772 case LoongArch::PseudoVMSKLTZ_H:
8773 case LoongArch::PseudoVMSKLTZ_W:
8774 case LoongArch::PseudoVMSKLTZ_D:
8775 case LoongArch::PseudoVMSKGEZ_B:
8776 case LoongArch::PseudoVMSKEQZ_B:
8777 case LoongArch::PseudoVMSKNEZ_B:
8778 case LoongArch::PseudoXVMSKLTZ_B:
8779 case LoongArch::PseudoXVMSKLTZ_H:
8780 case LoongArch::PseudoXVMSKLTZ_W:
8781 case LoongArch::PseudoXVMSKLTZ_D:
8782 case LoongArch::PseudoXVMSKGEZ_B:
8783 case LoongArch::PseudoXVMSKEQZ_B:
8784 case LoongArch::PseudoXVMSKNEZ_B:
8786 case TargetOpcode::STATEPOINT:
8792 MI.addOperand(*
MI.getMF(),
8794 LoongArch::R1,
true,
8797 if (!Subtarget.is64Bit())
8800 case LoongArch::PROBED_STACKALLOC_DYN:
8807 unsigned *
Fast)
const {
8808 if (!Subtarget.hasUAL())
8826 LoongArch::R7, LoongArch::R8, LoongArch::R9,
8827 LoongArch::R10, LoongArch::R11};
8842 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
8843 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
8844 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
8845 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
8846 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
8847 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
8853 LoongArch::F3, LoongArch::F4, LoongArch::F5,
8854 LoongArch::F6, LoongArch::F7};
8857 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
8858 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
8861 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
8862 LoongArch::VR6, LoongArch::VR7};
8865 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
8866 LoongArch::XR6, LoongArch::XR7};
8869 switch (State.getCallingConv()) {
8871 if (!State.isVarArg())
8875 return State.AllocateReg(
ArgGPRs);
8883 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
8885 unsigned GRLenInBytes = GRLen / 8;
8896 State.AllocateStack(GRLenInBytes, StackAlign),
8899 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8910 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8918 unsigned ValNo,
MVT ValVT,
8921 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
8922 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
8923 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
8928 if (IsRet && ValNo > 1)
8932 bool UseGPRForFloat =
true;
8942 UseGPRForFloat = ArgFlags.
isVarArg();
8955 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
8958 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
8959 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
8961 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
8967 State.getPendingArgFlags();
8970 "PendingLocs and PendingArgFlags out of sync");
8974 UseGPRForFloat =
true;
8976 if (UseGPRForFloat && ValVT == MVT::f32) {
8979 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
8982 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
8985 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9027 PendingLocs.
size() <= 2) {
9028 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9033 PendingLocs.
clear();
9034 PendingArgFlags.
clear();
9041 unsigned StoreSizeBytes = GRLen / 8;
9044 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9046 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9050 UseGPRForFloat =
false;
9051 StoreSizeBytes = 16;
9052 StackAlign =
Align(16);
9055 UseGPRForFloat =
false;
9056 StoreSizeBytes = 32;
9057 StackAlign =
Align(32);
9063 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9067 if (!PendingLocs.
empty()) {
9069 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9070 for (
auto &It : PendingLocs) {
9072 It.convertToReg(
Reg);
9077 PendingLocs.clear();
9078 PendingArgFlags.
clear();
9081 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9082 "Expected an GRLenVT at this stage");
9099void LoongArchTargetLowering::analyzeInputArgs(
9102 LoongArchCCAssignFn Fn)
const {
9104 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9105 MVT ArgVT = Ins[i].VT;
9106 Type *ArgTy =
nullptr;
9108 ArgTy = FType->getReturnType();
9109 else if (Ins[i].isOrigArg())
9110 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9114 CCInfo, IsRet, ArgTy)) {
9115 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9122void LoongArchTargetLowering::analyzeOutputArgs(
9125 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9126 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9127 MVT ArgVT = Outs[i].VT;
9128 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
9132 CCInfo, IsRet, OrigTy)) {
9133 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
9152 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
9174 if (In.isOrigArg()) {
9179 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
9180 (
BitWidth < 32 && In.Flags.isZExt())) {
9230 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9243 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9247 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
9261 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
9273 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
9277 LoongArch::R23, LoongArch::R24, LoongArch::R25,
9278 LoongArch::R26, LoongArch::R27, LoongArch::R28,
9279 LoongArch::R29, LoongArch::R30, LoongArch::R31};
9286 if (LocVT == MVT::f32) {
9289 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9290 LoongArch::F26, LoongArch::F27};
9297 if (LocVT == MVT::f64) {
9300 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9301 LoongArch::F30_64, LoongArch::F31_64};
9332 "GHC calling convention requires the F and D extensions");
9337 MVT GRLenVT = Subtarget.getGRLenVT();
9338 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9347 return CI->isMustTailCall();
9352 std::vector<SDValue> OutChains;
9361 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9363 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
9380 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
9389 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
9390 assert(ArgPartOffset == 0);
9391 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
9393 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
9417 int VaArgOffset, VarArgsSaveSize;
9421 if (ArgRegs.
size() == Idx) {
9423 VarArgsSaveSize = 0;
9425 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
9426 VaArgOffset = -VarArgsSaveSize;
9432 LoongArchFI->setVarArgsFrameIndex(FI);
9440 VarArgsSaveSize += GRLenInBytes;
9445 for (
unsigned I = Idx;
I < ArgRegs.
size();
9446 ++
I, VaArgOffset += GRLenInBytes) {
9447 const Register Reg = RegInfo.createVirtualRegister(RC);
9448 RegInfo.addLiveIn(ArgRegs[
I], Reg);
9456 ->setValue((
Value *)
nullptr);
9457 OutChains.push_back(Store);
9459 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
9464 if (!OutChains.empty()) {
9465 OutChains.push_back(Chain);
9480 if (
N->getNumValues() != 1)
9482 if (!
N->hasNUsesOfValue(1, 0))
9485 SDNode *Copy = *
N->user_begin();
9491 if (Copy->getGluedNode())
9495 bool HasRet =
false;
9497 if (
Node->getOpcode() != LoongArchISD::RET)
9505 Chain = Copy->getOperand(0);
9510bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
9514 auto CalleeCC = CLI.CallConv;
9515 auto &Outs = CLI.Outs;
9517 auto CallerCC = Caller.getCallingConv();
9519 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
9528 for (
auto &Arg : Outs)
9529 if (Arg.Flags.isByVal())
9545 for (
auto &VA : ArgLocs)
9551 auto IsCallerStructRet = Caller.hasStructRetAttr();
9552 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
9553 if (IsCallerStructRet || IsCalleeStructRet)
9558 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
9559 if (CalleeCC != CallerCC) {
9560 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
9561 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
9587 MVT GRLenVT = Subtarget.getGRLenVT();
9599 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
9603 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
9609 "site marked musttail");
9616 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9618 if (!Flags.isByVal())
9622 unsigned Size = Flags.getByValSize();
9623 Align Alignment = Flags.getNonZeroByValAlign();
9630 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
9632 false,
nullptr, std::nullopt,
9644 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
9647 SDValue ArgValue = OutVals[OutIdx];
9655 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
9656 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
9668 if (!StackPtr.getNode())
9680 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
9694 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
9714 const Argument *FormalArg =
nullptr;
9715 unsigned FilteredIdx = 0;
9716 for (
const auto &CallArg : CLI.
CB->
args()) {
9717 if (CallArg->getType()->isEmptyTy())
9719 if (FilteredIdx == CallArgIdx) {
9728 unsigned FormalArgIdx = CallArgIdx;
9730 FormalArgIdx = FormalArg->
getArgNo();
9734 if (Arg.getType()->isEmptyTy())
9736 if (FilteredIdx == CallArgIdx) {
9737 FormalArgIdx = Arg.getArgNo();
9767 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
9768 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
9769 SDValue PartValue = OutVals[OutIdx + 1];
9770 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
9781 ArgValue = IncomingPtr;
9785 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
9797 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
9798 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
9799 assert(ArgPartOffset == 0);
9804 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
9805 SDValue PartValue = OutVals[OutIdx + 1];
9806 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
9820 for (
const auto &Part : Parts) {
9821 SDValue PartValue = Part.first;
9822 SDValue PartOffset = Part.second;
9829 ArgValue = SpillSlot;
9836 if (Flags.isByVal())
9837 ArgValue = ByValArgs[j++];
9845 "Tail call not allowed if stack is used for passing parameters");
9848 if (!StackPtr.getNode())
9861 if (!MemOpChains.
empty())
9867 for (
auto &Reg : RegsToPass) {
9868 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
9890 Ops.push_back(Chain);
9891 Ops.push_back(Callee);
9895 for (
auto &Reg : RegsToPass)
9896 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
9901 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
9902 assert(Mask &&
"Missing call preserved mask for calling convention");
9908 Ops.push_back(Glue);
9917 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
9920 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
9923 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
9924 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
9946 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
9949 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
9950 auto &VA = RVLocs[i];
9958 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
9959 assert(VA.needsCustom());
9964 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
9965 RetValue, RetValue2);
9978 const Type *RetTy)
const {
9980 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
9982 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9986 Outs[i].Flags, CCInfo,
true,
nullptr))
10012 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10013 SDValue Val = OutVals[OutIdx];
10022 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10026 Register RegHi = RVLocs[++i].getLocReg();
10051 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10059 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10062 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10064 RequiredImm = (0b10101 << 8) | (V >> 8);
10065 return {
true, RequiredImm};
10066 }
else if (SplatBitSize == 32) {
10068 if (!(V & 0xFFFF00FF)) {
10069 RequiredImm = (0b10001 << 8) | (V >> 8);
10070 return {
true, RequiredImm};
10073 if (!(V & 0xFF00FFFF)) {
10074 RequiredImm = (0b10010 << 8) | (V >> 16);
10075 return {
true, RequiredImm};
10078 if (!(V & 0x00FFFFFF)) {
10079 RequiredImm = (0b10011 << 8) | (V >> 24);
10080 return {
true, RequiredImm};
10083 if ((V & 0xFFFF00FF) == 0xFF) {
10084 RequiredImm = (0b10110 << 8) | (V >> 8);
10085 return {
true, RequiredImm};
10088 if ((V & 0xFF00FFFF) == 0xFFFF) {
10089 RequiredImm = (0b10111 << 8) | (V >> 16);
10090 return {
true, RequiredImm};
10093 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
10095 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10096 return {
true, RequiredImm};
10098 }
else if (SplatBitSize == 64) {
10100 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
10101 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
10103 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10104 return {
true, RequiredImm};
10107 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
10108 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
10110 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
10111 return {
true, RequiredImm};
10114 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
10116 for (
int i = 0; i < 8; ++i) {
10118 if (
byte == 0 ||
byte == 0xFF)
10119 res |= ((
byte & 1) << i);
10124 return {
true, res};
10126 auto [IsSame, Suffix] = sameBitsPreByte(V);
10128 RequiredImm = (0b11001 << 8) | Suffix;
10129 return {
true, RequiredImm};
10132 return {
false, RequiredImm};
10137 if (!Subtarget.hasExtLSX())
10140 if (VT == MVT::f32) {
10141 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
10142 return (masked == 0x3e000000 || masked == 0x40000000);
10145 if (VT == MVT::f64) {
10146 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
10147 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
10153bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
10154 bool ForCodeSize)
const {
10156 if (VT == MVT::f32 && !Subtarget.hasBasicF())
10158 if (VT == MVT::f64 && !Subtarget.hasBasicD())
10160 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
10171bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
10181 Type *Ty =
I->getOperand(0)->getType();
10183 unsigned Size = Ty->getIntegerBitWidth();
10203 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
10208 if (Subtarget.hasExtLASX())
10210 else if (Subtarget.hasExtLSX())
10217 EVT VT =
Y.getValueType();
10220 return Subtarget.hasExtLSX() && VT.
isInteger();
10231 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
10232 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
10233 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
10234 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
10237 Info.memVT = MVT::i32;
10238 Info.ptrVal =
I.getArgOperand(0);
10240 Info.align =
Align(4);
10259 "Unable to expand");
10260 unsigned MinWordSize = 4;
10272 Value *AlignedAddr = Builder.CreateIntrinsic(
10273 Intrinsic::ptrmask, {PtrTy, IntTy},
10274 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
10277 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
10278 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
10279 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
10280 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
10281 Value *Mask = Builder.CreateShl(
10282 ConstantInt::get(WordType,
10283 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
10285 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
10286 Value *ValOperand_Shifted =
10287 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
10288 ShiftAmt,
"ValOperand_Shifted");
10291 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
10293 NewOperand = ValOperand_Shifted;
10296 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
10299 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
10300 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
10301 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
10320 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
10328 if (Subtarget.hasLAMCAS()) {
10350 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
10352 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
10354 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
10356 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
10358 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
10360 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
10362 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
10364 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
10374 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
10376 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
10378 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
10380 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
10382 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
10384 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
10386 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
10388 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
10400 if (Subtarget.hasLAMCAS())
10412 unsigned GRLen = Subtarget.getGRLen();
10414 Value *FailureOrdering =
10415 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
10416 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
10418 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
10419 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
10420 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
10421 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10424 Value *Result = Builder.CreateIntrinsic(
10425 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
10427 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10443 Builder.CreateNot(Mask,
"Inv_Mask"),
10450 unsigned GRLen = Subtarget.getGRLen();
10459 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
10460 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10461 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
10474 unsigned ValWidth =
10477 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
10478 Result = Builder.CreateCall(LlwOpScwLoop,
10479 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
10482 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
10486 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10509 const Constant *PersonalityFn)
const {
10510 return LoongArch::R4;
10514 const Constant *PersonalityFn)
const {
10515 return LoongArch::R5;
10526 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
10527 return RefinementSteps;
10532 assert(Subtarget.hasFrecipe() &&
10533 "Reciprocal estimate queried on unsupported target");
10544 return Subtarget.hasBasicD();
10548 return Subtarget.hasExtLSX();
10552 return Subtarget.hasExtLASX();
10561 int &RefinementSteps,
10562 bool &UseOneConstNR,
10563 bool Reciprocal)
const {
10565 "Enabled should never be Disabled here");
10567 if (!Subtarget.hasFrecipe())
10582 UseOneConstNR =
false;
10588 if (Reciprocal || RefinementSteps > 0)
10598 int &RefinementSteps)
const {
10600 "Enabled should never be Disabled here");
10602 if (!Subtarget.hasFrecipe())
10616 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
10624LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
10644 if (Constraint.
size() == 1) {
10645 switch (Constraint[0]) {
10661 if (Constraint ==
"ZC" || Constraint ==
"ZB")
10670 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
10677std::pair<unsigned, const TargetRegisterClass *>
10678LoongArchTargetLowering::getRegForInlineAsmConstraint(
10682 if (Constraint.
size() == 1) {
10683 switch (Constraint[0]) {
10688 return std::make_pair(0U, &LoongArch::GPRRegClass);
10690 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
10692 if (Subtarget.hasBasicF() && VT == MVT::f32)
10693 return std::make_pair(0U, &LoongArch::FPR32RegClass);
10694 if (Subtarget.hasBasicD() && VT == MVT::f64)
10695 return std::make_pair(0U, &LoongArch::FPR64RegClass);
10696 if (Subtarget.hasExtLSX() &&
10697 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
10698 return std::make_pair(0U, &LoongArch::LSX128RegClass);
10699 if (Subtarget.hasExtLASX() &&
10700 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
10701 return std::make_pair(0U, &LoongArch::LASX256RegClass);
10721 bool IsFP = Constraint[2] ==
'f';
10722 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
10723 std::pair<unsigned, const TargetRegisterClass *>
R;
10728 unsigned RegNo =
R.first;
10729 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
10730 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
10731 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
10732 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
10742void LoongArchTargetLowering::LowerAsmOperandForConstraint(
10746 if (Constraint.
size() == 1) {
10747 switch (Constraint[0]) {
10751 uint64_t CVal =
C->getSExtValue();
10754 Subtarget.getGRLenVT()));
10760 uint64_t CVal =
C->getSExtValue();
10763 Subtarget.getGRLenVT()));
10769 if (
C->getZExtValue() == 0)
10776 uint64_t CVal =
C->getZExtValue();
10789#define GET_REGISTER_MATCHER
10790#include "LoongArchGenAsmMatcher.inc"
10796 std::string NewRegName = Name.second.str();
10802 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
10803 if (!ReservedRegs.
test(Reg))
10820 const APInt &Imm = ConstNode->getAPIntValue();
10822 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
10823 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
10826 if (ConstNode->hasOneUse() &&
10827 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
10828 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
10834 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
10835 unsigned Shifts = Imm.countr_zero();
10841 APInt ImmPop = Imm.ashr(Shifts);
10842 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
10846 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
10847 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
10848 (ImmSmall - Imm).isPowerOf2())
10858 Type *Ty,
unsigned AS,
10877 switch (AM.
Scale) {
10913 EVT MemVT = LD->getMemoryVT();
10914 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10925 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
10934 if (
Y.getValueType().isVector())
10946 Type *Ty,
bool IsSigned)
const {
10947 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
10956 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
10957 Type.getSizeInBits() < Subtarget.getGRLen()))
10967 Align &PrefAlign)
const {
10971 if (Subtarget.is64Bit()) {
10973 PrefAlign =
Align(8);
10976 PrefAlign =
Align(4);
10991bool LoongArchTargetLowering::splitValueIntoRegisterParts(
10993 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
10994 bool IsABIRegCopy = CC.has_value();
10997 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10998 PartVT == MVT::f32) {
11013SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11015 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11016 bool IsABIRegCopy = CC.has_value();
11018 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11019 PartVT == MVT::f32) {
11036 if (VT == MVT::f16 && Subtarget.hasBasicF())
11042unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11045 if (VT == MVT::f16 && Subtarget.hasBasicF())
11054 unsigned Opc =
Op.getOpcode();
11059 case LoongArchISD::VPICK_ZEXT_ELT: {
11073 unsigned Depth)
const {
11074 EVT VT =
Op.getValueType();
11076 unsigned Opc =
Op.getOpcode();
11080 case LoongArchISD::VMSKLTZ:
11081 case LoongArchISD::XVMSKLTZ: {
11083 MVT SrcVT = Src.getSimpleValueType();
11088 if (OriginalDemandedBits.
countr_zero() >= NumElts)
11092 APInt KnownUndef, KnownZero;
11108 if (KnownSrc.
One[SrcBits - 1])
11110 else if (KnownSrc.
Zero[SrcBits - 1])
11115 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
11122 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
11145 unsigned Index)
const {
11154 unsigned Index)
const {
11158 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
11173 Align StackAlign)
const {
11177 unsigned StackProbeSize =
11181 return StackProbeSize ? StackProbeSize : StackAlign.
value();
11185LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
11199 const EVT VT =
Op.getValueType();
11210 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
11220 const Register TargetReg =
MI.getOperand(0).getReg();
11223 const bool IsLA64 = Subtarget.is64Bit();
11224 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
11231 MF.
insert(MBBInsertPoint, LoopTestMBB);
11234 MF.
insert(MBBInsertPoint, ExitMBB);
11245 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
11251 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
11257 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
11272 MBB->addSuccessor(LoopTestMBB);
11274 MI.eraseFromParent();
11276 return ExitMBB->
begin()->getParent();
static MCRegister MatchRegisterName(StringRef Name)
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSELECT_CCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
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.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type count() const
Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
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 setIncomingIndirectArg(unsigned ArgIndex, Register Reg)
void addSExt32Register(Register Reg)
Register getIncomingIndirectArg(unsigned ArgIndex) const
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.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
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...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
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 getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
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)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
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.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
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 getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)