32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
250 if (Subtarget.is64Bit())
253 if (!Subtarget.hasBasicD()) {
255 if (Subtarget.is64Bit()) {
264 if (Subtarget.hasBasicD()) {
297 if (Subtarget.is64Bit())
303 if (Subtarget.hasExtLSX()) {
318 for (
MVT VT : LSXVTs) {
332 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
360 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
362 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
364 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
369 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
393 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
394 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
409 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
411 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
418 if (Subtarget.hasExtLASX()) {
419 for (
MVT VT : LASXVTs) {
434 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
463 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
465 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
467 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
472 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
491 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
497 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
501 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
506 if (Subtarget.hasBasicF()) {
523 if (Subtarget.has32S())
528 if (Subtarget.hasExtLSX()) {
543 if (Subtarget.hasExtLASX()) {
568 if (Subtarget.hasLAMCAS())
571 if (Subtarget.hasSCQ()) {
591 switch (
Op.getOpcode()) {
593 return lowerATOMIC_FENCE(
Op, DAG);
595 return lowerEH_DWARF_CFA(
Op, DAG);
597 return lowerGlobalAddress(
Op, DAG);
599 return lowerGlobalTLSAddress(
Op, DAG);
601 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
603 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
605 return lowerINTRINSIC_VOID(
Op, DAG);
607 return lowerBlockAddress(
Op, DAG);
609 return lowerJumpTable(
Op, DAG);
611 return lowerShiftLeftParts(
Op, DAG);
613 return lowerShiftRightParts(
Op, DAG,
true);
615 return lowerShiftRightParts(
Op, DAG,
false);
617 return lowerConstantPool(
Op, DAG);
619 return lowerFP_TO_SINT(
Op, DAG);
621 return lowerFP_TO_UINT(
Op, DAG);
623 return lowerBITCAST(
Op, DAG);
625 return lowerUINT_TO_FP(
Op, DAG);
627 return lowerSINT_TO_FP(
Op, DAG);
629 return lowerVASTART(
Op, DAG);
631 return lowerFRAMEADDR(
Op, DAG);
633 return lowerRETURNADDR(
Op, DAG);
635 return lowerSET_ROUNDING(
Op, DAG);
637 return lowerGET_ROUNDING(
Op, DAG);
639 return lowerWRITE_REGISTER(
Op, DAG);
641 return lowerINSERT_VECTOR_ELT(
Op, DAG);
643 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
645 return lowerBUILD_VECTOR(
Op, DAG);
647 return lowerCONCAT_VECTORS(
Op, DAG);
649 return lowerVECTOR_SHUFFLE(
Op, DAG);
651 return lowerBITREVERSE(
Op, DAG);
653 return lowerSCALAR_TO_VECTOR(
Op, DAG);
655 return lowerPREFETCH(
Op, DAG);
657 return lowerSELECT(
Op, DAG);
659 return lowerBRCOND(
Op, DAG);
661 return lowerFP_TO_FP16(
Op, DAG);
663 return lowerFP16_TO_FP(
Op, DAG);
665 return lowerFP_TO_BF16(
Op, DAG);
667 return lowerBF16_TO_FP(
Op, DAG);
669 return lowerVECREDUCE_ADD(
Op, DAG);
672 return lowerRotate(
Op, DAG);
680 return lowerVECREDUCE(
Op, DAG);
682 return lowerConstantFP(
Op, DAG);
684 return lowerSETCC(
Op, DAG);
686 return lowerFP_ROUND(
Op, DAG);
688 return lowerFP_EXTEND(
Op, DAG);
690 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
692 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
694 return lowerANY_EXTEND(
Op, DAG);
703 EVT VT = V.getValueType();
709 return V.getOperand(0);
713 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
715 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
725 if (!V->isOnlyUserOf(SplatValue.getNode()))
729 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
737 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
765 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
766 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
773 if (Opcode0 != Opcode1)
776 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
783 EVT VT =
N.getValueType();
797 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
798 SSVT0 == MVT::v4f64) {
817 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
818 N->getOpcode() == LoongArchISD::VPERMI) &&
819 Opcode0 == LoongArchISD::VFCVT) {
824 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
827 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
828 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
834 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
849 SDValue
In =
Op.getOperand(0);
850 MVT VT =
Op.getSimpleValueType();
851 MVT SVT =
In.getSimpleValueType();
853 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
866 EVT VT =
Op.getValueType();
867 SDValue Src =
Op->getOperand(0);
868 EVT SVT = Src.getValueType();
871 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
873 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
874 if (!V2F32ToV2F64 && !V4F32ToV4F64)
878 auto CheckVecHighPart = [](SDValue
Op) {
881 SDValue SOp =
Op.getOperand(0);
901 if (SDValue V = CheckVecHighPart(Src)) {
903 "Unexpected wide vector");
904 Opcode = LoongArchISD::VFCVTH;
907 Opcode = LoongArchISD::VFCVTL;
909 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
914 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
920 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
932 EVT VT =
Op.getValueType();
937 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
938 (VT == MVT::f64 && Subtarget.hasBasicD()));
955 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
965 if (Subtarget.is64Bit())
967 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
968 : LoongArchISD::MOVGR2FR_W,
972 if (Subtarget.is64Bit()) {
974 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
978 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
990 EVT ResultVT =
Op.getValueType();
991 EVT OperandVT =
Op.getOperand(0).getValueType();
996 if (ResultVT == SetCCResultVT)
999 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
1000 "SETCC operands must have the same type!");
1004 Op.getOperand(1),
Op.getOperand(2));
1006 if (ResultVT.
bitsGT(SetCCResultVT))
1008 else if (ResultVT.
bitsLT(SetCCResultVT))
1020SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1023 SDValue Src =
Op.getOperand(0);
1024 MVT SrcVT = Src.getSimpleValueType();
1025 MVT DstVT =
Op.getSimpleValueType();
1035 SDValue LoInterleaved =
1036 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1047 assert(Subtarget.hasExtLASX());
1066 MVT OpVT =
Op.getSimpleValueType();
1067 SDValue Val =
Op.getOperand(0);
1073 unsigned LegalVecSize = 128;
1074 bool isLASX256Vector =
1084 if (isLASX256Vector) {
1090 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1091 EleBits = std::min(EleBits, 64u);
1094 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1097 if (isLASX256Vector) {
1098 SDValue Tmp = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, Val,
1123 MVT OpVT =
Op.getSimpleValueType();
1124 SDValue Val =
Op.getOperand(0);
1136 MVT GRLenVT = Subtarget.getGRLenVT();
1138 for (
int i = NumEles; i > 1; i /= 2) {
1139 SDValue ShiftAmt = DAG.
getConstant(i * EleBits / 16,
DL, GRLenVT);
1140 SDValue Tmp = DAG.
getNode(LoongArchISD::VBSRL,
DL, VecTy, Val, ShiftAmt);
1141 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1150 unsigned IsData =
Op.getConstantOperandVal(4);
1155 return Op.getOperand(0);
1162 MVT VT =
Op.getSimpleValueType();
1166 SDValue
R =
Op.getOperand(0);
1167 SDValue Amt =
Op.getOperand(1);
1168 unsigned Opcode =
Op.getOpcode();
1171 auto checkCstSplat = [](SDValue
V, APInt &CstSplatValue) {
1174 if (SDValue SplatValue =
1177 CstSplatValue =
C->getAPIntValue();
1185 APInt CstSplatValue;
1186 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1190 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1206 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1222 if (
LHS == LHS2 &&
RHS == RHS2) {
1227 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1235 return std::nullopt;
1243 MVT VT =
N->getSimpleValueType(0);
1274 if (~TrueVal == FalseVal) {
1314 unsigned SelOpNo = 0;
1324 unsigned ConstSelOpNo = 1;
1325 unsigned OtherSelOpNo = 2;
1332 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1337 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1343 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1345 std::swap(NewConstOps[0], NewConstOps[1]);
1357 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1359 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1362 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1363 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1383 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1397 int64_t
C = RHSC->getSExtValue();
1436 SDValue CondV =
Op.getOperand(0);
1437 SDValue TrueV =
Op.getOperand(1);
1438 SDValue FalseV =
Op.getOperand(2);
1440 MVT VT =
Op.getSimpleValueType();
1441 MVT GRLenVT = Subtarget.getGRLenVT();
1446 if (
Op.hasOneUse()) {
1447 unsigned UseOpc =
Op->user_begin()->getOpcode();
1449 SDNode *BinOp = *
Op->user_begin();
1456 return lowerSELECT(NewSel, DAG);
1471 SDValue
Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
1473 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1496 if (TrueVal - 1 == FalseVal)
1498 if (TrueVal + 1 == FalseVal)
1505 RHS == TrueV &&
LHS == FalseV) {
1529 SDValue
Ops[] = {
LHS,
RHS, TargetCC, TrueV, FalseV};
1530 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1535 SDValue CondV =
Op.getOperand(1);
1537 MVT GRLenVT = Subtarget.getGRLenVT();
1548 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1549 Op.getOperand(0),
LHS,
RHS, TargetCC,
1552 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1553 Op.getOperand(0), CondV,
Op.getOperand(2));
1557 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1563LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1566 MVT OpVT =
Op.getSimpleValueType();
1569 SDValue Val =
Op.getOperand(0);
1577 EVT ResTy =
Op->getValueType(0);
1578 SDValue Src =
Op->getOperand(0);
1582 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1592 for (
unsigned int i = 0; i < NewEltNum; i++) {
1595 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1596 ? (
unsigned)LoongArchISD::BITREV_8B
1614 for (
unsigned int i = 0; i < NewEltNum; i++)
1615 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1616 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1634 if (EltBits > 32 || EltBits == 1)
1662 int MaskOffset,
const APInt &Zeroable) {
1663 int Size = Mask.size();
1664 unsigned SizeInBits =
Size * ScalarSizeInBits;
1666 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1667 for (
int i = 0; i <
Size; i += Scale)
1668 for (
int j = 0; j < Shift; ++j)
1669 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1677 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1678 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1683 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1684 for (
int i = 0; i !=
Size; i += Scale) {
1685 unsigned Pos =
Left ? i + Shift : i;
1686 unsigned Low =
Left ? i : i + Shift;
1687 unsigned Len = Scale - Shift;
1692 int ShiftEltBits = ScalarSizeInBits * Scale;
1693 bool ByteShift = ShiftEltBits > 64;
1694 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1695 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1696 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1700 Scale = ByteShift ? Scale / 2 : Scale;
1706 return (
int)ShiftAmt;
1709 unsigned MaxWidth = 128;
1710 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1711 for (
int Shift = 1; Shift != Scale; ++Shift)
1712 for (
bool Left : {
true,
false})
1713 if (CheckZeros(Shift, Scale,
Left)) {
1714 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1739 const APInt &Zeroable) {
1740 int Size = Mask.size();
1754 Mask,
Size, Zeroable);
1762 "Illegal integer vector type");
1771template <
typename ValType>
1774 unsigned CheckStride,
1776 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1780 if (*
I != -1 && *
I != ExpectedIndex)
1782 ExpectedIndex += ExpectedIndexStride;
1786 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1798 int Size = Mask.size();
1807 int VectorSizeInBits =
V1.getValueSizeInBits();
1808 int ScalarSizeInBits = VectorSizeInBits /
Size;
1809 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1810 (void)ScalarSizeInBits;
1812 for (
int i = 0; i <
Size; ++i) {
1818 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1835 RepeatedMask.
assign(LaneSize, -1);
1836 int Size = Mask.size();
1837 for (
int i = 0; i <
Size; ++i) {
1838 assert(Mask[i] == -1 || Mask[i] >= 0);
1841 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1848 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1849 if (RepeatedMask[i % LaneSize] < 0)
1851 RepeatedMask[i % LaneSize] = LocalM;
1852 else if (RepeatedMask[i % LaneSize] != LocalM)
1869 int NumElts = RepeatedMask.
size();
1871 int Scale = 16 / NumElts;
1873 for (
int i = 0; i < NumElts; ++i) {
1874 int M = RepeatedMask[i];
1875 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1876 "Unexpected mask index.");
1881 int StartIdx = i - (M % NumElts);
1888 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1891 Rotation = CandidateRotation;
1892 else if (Rotation != CandidateRotation)
1907 else if (TargetV != MaskV)
1912 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1913 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1922 return Rotation * Scale;
1941 if (ByteRotation <= 0)
1948 int LoByteShift = 16 - ByteRotation;
1949 int HiByteShift = ByteRotation;
1972 const APInt &Zeroable) {
1986 for (
int i = 0; i < NumElements; i++) {
1990 if (i % Scale != 0) {
2002 M = M % NumElements;
2005 Offset = M - (i / Scale);
2008 if (
Offset % (NumElements / Scale))
2010 }
else if (InputV != V)
2013 if (M != (
Offset + (i / Scale)))
2023 unsigned VilVLoHi = LoongArchISD::VILVL;
2024 if (
Offset >= (NumElements / 2)) {
2025 VilVLoHi = LoongArchISD::VILVH;
2026 Offset -= (NumElements / 2);
2034 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2038 }
while (Scale > 1);
2044 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2045 NumExtElements *= 2) {
2065 int SplatIndex = -1;
2066 for (
const auto &M : Mask) {
2073 if (SplatIndex == -1)
2076 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2078 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2108 unsigned SubVecSize = 4;
2109 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2112 int SubMask[4] = {-1, -1, -1, -1};
2113 for (
unsigned i = 0; i < SubVecSize; ++i) {
2114 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2120 M -= 4 * (j / SubVecSize);
2121 if (M < 0 || M >= 4)
2127 if (SubMask[i] == -1)
2131 else if (M != -1 && M != SubMask[i])
2138 for (
int i = SubVecSize - 1; i >= 0; --i) {
2151 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2152 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2155 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2173 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2182 for (
int i = 0; i < WidenNumElts; ++i)
2183 WidenMask[i] = WidenNumElts - 1 - i;
2191 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2215 const auto &Begin = Mask.begin();
2216 const auto &
End = Mask.end();
2233 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2255 const auto &Begin = Mask.begin();
2256 const auto &
End = Mask.end();
2273 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2296 const auto &Begin = Mask.begin();
2297 const auto &
End = Mask.end();
2298 unsigned HalfSize = Mask.size() / 2;
2316 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2339 const auto &Begin = Mask.begin();
2340 const auto &
End = Mask.end();
2357 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2379 const auto &Begin = Mask.begin();
2380 const auto &Mid = Mask.begin() + Mask.size() / 2;
2381 const auto &
End = Mask.end();
2399 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2421 const auto &Begin = Mask.begin();
2422 const auto &Mid = Mask.begin() + Mask.size() / 2;
2423 const auto &
End = Mask.end();
2440 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2466 if (Mask.size() != NumElts)
2469 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2472 for (
unsigned i = 0; i < NumElts; ++i) {
2475 if (Mask[i] !=
int(
Base + i)) {
2488 int DiffMask = Mask[DiffPos];
2489 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2495 if (
unsigned(DiffMask) < NumElts) {
2500 SrcIdx =
unsigned(DiffMask) - NumElts;
2516 if (
SDValue Result = tryLowerToExtrAndIns(0))
2518 return tryLowerToExtrAndIns(NumElts);
2526 unsigned &MaskImm) {
2527 unsigned MaskSize = Mask.size();
2530 return (M == -1) || (M >=
Off && M <
Off + 4);
2533 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2534 auto immPart = [&](
int M,
unsigned Off) {
2535 return (M == -1 ? 0 : (M -
Off)) & 0x3;
2537 MaskImm |= immPart(MLo,
Off) << (
I * 2);
2538 MaskImm |= immPart(MHi,
Off) << ((
I + 1) * 2);
2541 for (
unsigned i = 0; i < 4; i += 2) {
2543 int MHi = Mask[i + 1];
2545 if (MaskSize == 8) {
2546 auto isValid2 = [&](
int &M,
int M2) {
2553 if ((M2 % MaskSize) < 4)
2561 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2567 buildImm(MLo, MHi, 0, i);
2570 buildImm(MLo, MHi, MaskSize, i);
2600 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2605 unsigned MaskImm = 0;
2609 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2636 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2649 "Vector type is unsupported for lsx!");
2651 "Two operands have different types!");
2653 "Unexpected mask size for shuffle!");
2654 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2656 APInt KnownUndef, KnownZero;
2658 APInt Zeroable = KnownUndef | KnownZero;
2731 int SplatIndex = -1;
2732 for (
const auto &M : Mask) {
2739 if (SplatIndex == -1)
2742 const auto &Begin = Mask.begin();
2743 const auto &
End = Mask.end();
2744 int HalfSize = Mask.size() / 2;
2746 if (SplatIndex >= HalfSize)
2749 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2753 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2767 if (Mask.size() == 4) {
2768 unsigned MaskImm = 0;
2769 for (
int i = 1; i >= 0; --i) {
2771 int MHi = Mask[i + 2];
2772 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2773 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2775 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2780 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2782 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2785 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2806 return DAG.
getNode(LoongArchISD::XVREPLVE0,
DL, VT,
V1);
2815 unsigned MaskSize = Mask.size();
2820 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2822 unsigned MaskImm = 0;
2826 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2831 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2832 unsigned MaskImm = 0;
2833 for (
unsigned i = 0; i < MaskSize; ++i) {
2836 if (Mask[i] >= (
int)MaskSize)
2838 MaskImm |= Mask[i] << (i * 2);
2841 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2853 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2857 unsigned HalfSize = NumElts / 2;
2858 bool FrontLo =
true, FrontHi =
true;
2859 bool BackLo =
true, BackHi =
true;
2861 auto inRange = [](
int val,
int low,
int high) {
2862 return (val == -1) || (val >= low && val < high);
2865 for (
unsigned i = 0; i < HalfSize; ++i) {
2866 int Fronti = Mask[i];
2867 int Backi = Mask[i + HalfSize];
2869 FrontLo &=
inRange(Fronti, 0, HalfSize);
2870 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2871 BackLo &=
inRange(Backi, 0, HalfSize);
2872 BackHi &=
inRange(Backi, HalfSize, NumElts);
2878 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2883 for (
unsigned i = 0; i < NumElts; ++i)
2888 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2910 const auto &Begin = Mask.begin();
2911 const auto &
End = Mask.end();
2912 unsigned HalfSize = Mask.size() / 2;
2913 unsigned LeftSize = HalfSize / 2;
2921 Mask.size() + HalfSize - LeftSize, 1) &&
2923 Mask.size() + HalfSize + LeftSize, 1))
2934 Mask.size() + HalfSize - LeftSize, 1) &&
2936 Mask.size() + HalfSize + LeftSize, 1))
2941 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2949 const auto &Begin = Mask.begin();
2950 const auto &
End = Mask.end();
2951 unsigned HalfSize = Mask.size() / 2;
2959 Mask.size() + HalfSize, 1))
2970 Mask.size() + HalfSize, 1))
2975 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2983 const auto &Begin = Mask.begin();
2984 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2985 const auto &Mid = Mask.begin() + Mask.size() / 2;
2986 const auto &RightMid = Mask.end() - Mask.size() / 4;
2987 const auto &
End = Mask.end();
2988 unsigned HalfSize = Mask.size() / 2;
3010 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
3018 const auto &Begin = Mask.begin();
3019 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3020 const auto &Mid = Mask.begin() + Mask.size() / 2;
3021 const auto &RightMid = Mask.end() - Mask.size() / 4;
3022 const auto &
End = Mask.end();
3023 unsigned HalfSize = Mask.size() / 2;
3046 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3055 int HalfSize = NumElts / 2;
3059 if ((
int)Mask.size() != NumElts)
3062 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3064 for (
int i = 0; i < NumElts; ++i) {
3067 if (Mask[i] !=
Base + i) {
3069 if (DiffPos.
size() > 2)
3077 if (DiffPos.
size() == 1) {
3078 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3079 DiffPos.
push_back(DiffPos[0] + HalfSize);
3080 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3081 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3085 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3089 int DiffMaskLo = Mask[DiffPos[0]];
3090 int DiffMaskHi = Mask[DiffPos[1]];
3091 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3092 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3093 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3094 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3096 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3097 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3099 if (DiffMaskHi != DiffMaskLo + HalfSize)
3103 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3105 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3126 if (
SDValue Result = tryLowerToExtrAndIns(0))
3128 return tryLowerToExtrAndIns(NumElts);
3137 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3142 int MaskSize = Mask.size();
3148 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3150 for (
int i = 0; i < MaskSize; ++i) {
3151 if (Mask[i] ==
Base + i || Mask[i] == -1)
3153 if (Mask[i] != Replaced)
3164 int Idx = checkReplaceOne(0, MaskSize);
3166 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3170 Idx = checkReplaceOne(MaskSize, 0);
3172 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3183 int MaskSize = Mask.size();
3184 int HalfSize = Mask.size() / 2;
3185 const auto &Begin = Mask.begin();
3186 const auto &Mid = Mask.begin() + HalfSize;
3187 const auto &
End = Mask.end();
3199 for (
auto it = Begin; it < Mid; it++) {
3202 else if ((*it >= 0 && *it < HalfSize) ||
3203 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3204 int M = *it < HalfSize ? *it : *it - HalfSize;
3209 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3211 for (
auto it = Mid; it <
End; it++) {
3214 else if ((*it >= HalfSize && *it < MaskSize) ||
3215 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3216 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3221 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3225 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3253 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3255 int MaskSize = Mask.size();
3256 int HalfSize = Mask.size() / 2;
3259 HalfMaskType preMask =
None, postMask =
None;
3261 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3262 return M < 0 || (M >= 0 && M < HalfSize) ||
3263 (M >= MaskSize && M < MaskSize + HalfSize);
3265 preMask = HighLaneTy;
3266 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3267 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3268 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3270 preMask = LowLaneTy;
3272 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3273 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3274 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3276 postMask = LowLaneTy;
3277 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3278 return M < 0 || (M >= 0 && M < HalfSize) ||
3279 (M >= MaskSize && M < MaskSize + HalfSize);
3281 postMask = HighLaneTy;
3289 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3292 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3300 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3305 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3306 *it = *it < 0 ? *it : *it - HalfSize;
3308 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3309 *it = *it < 0 ? *it : *it + HalfSize;
3311 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3319 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3324 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3325 *it = *it < 0 ? *it : *it - HalfSize;
3327 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3335 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3340 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3341 *it = *it < 0 ? *it : *it + HalfSize;
3366 int Size = Mask.size();
3367 int LaneSize =
Size / 2;
3369 bool LaneCrossing[2] = {
false,
false};
3370 for (
int i = 0; i <
Size; ++i)
3371 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3372 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3375 if (!LaneCrossing[0] && !LaneCrossing[1])
3379 InLaneMask.
assign(Mask.begin(), Mask.end());
3380 for (
int i = 0; i <
Size; ++i) {
3381 int &M = InLaneMask[i];
3384 if (((M %
Size) / LaneSize) != (i / LaneSize))
3385 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3390 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3405 "Vector type is unsupported for lasx!");
3407 "Two operands have different types!");
3409 "Unexpected mask size for shuffle!");
3410 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3411 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3413 APInt KnownUndef, KnownZero;
3415 APInt Zeroable = KnownUndef | KnownZero;
3504 ArrayRef<int> OrigMask = SVOp->
getMask();
3505 SDValue
V1 =
Op.getOperand(0);
3506 SDValue V2 =
Op.getOperand(1);
3507 MVT VT =
Op.getSimpleValueType();
3511 bool V1IsUndef =
V1.isUndef();
3512 bool V2IsUndef = V2.
isUndef();
3513 if (V1IsUndef && V2IsUndef)
3526 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3527 SmallVector<int, 8> NewMask(OrigMask);
3528 for (
int &M : NewMask)
3529 if (M >= NumElements)
3535 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3536 (void)MaskUpperLimit;
3538 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3539 "Out of bounds shuffle index");
3557 SDValue Op0 =
Op.getOperand(0);
3558 SDValue Chain = SDValue();
3561 std::tie(Res, Chain) =
3562 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3563 if (Subtarget.is64Bit())
3564 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3574 SDValue Op0 =
Op.getOperand(0);
3575 SDValue Chain = SDValue();
3576 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3580 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3581 CallOptions,
DL, Chain);
3587 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3593 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3594 if (Subtarget.is64Bit())
3595 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3601 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3602 MVT VT =
Op.getSimpleValueType();
3607 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3628 "Unsupported vector type for broadcast.");
3631 bool IsIdeneity =
true;
3633 for (
int i = 0; i !=
NumOps; i++) {
3635 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3647 auto ExtType = LN->getExtensionType();
3652 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3657 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3675 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3689 EVT ResTy,
unsigned first) {
3692 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3695 Node->op_begin() + first + NumElts);
3704 MVT VT =
Node->getSimpleValueType(0);
3705 EVT ResTy =
Op->getValueType(0);
3708 APInt SplatValue, SplatUndef;
3709 unsigned SplatBitSize;
3712 bool UseSameConstant =
true;
3713 SDValue ConstantValue;
3717 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3718 (!Subtarget.hasExtLASX() || !Is256Vec))
3724 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3726 SplatBitSize <= 64) {
3728 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3732 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3739 if ((Is128Vec && ResTy == MVT::v4i32) ||
3740 (Is256Vec && ResTy == MVT::v8i32))
3746 switch (SplatBitSize) {
3750 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3753 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3756 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3759 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3767 if (ViaVecTy != ResTy)
3776 for (
unsigned i = 0; i < NumElts; ++i) {
3777 SDValue Opi =
Node->getOperand(i);
3781 ConstantValue = Opi;
3782 else if (ConstantValue != Opi)
3783 UseSameConstant =
false;
3788 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3790 for (
unsigned i = 0; i < NumElts; ++i) {
3791 SDValue Opi =
Node->getOperand(i);
3808 BitVector UndefElements;
3809 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3810 UndefElements.
count() == 0) {
3814 EVT FillTy = Is256Vec
3820 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3823 unsigned SplatLen = NumElts / SeqLen;
3829 if (SplatEltTy == MVT::i128)
3830 SplatTy = MVT::v4i64;
3838 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3839 : LoongArchISD::XVREPLVE0,
3840 DL, SplatTy, SrcVec);
3842 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3855 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3856 ResTy == MVT::v4f64) {
3857 unsigned NonUndefCount = 0;
3858 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3859 if (!
Node->getOperand(i).isUndef()) {
3861 if (NonUndefCount > 1)
3865 if (NonUndefCount == 1)
3878 VecTy, NumElts / 2);
3889 MVT ResVT =
Op.getSimpleValueType();
3897 unsigned NumFreezeUndef = 0;
3898 unsigned NumZero = 0;
3899 unsigned NumNonZero = 0;
3900 unsigned NonZeros = 0;
3901 SmallSet<SDValue, 4> Undefs;
3902 for (
unsigned i = 0; i != NumOperands; ++i) {
3903 SDValue SubVec =
Op.getOperand(i);
3917 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3924 if (NumNonZero > 2) {
3928 Ops.slice(0, NumOperands / 2));
3930 Ops.slice(NumOperands / 2));
3940 for (SDValue U : Undefs)
3943 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3945 for (
unsigned i = 0; i != NumOperands; ++i) {
3946 if ((NonZeros & (1 << i)) == 0)
3957LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3959 MVT EltVT =
Op.getSimpleValueType();
3960 SDValue Vec =
Op->getOperand(0);
3962 SDValue
Idx =
Op->getOperand(1);
3964 MVT GRLenVT = Subtarget.getGRLenVT();
3992 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3996 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3998 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
4006 SDValue SplatValue =
4007 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
4016LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
4018 MVT VT =
Op.getSimpleValueType();
4023 SDValue Op0 =
Op.getOperand(0);
4024 SDValue Op1 =
Op.getOperand(1);
4025 SDValue Op2 =
Op.getOperand(2);
4041 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4043 for (
unsigned i = 0; i < NumElts; ++i) {
4051 for (
unsigned i = 0; i < NumElts; ++i) {
4060 for (
unsigned i = 0; i < NumElts; ++i)
4113 MVT GRLenVT = Subtarget.getGRLenVT();
4115 SDValue Chain =
Op.getOperand(0);
4116 SDValue RMValue =
Op.getOperand(1);
4125 "rounding mode is not supported by LoongArch hardware",
4126 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4143 FCSRNo, RMValue, Chain);
4144 return SDValue(RN, 0);
4149 MVT GRLenVT = Subtarget.getGRLenVT();
4151 SDValue Chain =
Op->getOperand(0);
4156 MVT::Other, FCSRNo, Chain);
4157 SDValue RMValue = SDValue(FCSR, 0);
4158 Chain = SDValue(FCSR, 1);
4172 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4174 "On LA64, only 64-bit registers can be written.");
4175 return Op.getOperand(0);
4178 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4180 "On LA32, only 32-bit registers can be written.");
4181 return Op.getOperand(0);
4191 "be a constant integer");
4197 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4198 EVT VT =
Op.getValueType();
4201 unsigned Depth =
Op.getConstantOperandVal(0);
4202 int GRLenInBytes = Subtarget.getGRLen() / 8;
4205 int Offset = -(GRLenInBytes * 2);
4217 if (
Op.getConstantOperandVal(0) != 0) {
4219 "return address can only be determined for the current frame");
4225 MVT GRLenVT = Subtarget.getGRLenVT();
4237 auto Size = Subtarget.getGRLen() / 8;
4245 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4248 SDValue FI = DAG.
getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
4255 MachinePointerInfo(SV));
4261 SDValue Op0 =
Op.getOperand(0);
4262 EVT VT =
Op.getValueType();
4277 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4285 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4288 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4289 !Subtarget.hasBasicD() &&
"unexpected target features");
4293 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4297 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4307 EVT RetVT =
Op.getValueType();
4311 SDValue Chain = SDValue();
4313 std::tie(Result, Chain) =
4320 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4321 !Subtarget.hasBasicD() &&
"unexpected target features");
4324 SDValue Op0 =
Op.getOperand(0);
4332 EVT RetVT =
Op.getValueType();
4336 SDValue Chain = SDValue();
4338 std::tie(Result, Chain) =
4347 EVT VT =
Op.getValueType();
4348 SDValue Op0 =
Op.getOperand(0);
4351 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4352 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4354 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4356 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4359 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4368 SDValue Op0 =
Op.getOperand(0);
4373 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4374 !Subtarget.hasBasicD()) {
4375 SDValue Dst = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f32, Op0);
4376 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4380 SDValue Trunc = DAG.
getNode(LoongArchISD::FTINT,
DL, FPTy, Op0);
4386 if (!Subtarget.hasExtLSX())
4390 SDValue Src =
Op.getOperand(0);
4391 EVT VT =
Op.getValueType();
4392 EVT SrcVT = Src.getValueType();
4397 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4400 if (SrcVT == MVT::f32)
4422 N->getOffset(), Flags);
4430template <
class NodeTy>
4433 bool IsLocal)
const {
4444 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4525 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4527 const GlobalValue *GV =
N->getGlobal();
4539 unsigned Opc,
bool UseGOT,
4543 MVT GRLenVT = Subtarget.getGRLenVT();
4551 SDValue
Offset =
Opc == LoongArch::PseudoLA_TLS_IE_LARGE
4553 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4557 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4591 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4598 TargetLowering::CallLoweringInfo CLI(DAG);
4613 const GlobalValue *GV =
N->getGlobal();
4623 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4627LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4634 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4637 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4650 return getDynamicTLSAddr(
N, DAG,
4651 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4652 : LoongArch::PseudoLA_TLS_GD,
4659 return getDynamicTLSAddr(
N, DAG,
4660 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4661 : LoongArch::PseudoLA_TLS_LD,
4666 return getStaticTLSAddr(
N, DAG,
4667 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4668 : LoongArch::PseudoLA_TLS_IE,
4675 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4679 return getTLSDescAddr(
N, DAG,
4680 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4681 : LoongArch::PseudoLA_TLS_DESC,
4685template <
unsigned N>
4690 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4691 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4693 ": argument out of range.");
4700LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4702 switch (
Op.getConstantOperandVal(0)) {
4705 case Intrinsic::thread_pointer: {
4709 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4710 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4711 case Intrinsic::loongarch_lsx_vreplvei_d:
4712 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4714 case Intrinsic::loongarch_lsx_vreplvei_w:
4715 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4716 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4717 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4718 case Intrinsic::loongarch_lasx_xvpickve_d:
4719 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4721 case Intrinsic::loongarch_lasx_xvinsve0_d:
4723 case Intrinsic::loongarch_lsx_vsat_b:
4724 case Intrinsic::loongarch_lsx_vsat_bu:
4725 case Intrinsic::loongarch_lsx_vrotri_b:
4726 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4727 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4728 case Intrinsic::loongarch_lsx_vsrlri_b:
4729 case Intrinsic::loongarch_lsx_vsrari_b:
4730 case Intrinsic::loongarch_lsx_vreplvei_h:
4731 case Intrinsic::loongarch_lasx_xvsat_b:
4732 case Intrinsic::loongarch_lasx_xvsat_bu:
4733 case Intrinsic::loongarch_lasx_xvrotri_b:
4734 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4735 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4736 case Intrinsic::loongarch_lasx_xvsrlri_b:
4737 case Intrinsic::loongarch_lasx_xvsrari_b:
4738 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4739 case Intrinsic::loongarch_lasx_xvpickve_w:
4740 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4742 case Intrinsic::loongarch_lasx_xvinsve0_w:
4744 case Intrinsic::loongarch_lsx_vsat_h:
4745 case Intrinsic::loongarch_lsx_vsat_hu:
4746 case Intrinsic::loongarch_lsx_vrotri_h:
4747 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4748 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4749 case Intrinsic::loongarch_lsx_vsrlri_h:
4750 case Intrinsic::loongarch_lsx_vsrari_h:
4751 case Intrinsic::loongarch_lsx_vreplvei_b:
4752 case Intrinsic::loongarch_lasx_xvsat_h:
4753 case Intrinsic::loongarch_lasx_xvsat_hu:
4754 case Intrinsic::loongarch_lasx_xvrotri_h:
4755 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4756 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4757 case Intrinsic::loongarch_lasx_xvsrlri_h:
4758 case Intrinsic::loongarch_lasx_xvsrari_h:
4759 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4761 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4762 case Intrinsic::loongarch_lsx_vsrani_b_h:
4763 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4764 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4765 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4766 case Intrinsic::loongarch_lsx_vssrani_b_h:
4767 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4768 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4769 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4770 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4771 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4772 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4773 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4774 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4775 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4776 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4777 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4778 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4779 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4780 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4781 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4782 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4783 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4784 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4786 case Intrinsic::loongarch_lsx_vsat_w:
4787 case Intrinsic::loongarch_lsx_vsat_wu:
4788 case Intrinsic::loongarch_lsx_vrotri_w:
4789 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4790 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4791 case Intrinsic::loongarch_lsx_vsrlri_w:
4792 case Intrinsic::loongarch_lsx_vsrari_w:
4793 case Intrinsic::loongarch_lsx_vslei_bu:
4794 case Intrinsic::loongarch_lsx_vslei_hu:
4795 case Intrinsic::loongarch_lsx_vslei_wu:
4796 case Intrinsic::loongarch_lsx_vslei_du:
4797 case Intrinsic::loongarch_lsx_vslti_bu:
4798 case Intrinsic::loongarch_lsx_vslti_hu:
4799 case Intrinsic::loongarch_lsx_vslti_wu:
4800 case Intrinsic::loongarch_lsx_vslti_du:
4801 case Intrinsic::loongarch_lsx_vbsll_v:
4802 case Intrinsic::loongarch_lsx_vbsrl_v:
4803 case Intrinsic::loongarch_lasx_xvsat_w:
4804 case Intrinsic::loongarch_lasx_xvsat_wu:
4805 case Intrinsic::loongarch_lasx_xvrotri_w:
4806 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4807 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4808 case Intrinsic::loongarch_lasx_xvsrlri_w:
4809 case Intrinsic::loongarch_lasx_xvsrari_w:
4810 case Intrinsic::loongarch_lasx_xvslei_bu:
4811 case Intrinsic::loongarch_lasx_xvslei_hu:
4812 case Intrinsic::loongarch_lasx_xvslei_wu:
4813 case Intrinsic::loongarch_lasx_xvslei_du:
4814 case Intrinsic::loongarch_lasx_xvslti_bu:
4815 case Intrinsic::loongarch_lasx_xvslti_hu:
4816 case Intrinsic::loongarch_lasx_xvslti_wu:
4817 case Intrinsic::loongarch_lasx_xvslti_du:
4818 case Intrinsic::loongarch_lasx_xvbsll_v:
4819 case Intrinsic::loongarch_lasx_xvbsrl_v:
4821 case Intrinsic::loongarch_lsx_vseqi_b:
4822 case Intrinsic::loongarch_lsx_vseqi_h:
4823 case Intrinsic::loongarch_lsx_vseqi_w:
4824 case Intrinsic::loongarch_lsx_vseqi_d:
4825 case Intrinsic::loongarch_lsx_vslei_b:
4826 case Intrinsic::loongarch_lsx_vslei_h:
4827 case Intrinsic::loongarch_lsx_vslei_w:
4828 case Intrinsic::loongarch_lsx_vslei_d:
4829 case Intrinsic::loongarch_lsx_vslti_b:
4830 case Intrinsic::loongarch_lsx_vslti_h:
4831 case Intrinsic::loongarch_lsx_vslti_w:
4832 case Intrinsic::loongarch_lsx_vslti_d:
4833 case Intrinsic::loongarch_lasx_xvseqi_b:
4834 case Intrinsic::loongarch_lasx_xvseqi_h:
4835 case Intrinsic::loongarch_lasx_xvseqi_w:
4836 case Intrinsic::loongarch_lasx_xvseqi_d:
4837 case Intrinsic::loongarch_lasx_xvslei_b:
4838 case Intrinsic::loongarch_lasx_xvslei_h:
4839 case Intrinsic::loongarch_lasx_xvslei_w:
4840 case Intrinsic::loongarch_lasx_xvslei_d:
4841 case Intrinsic::loongarch_lasx_xvslti_b:
4842 case Intrinsic::loongarch_lasx_xvslti_h:
4843 case Intrinsic::loongarch_lasx_xvslti_w:
4844 case Intrinsic::loongarch_lasx_xvslti_d:
4846 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4847 case Intrinsic::loongarch_lsx_vsrani_h_w:
4848 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4849 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4850 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4851 case Intrinsic::loongarch_lsx_vssrani_h_w:
4852 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4853 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4854 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4855 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4856 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4857 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4858 case Intrinsic::loongarch_lsx_vfrstpi_b:
4859 case Intrinsic::loongarch_lsx_vfrstpi_h:
4860 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4861 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4862 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4863 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4864 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4865 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4866 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4867 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4868 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4869 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4870 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4871 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4872 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4873 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4875 case Intrinsic::loongarch_lsx_vsat_d:
4876 case Intrinsic::loongarch_lsx_vsat_du:
4877 case Intrinsic::loongarch_lsx_vrotri_d:
4878 case Intrinsic::loongarch_lsx_vsrlri_d:
4879 case Intrinsic::loongarch_lsx_vsrari_d:
4880 case Intrinsic::loongarch_lasx_xvsat_d:
4881 case Intrinsic::loongarch_lasx_xvsat_du:
4882 case Intrinsic::loongarch_lasx_xvrotri_d:
4883 case Intrinsic::loongarch_lasx_xvsrlri_d:
4884 case Intrinsic::loongarch_lasx_xvsrari_d:
4886 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4887 case Intrinsic::loongarch_lsx_vsrani_w_d:
4888 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4889 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4890 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4891 case Intrinsic::loongarch_lsx_vssrani_w_d:
4892 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4893 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4894 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4895 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4896 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4897 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4898 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4899 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4900 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4901 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4902 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4903 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4904 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4905 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4906 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4907 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4908 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4909 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4911 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4912 case Intrinsic::loongarch_lsx_vsrani_d_q:
4913 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4914 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4915 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4916 case Intrinsic::loongarch_lsx_vssrani_d_q:
4917 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4918 case Intrinsic::loongarch_lsx_vssrani_du_q:
4919 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4920 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4921 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4922 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4923 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4924 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4925 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4926 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4927 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4928 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4929 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4930 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4931 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4932 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4933 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4934 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4936 case Intrinsic::loongarch_lsx_vnori_b:
4937 case Intrinsic::loongarch_lsx_vshuf4i_b:
4938 case Intrinsic::loongarch_lsx_vshuf4i_h:
4939 case Intrinsic::loongarch_lsx_vshuf4i_w:
4940 case Intrinsic::loongarch_lasx_xvnori_b:
4941 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4942 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4943 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4944 case Intrinsic::loongarch_lasx_xvpermi_d:
4946 case Intrinsic::loongarch_lsx_vshuf4i_d:
4947 case Intrinsic::loongarch_lsx_vpermi_w:
4948 case Intrinsic::loongarch_lsx_vbitseli_b:
4949 case Intrinsic::loongarch_lsx_vextrins_b:
4950 case Intrinsic::loongarch_lsx_vextrins_h:
4951 case Intrinsic::loongarch_lsx_vextrins_w:
4952 case Intrinsic::loongarch_lsx_vextrins_d:
4953 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4954 case Intrinsic::loongarch_lasx_xvpermi_w:
4955 case Intrinsic::loongarch_lasx_xvpermi_q:
4956 case Intrinsic::loongarch_lasx_xvbitseli_b:
4957 case Intrinsic::loongarch_lasx_xvextrins_b:
4958 case Intrinsic::loongarch_lasx_xvextrins_h:
4959 case Intrinsic::loongarch_lasx_xvextrins_w:
4960 case Intrinsic::loongarch_lasx_xvextrins_d:
4962 case Intrinsic::loongarch_lsx_vrepli_b:
4963 case Intrinsic::loongarch_lsx_vrepli_h:
4964 case Intrinsic::loongarch_lsx_vrepli_w:
4965 case Intrinsic::loongarch_lsx_vrepli_d:
4966 case Intrinsic::loongarch_lasx_xvrepli_b:
4967 case Intrinsic::loongarch_lasx_xvrepli_h:
4968 case Intrinsic::loongarch_lasx_xvrepli_w:
4969 case Intrinsic::loongarch_lasx_xvrepli_d:
4971 case Intrinsic::loongarch_lsx_vldi:
4972 case Intrinsic::loongarch_lasx_xvldi:
4988LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4991 MVT GRLenVT = Subtarget.getGRLenVT();
4992 EVT VT =
Op.getValueType();
4993 SDValue Chain =
Op.getOperand(0);
4994 const StringRef ErrorMsgOOR =
"argument out of range";
4995 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4996 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4998 switch (
Op.getConstantOperandVal(1)) {
5001 case Intrinsic::loongarch_crc_w_b_w:
5002 case Intrinsic::loongarch_crc_w_h_w:
5003 case Intrinsic::loongarch_crc_w_w_w:
5004 case Intrinsic::loongarch_crc_w_d_w:
5005 case Intrinsic::loongarch_crcc_w_b_w:
5006 case Intrinsic::loongarch_crcc_w_h_w:
5007 case Intrinsic::loongarch_crcc_w_w_w:
5008 case Intrinsic::loongarch_crcc_w_d_w:
5010 case Intrinsic::loongarch_csrrd_w:
5011 case Intrinsic::loongarch_csrrd_d: {
5012 unsigned Imm =
Op.getConstantOperandVal(2);
5015 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5018 case Intrinsic::loongarch_csrwr_w:
5019 case Intrinsic::loongarch_csrwr_d: {
5020 unsigned Imm =
Op.getConstantOperandVal(3);
5023 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5024 {Chain,
Op.getOperand(2),
5027 case Intrinsic::loongarch_csrxchg_w:
5028 case Intrinsic::loongarch_csrxchg_d: {
5029 unsigned Imm =
Op.getConstantOperandVal(4);
5032 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5033 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5036 case Intrinsic::loongarch_iocsrrd_d: {
5038 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5041#define IOCSRRD_CASE(NAME, NODE) \
5042 case Intrinsic::loongarch_##NAME: { \
5043 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5044 {Chain, Op.getOperand(2)}); \
5050 case Intrinsic::loongarch_cpucfg: {
5051 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5052 {Chain,
Op.getOperand(2)});
5054 case Intrinsic::loongarch_lddir_d: {
5055 unsigned Imm =
Op.getConstantOperandVal(3);
5060 case Intrinsic::loongarch_movfcsr2gr: {
5061 if (!Subtarget.hasBasicF())
5063 unsigned Imm =
Op.getConstantOperandVal(2);
5066 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5069 case Intrinsic::loongarch_lsx_vld:
5070 case Intrinsic::loongarch_lsx_vldrepl_b:
5071 case Intrinsic::loongarch_lasx_xvld:
5072 case Intrinsic::loongarch_lasx_xvldrepl_b:
5076 case Intrinsic::loongarch_lsx_vldrepl_h:
5077 case Intrinsic::loongarch_lasx_xvldrepl_h:
5081 Op,
"argument out of range or not a multiple of 2", DAG)
5083 case Intrinsic::loongarch_lsx_vldrepl_w:
5084 case Intrinsic::loongarch_lasx_xvldrepl_w:
5088 Op,
"argument out of range or not a multiple of 4", DAG)
5090 case Intrinsic::loongarch_lsx_vldrepl_d:
5091 case Intrinsic::loongarch_lasx_xvldrepl_d:
5095 Op,
"argument out of range or not a multiple of 8", DAG)
5106 return Op.getOperand(0);
5112 MVT GRLenVT = Subtarget.getGRLenVT();
5113 SDValue Chain =
Op.getOperand(0);
5114 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5115 SDValue Op2 =
Op.getOperand(2);
5116 const StringRef ErrorMsgOOR =
"argument out of range";
5117 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5118 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5119 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5121 switch (IntrinsicEnum) {
5125 case Intrinsic::loongarch_cacop_d:
5126 case Intrinsic::loongarch_cacop_w: {
5127 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5129 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5138 case Intrinsic::loongarch_dbar: {
5145 case Intrinsic::loongarch_ibar: {
5152 case Intrinsic::loongarch_break: {
5159 case Intrinsic::loongarch_movgr2fcsr: {
5160 if (!Subtarget.hasBasicF())
5170 case Intrinsic::loongarch_syscall: {
5177#define IOCSRWR_CASE(NAME, NODE) \
5178 case Intrinsic::loongarch_##NAME: { \
5179 SDValue Op3 = Op.getOperand(3); \
5180 return Subtarget.is64Bit() \
5181 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5182 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5183 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5184 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5191 case Intrinsic::loongarch_iocsrwr_d: {
5192 return !Subtarget.is64Bit()
5199#define ASRT_LE_GT_CASE(NAME) \
5200 case Intrinsic::loongarch_##NAME: { \
5201 return !Subtarget.is64Bit() \
5202 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5207#undef ASRT_LE_GT_CASE
5208 case Intrinsic::loongarch_ldpte_d: {
5209 unsigned Imm =
Op.getConstantOperandVal(3);
5210 return !Subtarget.is64Bit()
5215 case Intrinsic::loongarch_lsx_vst:
5216 case Intrinsic::loongarch_lasx_xvst:
5220 case Intrinsic::loongarch_lasx_xvstelm_b:
5225 case Intrinsic::loongarch_lsx_vstelm_b:
5230 case Intrinsic::loongarch_lasx_xvstelm_h:
5235 Op,
"argument out of range or not a multiple of 2", DAG)
5237 case Intrinsic::loongarch_lsx_vstelm_h:
5242 Op,
"argument out of range or not a multiple of 2", DAG)
5244 case Intrinsic::loongarch_lasx_xvstelm_w:
5249 Op,
"argument out of range or not a multiple of 4", DAG)
5251 case Intrinsic::loongarch_lsx_vstelm_w:
5256 Op,
"argument out of range or not a multiple of 4", DAG)
5258 case Intrinsic::loongarch_lasx_xvstelm_d:
5263 Op,
"argument out of range or not a multiple of 8", DAG)
5265 case Intrinsic::loongarch_lsx_vstelm_d:
5270 Op,
"argument out of range or not a multiple of 8", DAG)
5278 SDValue
Lo =
Op.getOperand(0);
5279 SDValue
Hi =
Op.getOperand(1);
5280 SDValue Shamt =
Op.getOperand(2);
5281 EVT VT =
Lo.getValueType();
5292 SDValue MinusGRLen =
5294 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5300 SDValue ShiftRightLo =
5311 SDValue Parts[2] = {
Lo,
Hi};
5319 SDValue
Lo =
Op.getOperand(0);
5320 SDValue
Hi =
Op.getOperand(1);
5321 SDValue Shamt =
Op.getOperand(2);
5322 EVT VT =
Lo.getValueType();
5344 SDValue MinusGRLen =
5346 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5352 SDValue ShiftLeftHi =
5355 SDValue HiTrue = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, Shamt);
5356 SDValue LoFalse = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, ShamtMinusGRLen);
5365 SDValue Parts[2] = {
Lo,
Hi};
5376 return LoongArchISD::DIV_W;
5378 return LoongArchISD::DIV_WU;
5380 return LoongArchISD::MOD_W;
5382 return LoongArchISD::MOD_WU;
5384 return LoongArchISD::SLL_W;
5386 return LoongArchISD::SRA_W;
5388 return LoongArchISD::SRL_W;
5391 return LoongArchISD::ROTR_W;
5393 return LoongArchISD::CTZ_W;
5395 return LoongArchISD::CLZ_W;
5414 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5415 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5419 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5425 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5452 StringRef ErrorMsg,
bool WithChain =
true) {
5457 Results.push_back(
N->getOperand(0));
5460template <
unsigned N>
5465 const StringRef ErrorMsgOOR =
"argument out of range";
5466 unsigned Imm =
Node->getConstantOperandVal(2);
5500 switch (
N->getConstantOperandVal(0)) {
5503 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5505 LoongArchISD::VPICK_SEXT_ELT);
5507 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5508 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5510 LoongArchISD::VPICK_SEXT_ELT);
5512 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5514 LoongArchISD::VPICK_SEXT_ELT);
5516 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5518 LoongArchISD::VPICK_ZEXT_ELT);
5520 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5521 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5523 LoongArchISD::VPICK_ZEXT_ELT);
5525 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5527 LoongArchISD::VPICK_ZEXT_ELT);
5529 case Intrinsic::loongarch_lsx_bz_b:
5530 case Intrinsic::loongarch_lsx_bz_h:
5531 case Intrinsic::loongarch_lsx_bz_w:
5532 case Intrinsic::loongarch_lsx_bz_d:
5533 case Intrinsic::loongarch_lasx_xbz_b:
5534 case Intrinsic::loongarch_lasx_xbz_h:
5535 case Intrinsic::loongarch_lasx_xbz_w:
5536 case Intrinsic::loongarch_lasx_xbz_d:
5538 LoongArchISD::VALL_ZERO);
5540 case Intrinsic::loongarch_lsx_bz_v:
5541 case Intrinsic::loongarch_lasx_xbz_v:
5543 LoongArchISD::VANY_ZERO);
5545 case Intrinsic::loongarch_lsx_bnz_b:
5546 case Intrinsic::loongarch_lsx_bnz_h:
5547 case Intrinsic::loongarch_lsx_bnz_w:
5548 case Intrinsic::loongarch_lsx_bnz_d:
5549 case Intrinsic::loongarch_lasx_xbnz_b:
5550 case Intrinsic::loongarch_lasx_xbnz_h:
5551 case Intrinsic::loongarch_lasx_xbnz_w:
5552 case Intrinsic::loongarch_lasx_xbnz_d:
5554 LoongArchISD::VALL_NONZERO);
5556 case Intrinsic::loongarch_lsx_bnz_v:
5557 case Intrinsic::loongarch_lasx_xbnz_v:
5559 LoongArchISD::VANY_NONZERO);
5567 assert(
N->getValueType(0) == MVT::i128 &&
5568 "AtomicCmpSwap on types less than 128 should be legal");
5572 switch (
MemOp->getMergedOrdering()) {
5576 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5580 Opcode = LoongArch::PseudoCmpXchg128;
5587 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5588 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5589 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5590 NewVal.first, NewVal.second,
N->getOperand(0)};
5593 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5604 EVT VT =
N->getValueType(0);
5605 switch (
N->getOpcode()) {
5610 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5611 "Unexpected custom legalisation");
5618 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5619 "Unexpected custom legalisation");
5621 Subtarget.hasDiv32() && VT == MVT::i32
5628 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5629 "Unexpected custom legalisation");
5637 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5638 "Unexpected custom legalisation");
5645 MVT VT =
N->getSimpleValueType(0);
5646 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5647 "Unexpected custom legalisation");
5649 "Unexpected type action!");
5654 Ld->getPointerInfo(), Ld->getBaseAlign(),
5655 Ld->getMemOperand()->getFlags());
5666 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5667 "Unexpected custom legalisation");
5674 if (Src.getValueType() == MVT::f16)
5685 EVT OpVT = Src.getValueType();
5689 std::tie(Result, Chain) =
5696 EVT SrcVT = Src.getValueType();
5697 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5698 Subtarget.hasBasicF()) {
5700 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5702 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5704 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5712 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5713 "Unexpected custom legalisation");
5716 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5721 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5722 "Unexpected custom legalisation");
5728 if (OpVT == MVT::v2f64) {
5738 assert((VT == MVT::i16 || VT == MVT::i32) &&
5739 "Unexpected custom legalization");
5740 MVT GRLenVT = Subtarget.getGRLenVT();
5747 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5752 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5760 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5761 "Unexpected custom legalization");
5762 MVT GRLenVT = Subtarget.getGRLenVT();
5769 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5772 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5780 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5781 "Unexpected custom legalisation");
5788 MVT GRLenVT = Subtarget.getGRLenVT();
5789 const StringRef ErrorMsgOOR =
"argument out of range";
5790 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5791 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5793 switch (
N->getConstantOperandVal(1)) {
5796 case Intrinsic::loongarch_movfcsr2gr: {
5797 if (!Subtarget.hasBasicF()) {
5807 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5814#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5815 case Intrinsic::loongarch_##NAME: { \
5816 SDValue NODE = DAG.getNode( \
5817 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5818 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5819 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5820 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5821 Results.push_back(NODE.getValue(1)); \
5830#undef CRC_CASE_EXT_BINARYOP
5832#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5833 case Intrinsic::loongarch_##NAME: { \
5834 SDValue NODE = DAG.getNode( \
5835 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5837 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5838 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5839 Results.push_back(NODE.getValue(1)); \
5844#undef CRC_CASE_EXT_UNARYOP
5845#define CSR_CASE(ID) \
5846 case Intrinsic::loongarch_##ID: { \
5847 if (!Subtarget.is64Bit()) \
5848 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5856 case Intrinsic::loongarch_csrrd_w: {
5863 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5870 case Intrinsic::loongarch_csrwr_w: {
5871 unsigned Imm =
N->getConstantOperandVal(3);
5877 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5885 case Intrinsic::loongarch_csrxchg_w: {
5886 unsigned Imm =
N->getConstantOperandVal(4);
5892 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5901#define IOCSRRD_CASE(NAME, NODE) \
5902 case Intrinsic::loongarch_##NAME: { \
5903 SDValue IOCSRRDResults = \
5904 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5905 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5906 Results.push_back( \
5907 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5908 Results.push_back(IOCSRRDResults.getValue(1)); \
5915 case Intrinsic::loongarch_cpucfg: {
5917 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5924 case Intrinsic::loongarch_lddir_d: {
5925 if (!Subtarget.is64Bit()) {
5935 if (Subtarget.is64Bit())
5937 "On LA64, only 64-bit registers can be read.");
5940 "On LA32, only 32-bit registers can be read.");
5942 Results.push_back(
N->getOperand(0));
5953 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5966 MVT VT =
N->getSimpleValueType(0);
5972 EVT InVT = In.getValueType();
5982 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5987 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
5990 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5999 for (
unsigned I = 0;
I < MinElts; ++
I)
6000 TruncMask[
I] = Scale *
I;
6002 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
6003 MVT SVT = In.getSimpleValueType().getScalarType();
6009 "Illegal vector type in truncation");
6021 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
6024 EVT DstVT =
N->getValueType(0);
6026 MVT SrcVT = Src.getSimpleValueType();
6040 unsigned WidenSrcElts = 128 / SrcEltBits;
6047 unsigned FirstStageEltBits = 128 / NumElts;
6051 SrcVT = FirstStageVT;
6052 SrcEltBits = FirstStageEltBits;
6059 while (SrcEltBits < DstEltBits) {
6060 unsigned NextEltBits = SrcEltBits * 2;
6063 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6081 Blocks = std::move(NextBlocks);
6082 SrcVT = NextBlockVT;
6083 SrcEltBits = NextEltBits;
6100 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6102 MVT VT =
N->getSimpleValueType(0);
6121 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6125 unsigned MinSizeInBits) {
6133 unsigned SplatBitSize;
6136 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6137 HasAnyUndefs, MinSizeInBits,
6149 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6160 unsigned EltIdx = IdxC->getZExtValue();
6162 Start = (int)EltIdx - (
int)(i * 2);
6163 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6169 else if (Src != CurSrc)
6173 if (!Src || Start < 0)
6183 if (!Subtarget.hasExtLSX())
6186 unsigned Opc =
N->getOpcode();
6189 EVT VT =
N->getValueType(0);
6196 unsigned ExtOpc =
LHS.getOpcode();
6204 if (ExtOpc !=
RHS.getOpcode())
6207 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6210 unsigned OddIdx, EvenIdx;
6214 if (!LHSVec || !RHSVec)
6216 if (OddIdx != 1 || EvenIdx != 0)
6226 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6239 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6241 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6243 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6255 EVT VT =
N->getValueType(0);
6321 if (
And.getOperand(0) ==
X) {
6350 if (ShiftVal != (SplatVal + 1))
6359 : LoongArchISD::VSRAR,
6369 SDValue FirstOperand =
N->getOperand(0);
6370 SDValue SecondOperand =
N->getOperand(1);
6371 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6372 EVT ValTy =
N->getValueType(0);
6375 unsigned SMIdx, SMLen;
6384 if (!Subtarget.has32S())
6440 NewOperand = FirstOperand;
6443 msb = lsb + SMLen - 1;
6447 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6461 EVT DstVT =
N.getValueType();
6470 EVT SrcVT = Src.getValueType();
6478 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6489 if (NumElts % 2 != 0)
6495 for (
unsigned I = 0;
I != NumElts; ++
I) {
6510 SrcVT = Src.getValueType();
6520 }
else if (ThisSrc != Src) {
6524 unsigned Half = NumElts / 2;
6525 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6526 ExpectedIdx += isLow ? 0 : Half;
6528 if (CI->getZExtValue() != ExpectedIdx)
6540 EVT VT =
N->getValueType(0);
6547 unsigned ExtOpc =
LHS.getOpcode();
6555 if (!
LHS.hasOneUse())
6559 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6575 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6584 if (!Subtarget.has32S())
6596 SDValue FirstOperand =
N->getOperand(0);
6598 EVT ValTy =
N->getValueType(0);
6601 unsigned MaskIdx, MaskLen;
6616 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6617 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6641 switch (Src.getOpcode()) {
6644 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6654 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6667 switch (Src.getOpcode()) {
6677 Src.getOpcode(),
DL, SExtVT,
6683 DL, SExtVT, Src.getOperand(0),
6695 EVT VT =
N->getValueType(0);
6697 EVT SrcVT = Src.getValueType();
6699 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6704 EVT CmpVT = Src.getOperand(0).getValueType();
6709 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6722 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6727 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6732 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6737 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6739 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6744 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6746 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6751 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6768 EVT VT =
N->getValueType(0);
6770 EVT SrcVT = Src.getValueType();
6787 bool UseLASX =
false;
6788 bool PropagateSExt =
false;
6790 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6791 EVT CmpVT = Src.getOperand(0).getValueType();
6800 SExtVT = MVT::v2i64;
6803 SExtVT = MVT::v4i32;
6805 SExtVT = MVT::v4i64;
6807 PropagateSExt =
true;
6811 SExtVT = MVT::v8i16;
6813 SExtVT = MVT::v8i32;
6815 PropagateSExt =
true;
6819 SExtVT = MVT::v16i8;
6821 SExtVT = MVT::v16i16;
6823 PropagateSExt =
true;
6827 SExtVT = MVT::v32i8;
6835 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6836 if (Src.getSimpleValueType() == MVT::v32i8) {
6844 }
else if (UseLASX) {
6850 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6863 EVT ValTy =
N->getValueType(0);
6864 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6868 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6870 bool SwapAndRetried =
false;
6873 if (!Subtarget.has32S())
6879 if (ValBits != 32 && ValBits != 64)
6894 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6897 (MaskIdx0 + MaskLen0 <= ValBits)) {
6918 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6919 (MaskIdx0 + MaskLen0 <= ValBits)) {
6936 (MaskIdx0 + MaskLen0 <= 64) &&
6944 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6945 : (MaskIdx0 + MaskLen0 - 1),
6961 (MaskIdx0 + MaskLen0 <= ValBits)) {
6984 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6985 : (MaskIdx0 + MaskLen0 - 1),
7000 unsigned MaskIdx, MaskLen;
7001 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
7010 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7028 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7034 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7042 if (!SwapAndRetried) {
7044 SwapAndRetried =
true;
7048 SwapAndRetried =
false;
7065 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7074 if (!SwapAndRetried) {
7076 SwapAndRetried =
true;
7086 switch (V.getNode()->getOpcode()) {
7098 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7106 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7136 unsigned MskOpc =
LHS.getOpcode();
7137 if (MskOpc != LoongArchISD::VMSKLTZ && MskOpc != LoongArchISD::XVMSKLTZ)
7140 if (!
LHS.hasOneUse())
7144 EVT SrcVT = Src.getValueType();
7151 : LoongArchISD::VALLZERO,
7221 SDLoc(
N), DAG, Subtarget))
7224 SDNode *AndNode =
N->getOperand(0).getNode();
7232 SDValue CmpInputValue =
N->getOperand(1);
7241 if (!CN || !CN->
isZero())
7243 AndInputValue1 = AndInputValue1.
getOperand(0);
7247 if (AndInputValue2 != CmpInputValue)
7280 TruncInputValue1, TruncInputValue2);
7282 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7301 return {V.getOperand(0),
cast<VTSDNode>(V.getOperand(1))->getVT()};
7322static std::tuple<unsigned, SDValue, EVT>
7326 unsigned Opc = Inner.getOpcode();
7331 if (Inner.getOperand(0) ==
X)
7332 return {
Opc, Inner.getOperand(1), ExtVT};
7333 if (Inner.getOperand(1) ==
X)
7334 return {
Opc, Inner.getOperand(0), ExtVT};
7338 if (Inner.getOperand(0) ==
X)
7339 return {
Opc, Inner.getOperand(1), ExtVT};
7361 EVT VT =
N->getValueType(0);
7373 bool BinIsTrueArm) ->
SDValue {
7381 if (Delta.getNode() ==
N)
7403 if (
SDValue R = TryFold(TrueV, FalseV,
true))
7405 if (
SDValue R = TryFold(FalseV, TrueV,
false))
7419 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7422 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7447 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7475 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7502 unsigned Sht =
LHS.getConstantOperandVal(1);
7506 if ((EleBits + Sht) == Subtarget.
getGRLen()) {
7516 EVT VT =
LHS.getValueType();
7540 DL, DAG, Subtarget))
7541 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7542 N->getOperand(0), V,
7547 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7548 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7564 EVT VT =
N->getValueType(0);
7567 if (TrueV == FalseV)
7598 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7599 {LHS, RHS, CC, TrueV, FalseV});
7604template <
unsigned N>
7608 bool IsSigned =
false) {
7612 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7613 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7615 ": argument out of range.");
7621template <
unsigned N>
7625 EVT ResTy =
Node->getValueType(0);
7629 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7630 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7632 ": argument out of range.");
7637 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7643 EVT ResTy =
Node->getValueType(0);
7651 EVT ResTy =
Node->getValueType(0);
7660template <
unsigned N>
7663 EVT ResTy =
Node->getValueType(0);
7668 ": argument out of range.");
7678template <
unsigned N>
7681 EVT ResTy =
Node->getValueType(0);
7686 ": argument out of range.");
7695template <
unsigned N>
7698 EVT ResTy =
Node->getValueType(0);
7703 ": argument out of range.");
7712template <
unsigned W>
7715 unsigned Imm =
N->getConstantOperandVal(2);
7717 const StringRef ErrorMsg =
"argument out of range";
7719 return DAG.
getUNDEF(
N->getValueType(0));
7725 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7733 switch (
N->getConstantOperandVal(0)) {
7736 case Intrinsic::loongarch_lsx_vadd_b:
7737 case Intrinsic::loongarch_lsx_vadd_h:
7738 case Intrinsic::loongarch_lsx_vadd_w:
7739 case Intrinsic::loongarch_lsx_vadd_d:
7740 case Intrinsic::loongarch_lasx_xvadd_b:
7741 case Intrinsic::loongarch_lasx_xvadd_h:
7742 case Intrinsic::loongarch_lasx_xvadd_w:
7743 case Intrinsic::loongarch_lasx_xvadd_d:
7746 case Intrinsic::loongarch_lsx_vaddi_bu:
7747 case Intrinsic::loongarch_lsx_vaddi_hu:
7748 case Intrinsic::loongarch_lsx_vaddi_wu:
7749 case Intrinsic::loongarch_lsx_vaddi_du:
7750 case Intrinsic::loongarch_lasx_xvaddi_bu:
7751 case Intrinsic::loongarch_lasx_xvaddi_hu:
7752 case Intrinsic::loongarch_lasx_xvaddi_wu:
7753 case Intrinsic::loongarch_lasx_xvaddi_du:
7756 case Intrinsic::loongarch_lsx_vsub_b:
7757 case Intrinsic::loongarch_lsx_vsub_h:
7758 case Intrinsic::loongarch_lsx_vsub_w:
7759 case Intrinsic::loongarch_lsx_vsub_d:
7760 case Intrinsic::loongarch_lasx_xvsub_b:
7761 case Intrinsic::loongarch_lasx_xvsub_h:
7762 case Intrinsic::loongarch_lasx_xvsub_w:
7763 case Intrinsic::loongarch_lasx_xvsub_d:
7766 case Intrinsic::loongarch_lsx_vsubi_bu:
7767 case Intrinsic::loongarch_lsx_vsubi_hu:
7768 case Intrinsic::loongarch_lsx_vsubi_wu:
7769 case Intrinsic::loongarch_lsx_vsubi_du:
7770 case Intrinsic::loongarch_lasx_xvsubi_bu:
7771 case Intrinsic::loongarch_lasx_xvsubi_hu:
7772 case Intrinsic::loongarch_lasx_xvsubi_wu:
7773 case Intrinsic::loongarch_lasx_xvsubi_du:
7776 case Intrinsic::loongarch_lsx_vneg_b:
7777 case Intrinsic::loongarch_lsx_vneg_h:
7778 case Intrinsic::loongarch_lsx_vneg_w:
7779 case Intrinsic::loongarch_lsx_vneg_d:
7780 case Intrinsic::loongarch_lasx_xvneg_b:
7781 case Intrinsic::loongarch_lasx_xvneg_h:
7782 case Intrinsic::loongarch_lasx_xvneg_w:
7783 case Intrinsic::loongarch_lasx_xvneg_d:
7787 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7789 SDLoc(
N),
N->getValueType(0)),
7791 case Intrinsic::loongarch_lsx_vmax_b:
7792 case Intrinsic::loongarch_lsx_vmax_h:
7793 case Intrinsic::loongarch_lsx_vmax_w:
7794 case Intrinsic::loongarch_lsx_vmax_d:
7795 case Intrinsic::loongarch_lasx_xvmax_b:
7796 case Intrinsic::loongarch_lasx_xvmax_h:
7797 case Intrinsic::loongarch_lasx_xvmax_w:
7798 case Intrinsic::loongarch_lasx_xvmax_d:
7801 case Intrinsic::loongarch_lsx_vmax_bu:
7802 case Intrinsic::loongarch_lsx_vmax_hu:
7803 case Intrinsic::loongarch_lsx_vmax_wu:
7804 case Intrinsic::loongarch_lsx_vmax_du:
7805 case Intrinsic::loongarch_lasx_xvmax_bu:
7806 case Intrinsic::loongarch_lasx_xvmax_hu:
7807 case Intrinsic::loongarch_lasx_xvmax_wu:
7808 case Intrinsic::loongarch_lasx_xvmax_du:
7811 case Intrinsic::loongarch_lsx_vmaxi_b:
7812 case Intrinsic::loongarch_lsx_vmaxi_h:
7813 case Intrinsic::loongarch_lsx_vmaxi_w:
7814 case Intrinsic::loongarch_lsx_vmaxi_d:
7815 case Intrinsic::loongarch_lasx_xvmaxi_b:
7816 case Intrinsic::loongarch_lasx_xvmaxi_h:
7817 case Intrinsic::loongarch_lasx_xvmaxi_w:
7818 case Intrinsic::loongarch_lasx_xvmaxi_d:
7821 case Intrinsic::loongarch_lsx_vmaxi_bu:
7822 case Intrinsic::loongarch_lsx_vmaxi_hu:
7823 case Intrinsic::loongarch_lsx_vmaxi_wu:
7824 case Intrinsic::loongarch_lsx_vmaxi_du:
7825 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7826 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7827 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7828 case Intrinsic::loongarch_lasx_xvmaxi_du:
7831 case Intrinsic::loongarch_lsx_vmin_b:
7832 case Intrinsic::loongarch_lsx_vmin_h:
7833 case Intrinsic::loongarch_lsx_vmin_w:
7834 case Intrinsic::loongarch_lsx_vmin_d:
7835 case Intrinsic::loongarch_lasx_xvmin_b:
7836 case Intrinsic::loongarch_lasx_xvmin_h:
7837 case Intrinsic::loongarch_lasx_xvmin_w:
7838 case Intrinsic::loongarch_lasx_xvmin_d:
7841 case Intrinsic::loongarch_lsx_vmin_bu:
7842 case Intrinsic::loongarch_lsx_vmin_hu:
7843 case Intrinsic::loongarch_lsx_vmin_wu:
7844 case Intrinsic::loongarch_lsx_vmin_du:
7845 case Intrinsic::loongarch_lasx_xvmin_bu:
7846 case Intrinsic::loongarch_lasx_xvmin_hu:
7847 case Intrinsic::loongarch_lasx_xvmin_wu:
7848 case Intrinsic::loongarch_lasx_xvmin_du:
7851 case Intrinsic::loongarch_lsx_vmini_b:
7852 case Intrinsic::loongarch_lsx_vmini_h:
7853 case Intrinsic::loongarch_lsx_vmini_w:
7854 case Intrinsic::loongarch_lsx_vmini_d:
7855 case Intrinsic::loongarch_lasx_xvmini_b:
7856 case Intrinsic::loongarch_lasx_xvmini_h:
7857 case Intrinsic::loongarch_lasx_xvmini_w:
7858 case Intrinsic::loongarch_lasx_xvmini_d:
7861 case Intrinsic::loongarch_lsx_vmini_bu:
7862 case Intrinsic::loongarch_lsx_vmini_hu:
7863 case Intrinsic::loongarch_lsx_vmini_wu:
7864 case Intrinsic::loongarch_lsx_vmini_du:
7865 case Intrinsic::loongarch_lasx_xvmini_bu:
7866 case Intrinsic::loongarch_lasx_xvmini_hu:
7867 case Intrinsic::loongarch_lasx_xvmini_wu:
7868 case Intrinsic::loongarch_lasx_xvmini_du:
7871 case Intrinsic::loongarch_lsx_vmul_b:
7872 case Intrinsic::loongarch_lsx_vmul_h:
7873 case Intrinsic::loongarch_lsx_vmul_w:
7874 case Intrinsic::loongarch_lsx_vmul_d:
7875 case Intrinsic::loongarch_lasx_xvmul_b:
7876 case Intrinsic::loongarch_lasx_xvmul_h:
7877 case Intrinsic::loongarch_lasx_xvmul_w:
7878 case Intrinsic::loongarch_lasx_xvmul_d:
7881 case Intrinsic::loongarch_lsx_vmadd_b:
7882 case Intrinsic::loongarch_lsx_vmadd_h:
7883 case Intrinsic::loongarch_lsx_vmadd_w:
7884 case Intrinsic::loongarch_lsx_vmadd_d:
7885 case Intrinsic::loongarch_lasx_xvmadd_b:
7886 case Intrinsic::loongarch_lasx_xvmadd_h:
7887 case Intrinsic::loongarch_lasx_xvmadd_w:
7888 case Intrinsic::loongarch_lasx_xvmadd_d: {
7889 EVT ResTy =
N->getValueType(0);
7894 case Intrinsic::loongarch_lsx_vmsub_b:
7895 case Intrinsic::loongarch_lsx_vmsub_h:
7896 case Intrinsic::loongarch_lsx_vmsub_w:
7897 case Intrinsic::loongarch_lsx_vmsub_d:
7898 case Intrinsic::loongarch_lasx_xvmsub_b:
7899 case Intrinsic::loongarch_lasx_xvmsub_h:
7900 case Intrinsic::loongarch_lasx_xvmsub_w:
7901 case Intrinsic::loongarch_lasx_xvmsub_d: {
7902 EVT ResTy =
N->getValueType(0);
7907 case Intrinsic::loongarch_lsx_vdiv_b:
7908 case Intrinsic::loongarch_lsx_vdiv_h:
7909 case Intrinsic::loongarch_lsx_vdiv_w:
7910 case Intrinsic::loongarch_lsx_vdiv_d:
7911 case Intrinsic::loongarch_lasx_xvdiv_b:
7912 case Intrinsic::loongarch_lasx_xvdiv_h:
7913 case Intrinsic::loongarch_lasx_xvdiv_w:
7914 case Intrinsic::loongarch_lasx_xvdiv_d:
7917 case Intrinsic::loongarch_lsx_vdiv_bu:
7918 case Intrinsic::loongarch_lsx_vdiv_hu:
7919 case Intrinsic::loongarch_lsx_vdiv_wu:
7920 case Intrinsic::loongarch_lsx_vdiv_du:
7921 case Intrinsic::loongarch_lasx_xvdiv_bu:
7922 case Intrinsic::loongarch_lasx_xvdiv_hu:
7923 case Intrinsic::loongarch_lasx_xvdiv_wu:
7924 case Intrinsic::loongarch_lasx_xvdiv_du:
7927 case Intrinsic::loongarch_lsx_vmod_b:
7928 case Intrinsic::loongarch_lsx_vmod_h:
7929 case Intrinsic::loongarch_lsx_vmod_w:
7930 case Intrinsic::loongarch_lsx_vmod_d:
7931 case Intrinsic::loongarch_lasx_xvmod_b:
7932 case Intrinsic::loongarch_lasx_xvmod_h:
7933 case Intrinsic::loongarch_lasx_xvmod_w:
7934 case Intrinsic::loongarch_lasx_xvmod_d:
7937 case Intrinsic::loongarch_lsx_vmod_bu:
7938 case Intrinsic::loongarch_lsx_vmod_hu:
7939 case Intrinsic::loongarch_lsx_vmod_wu:
7940 case Intrinsic::loongarch_lsx_vmod_du:
7941 case Intrinsic::loongarch_lasx_xvmod_bu:
7942 case Intrinsic::loongarch_lasx_xvmod_hu:
7943 case Intrinsic::loongarch_lasx_xvmod_wu:
7944 case Intrinsic::loongarch_lasx_xvmod_du:
7947 case Intrinsic::loongarch_lsx_vand_v:
7948 case Intrinsic::loongarch_lasx_xvand_v:
7951 case Intrinsic::loongarch_lsx_vor_v:
7952 case Intrinsic::loongarch_lasx_xvor_v:
7955 case Intrinsic::loongarch_lsx_vxor_v:
7956 case Intrinsic::loongarch_lasx_xvxor_v:
7959 case Intrinsic::loongarch_lsx_vnor_v:
7960 case Intrinsic::loongarch_lasx_xvnor_v: {
7965 case Intrinsic::loongarch_lsx_vandi_b:
7966 case Intrinsic::loongarch_lasx_xvandi_b:
7969 case Intrinsic::loongarch_lsx_vori_b:
7970 case Intrinsic::loongarch_lasx_xvori_b:
7973 case Intrinsic::loongarch_lsx_vxori_b:
7974 case Intrinsic::loongarch_lasx_xvxori_b:
7977 case Intrinsic::loongarch_lsx_vsll_b:
7978 case Intrinsic::loongarch_lsx_vsll_h:
7979 case Intrinsic::loongarch_lsx_vsll_w:
7980 case Intrinsic::loongarch_lsx_vsll_d:
7981 case Intrinsic::loongarch_lasx_xvsll_b:
7982 case Intrinsic::loongarch_lasx_xvsll_h:
7983 case Intrinsic::loongarch_lasx_xvsll_w:
7984 case Intrinsic::loongarch_lasx_xvsll_d:
7987 case Intrinsic::loongarch_lsx_vslli_b:
7988 case Intrinsic::loongarch_lasx_xvslli_b:
7991 case Intrinsic::loongarch_lsx_vslli_h:
7992 case Intrinsic::loongarch_lasx_xvslli_h:
7995 case Intrinsic::loongarch_lsx_vslli_w:
7996 case Intrinsic::loongarch_lasx_xvslli_w:
7999 case Intrinsic::loongarch_lsx_vslli_d:
8000 case Intrinsic::loongarch_lasx_xvslli_d:
8003 case Intrinsic::loongarch_lsx_vsrl_b:
8004 case Intrinsic::loongarch_lsx_vsrl_h:
8005 case Intrinsic::loongarch_lsx_vsrl_w:
8006 case Intrinsic::loongarch_lsx_vsrl_d:
8007 case Intrinsic::loongarch_lasx_xvsrl_b:
8008 case Intrinsic::loongarch_lasx_xvsrl_h:
8009 case Intrinsic::loongarch_lasx_xvsrl_w:
8010 case Intrinsic::loongarch_lasx_xvsrl_d:
8013 case Intrinsic::loongarch_lsx_vsrli_b:
8014 case Intrinsic::loongarch_lasx_xvsrli_b:
8017 case Intrinsic::loongarch_lsx_vsrli_h:
8018 case Intrinsic::loongarch_lasx_xvsrli_h:
8021 case Intrinsic::loongarch_lsx_vsrli_w:
8022 case Intrinsic::loongarch_lasx_xvsrli_w:
8025 case Intrinsic::loongarch_lsx_vsrli_d:
8026 case Intrinsic::loongarch_lasx_xvsrli_d:
8029 case Intrinsic::loongarch_lsx_vsra_b:
8030 case Intrinsic::loongarch_lsx_vsra_h:
8031 case Intrinsic::loongarch_lsx_vsra_w:
8032 case Intrinsic::loongarch_lsx_vsra_d:
8033 case Intrinsic::loongarch_lasx_xvsra_b:
8034 case Intrinsic::loongarch_lasx_xvsra_h:
8035 case Intrinsic::loongarch_lasx_xvsra_w:
8036 case Intrinsic::loongarch_lasx_xvsra_d:
8039 case Intrinsic::loongarch_lsx_vsrai_b:
8040 case Intrinsic::loongarch_lasx_xvsrai_b:
8043 case Intrinsic::loongarch_lsx_vsrai_h:
8044 case Intrinsic::loongarch_lasx_xvsrai_h:
8047 case Intrinsic::loongarch_lsx_vsrai_w:
8048 case Intrinsic::loongarch_lasx_xvsrai_w:
8051 case Intrinsic::loongarch_lsx_vsrai_d:
8052 case Intrinsic::loongarch_lasx_xvsrai_d:
8055 case Intrinsic::loongarch_lsx_vclz_b:
8056 case Intrinsic::loongarch_lsx_vclz_h:
8057 case Intrinsic::loongarch_lsx_vclz_w:
8058 case Intrinsic::loongarch_lsx_vclz_d:
8059 case Intrinsic::loongarch_lasx_xvclz_b:
8060 case Intrinsic::loongarch_lasx_xvclz_h:
8061 case Intrinsic::loongarch_lasx_xvclz_w:
8062 case Intrinsic::loongarch_lasx_xvclz_d:
8064 case Intrinsic::loongarch_lsx_vpcnt_b:
8065 case Intrinsic::loongarch_lsx_vpcnt_h:
8066 case Intrinsic::loongarch_lsx_vpcnt_w:
8067 case Intrinsic::loongarch_lsx_vpcnt_d:
8068 case Intrinsic::loongarch_lasx_xvpcnt_b:
8069 case Intrinsic::loongarch_lasx_xvpcnt_h:
8070 case Intrinsic::loongarch_lasx_xvpcnt_w:
8071 case Intrinsic::loongarch_lasx_xvpcnt_d:
8073 case Intrinsic::loongarch_lsx_vbitclr_b:
8074 case Intrinsic::loongarch_lsx_vbitclr_h:
8075 case Intrinsic::loongarch_lsx_vbitclr_w:
8076 case Intrinsic::loongarch_lsx_vbitclr_d:
8077 case Intrinsic::loongarch_lasx_xvbitclr_b:
8078 case Intrinsic::loongarch_lasx_xvbitclr_h:
8079 case Intrinsic::loongarch_lasx_xvbitclr_w:
8080 case Intrinsic::loongarch_lasx_xvbitclr_d:
8082 case Intrinsic::loongarch_lsx_vbitclri_b:
8083 case Intrinsic::loongarch_lasx_xvbitclri_b:
8085 case Intrinsic::loongarch_lsx_vbitclri_h:
8086 case Intrinsic::loongarch_lasx_xvbitclri_h:
8088 case Intrinsic::loongarch_lsx_vbitclri_w:
8089 case Intrinsic::loongarch_lasx_xvbitclri_w:
8091 case Intrinsic::loongarch_lsx_vbitclri_d:
8092 case Intrinsic::loongarch_lasx_xvbitclri_d:
8094 case Intrinsic::loongarch_lsx_vbitset_b:
8095 case Intrinsic::loongarch_lsx_vbitset_h:
8096 case Intrinsic::loongarch_lsx_vbitset_w:
8097 case Intrinsic::loongarch_lsx_vbitset_d:
8098 case Intrinsic::loongarch_lasx_xvbitset_b:
8099 case Intrinsic::loongarch_lasx_xvbitset_h:
8100 case Intrinsic::loongarch_lasx_xvbitset_w:
8101 case Intrinsic::loongarch_lasx_xvbitset_d: {
8102 EVT VecTy =
N->getValueType(0);
8108 case Intrinsic::loongarch_lsx_vbitseti_b:
8109 case Intrinsic::loongarch_lasx_xvbitseti_b:
8111 case Intrinsic::loongarch_lsx_vbitseti_h:
8112 case Intrinsic::loongarch_lasx_xvbitseti_h:
8114 case Intrinsic::loongarch_lsx_vbitseti_w:
8115 case Intrinsic::loongarch_lasx_xvbitseti_w:
8117 case Intrinsic::loongarch_lsx_vbitseti_d:
8118 case Intrinsic::loongarch_lasx_xvbitseti_d:
8120 case Intrinsic::loongarch_lsx_vbitrev_b:
8121 case Intrinsic::loongarch_lsx_vbitrev_h:
8122 case Intrinsic::loongarch_lsx_vbitrev_w:
8123 case Intrinsic::loongarch_lsx_vbitrev_d:
8124 case Intrinsic::loongarch_lasx_xvbitrev_b:
8125 case Intrinsic::loongarch_lasx_xvbitrev_h:
8126 case Intrinsic::loongarch_lasx_xvbitrev_w:
8127 case Intrinsic::loongarch_lasx_xvbitrev_d: {
8128 EVT VecTy =
N->getValueType(0);
8134 case Intrinsic::loongarch_lsx_vbitrevi_b:
8135 case Intrinsic::loongarch_lasx_xvbitrevi_b:
8137 case Intrinsic::loongarch_lsx_vbitrevi_h:
8138 case Intrinsic::loongarch_lasx_xvbitrevi_h:
8140 case Intrinsic::loongarch_lsx_vbitrevi_w:
8141 case Intrinsic::loongarch_lasx_xvbitrevi_w:
8143 case Intrinsic::loongarch_lsx_vbitrevi_d:
8144 case Intrinsic::loongarch_lasx_xvbitrevi_d:
8146 case Intrinsic::loongarch_lsx_vfadd_s:
8147 case Intrinsic::loongarch_lsx_vfadd_d:
8148 case Intrinsic::loongarch_lasx_xvfadd_s:
8149 case Intrinsic::loongarch_lasx_xvfadd_d:
8152 case Intrinsic::loongarch_lsx_vfsub_s:
8153 case Intrinsic::loongarch_lsx_vfsub_d:
8154 case Intrinsic::loongarch_lasx_xvfsub_s:
8155 case Intrinsic::loongarch_lasx_xvfsub_d:
8158 case Intrinsic::loongarch_lsx_vfmul_s:
8159 case Intrinsic::loongarch_lsx_vfmul_d:
8160 case Intrinsic::loongarch_lasx_xvfmul_s:
8161 case Intrinsic::loongarch_lasx_xvfmul_d:
8164 case Intrinsic::loongarch_lsx_vfdiv_s:
8165 case Intrinsic::loongarch_lsx_vfdiv_d:
8166 case Intrinsic::loongarch_lasx_xvfdiv_s:
8167 case Intrinsic::loongarch_lasx_xvfdiv_d:
8170 case Intrinsic::loongarch_lsx_vfmadd_s:
8171 case Intrinsic::loongarch_lsx_vfmadd_d:
8172 case Intrinsic::loongarch_lasx_xvfmadd_s:
8173 case Intrinsic::loongarch_lasx_xvfmadd_d:
8175 N->getOperand(2),
N->getOperand(3));
8176 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
8178 N->getOperand(1),
N->getOperand(2),
8180 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
8181 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
8183 N->getOperand(1),
N->getOperand(2),
8185 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
8186 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
8188 N->getOperand(1),
N->getOperand(2),
8190 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
8192 N->getOperand(1),
N->getOperand(2),
8194 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
8195 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
8196 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
8197 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
8198 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
8199 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
8200 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
8201 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
8202 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
8205 case Intrinsic::loongarch_lsx_vreplve_b:
8206 case Intrinsic::loongarch_lsx_vreplve_h:
8207 case Intrinsic::loongarch_lsx_vreplve_w:
8208 case Intrinsic::loongarch_lsx_vreplve_d:
8209 case Intrinsic::loongarch_lasx_xvreplve_b:
8210 case Intrinsic::loongarch_lasx_xvreplve_h:
8211 case Intrinsic::loongarch_lasx_xvreplve_w:
8212 case Intrinsic::loongarch_lasx_xvreplve_d:
8213 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
8217 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8221 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8222 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8226 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8230 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8234 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8235 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8239 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8243 case Intrinsic::loongarch_lsx_bz_b:
8244 case Intrinsic::loongarch_lsx_bz_h:
8245 case Intrinsic::loongarch_lsx_bz_w:
8246 case Intrinsic::loongarch_lsx_bz_d:
8247 case Intrinsic::loongarch_lasx_xbz_b:
8248 case Intrinsic::loongarch_lasx_xbz_h:
8249 case Intrinsic::loongarch_lasx_xbz_w:
8250 case Intrinsic::loongarch_lasx_xbz_d:
8252 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8255 case Intrinsic::loongarch_lsx_bz_v:
8256 case Intrinsic::loongarch_lasx_xbz_v:
8258 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8261 case Intrinsic::loongarch_lsx_bnz_b:
8262 case Intrinsic::loongarch_lsx_bnz_h:
8263 case Intrinsic::loongarch_lsx_bnz_w:
8264 case Intrinsic::loongarch_lsx_bnz_d:
8265 case Intrinsic::loongarch_lasx_xbnz_b:
8266 case Intrinsic::loongarch_lasx_xbnz_h:
8267 case Intrinsic::loongarch_lasx_xbnz_w:
8268 case Intrinsic::loongarch_lasx_xbnz_d:
8270 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8273 case Intrinsic::loongarch_lsx_bnz_v:
8274 case Intrinsic::loongarch_lasx_xbnz_v:
8276 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8279 case Intrinsic::loongarch_lasx_concat_128_s:
8280 case Intrinsic::loongarch_lasx_concat_128_d:
8281 case Intrinsic::loongarch_lasx_concat_128:
8283 N->getOperand(1),
N->getOperand(2));
8295 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8307 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8309 "Unexpected value type!");
8318 MVT VT =
N->getSimpleValueType(0);
8339 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8352 APInt V =
C->getValueAPF().bitcastToAPInt();
8367 MVT VT =
N->getSimpleValueType(0);
8426 EVT VT =
N->getValueType(0);
8428 EVT SrcVT = Src.getValueType();
8434 if (SrcEltBits >= DstEltBits)
8441 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8453 unsigned BlockBits) {
8455 MVT DstVT =
N->getSimpleValueType(0);
8457 MVT SrcVT = Src.getSimpleValueType();
8464 Src.getOperand(0).getValueType() == BlockVT) {
8465 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8467 }
else if (SrcBits > BlockBits) {
8469 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8474 BlockBits = SrcBits;
8481 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8486 if (BlockBits == 256) {
8496 if (Blocks.
size() == 1)
8506 EVT VT =
N->getValueType(0);
8508 EVT SrcVT = Src.getValueType();
8514 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8517 if (SrcEltBits <= DstEltBits)
8520 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8530 if (VT != MVT::f32 && VT != MVT::f64)
8532 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8534 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8566 EVT VT =
N->getValueType(0);
8583 if (!Subtarget.hasExtLSX())
8587 EVT DstVT =
N->getValueType(0);
8589 EVT SrcVT = Src.getValueType();
8599 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8604 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8607 if (DstEltBits < 32) {
8613 if (SrcEltBits != 64 || DstEltBits != 32)
8618 if (Subtarget.hasExtLASX())
8679 Subtarget.hasExtLASX() && N1.
hasOneUse())
8691 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8701 EVT VT =
N.getValueType();
8718 switch (
N.getOpcode()) {
8734 EVT VT =
N->getValueType(0);
8742 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
8747 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
8749 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
8761 EVT VT =
N->getValueType(0);
8763 if (VT.
isVector() &&
N->getNumOperands() == 2)
8776 EVT VT =
N->getValueType(0);
8788 SDValue TrueVal =
N->getOperand(1);
8789 SDValue FalseVal =
N->getOperand(2);
8823 if (FalseVal.getOpcode() !=
ISD::ADD)
8826 SDValue Add0 = FalseVal.getOperand(0);
8827 SDValue Add1 = FalseVal.getOperand(1);
8897 : LoongArchISD::VSRAR,
8904 switch (
N->getOpcode()) {
8936 case LoongArchISD::BITREV_W:
8938 case LoongArchISD::BR_CC:
8940 case LoongArchISD::SELECT_CC:
8944 case LoongArchISD::MOVGR2FR_W_LA64:
8946 case LoongArchISD::MOVFR2GR_S_LA64:
8948 case LoongArchISD::CRC_W_B_W:
8949 case LoongArchISD::CRC_W_H_W:
8950 case LoongArchISD::CRCC_W_B_W:
8951 case LoongArchISD::CRCC_W_H_W:
8952 case LoongArchISD::VMSKLTZ:
8953 case LoongArchISD::XVMSKLTZ:
8955 case LoongArchISD::SPLIT_PAIR_F64:
8957 case LoongArchISD::VANDN:
8963 case LoongArchISD::VPACKEV:
8964 case LoongArchISD::VPERMI:
8990 MF->
insert(It, BreakMBB);
8994 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8995 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
9007 MBB->addSuccessor(BreakMBB);
9008 MBB->addSuccessor(SinkMBB);
9014 BreakMBB->addSuccessor(SinkMBB);
9026 switch (
MI.getOpcode()) {
9029 case LoongArch::PseudoVBZ:
9030 CondOpc = LoongArch::VSETEQZ_V;
9032 case LoongArch::PseudoVBZ_B:
9033 CondOpc = LoongArch::VSETANYEQZ_B;
9035 case LoongArch::PseudoVBZ_H:
9036 CondOpc = LoongArch::VSETANYEQZ_H;
9038 case LoongArch::PseudoVBZ_W:
9039 CondOpc = LoongArch::VSETANYEQZ_W;
9041 case LoongArch::PseudoVBZ_D:
9042 CondOpc = LoongArch::VSETANYEQZ_D;
9044 case LoongArch::PseudoVBNZ:
9045 CondOpc = LoongArch::VSETNEZ_V;
9047 case LoongArch::PseudoVBNZ_B:
9048 CondOpc = LoongArch::VSETALLNEZ_B;
9050 case LoongArch::PseudoVBNZ_H:
9051 CondOpc = LoongArch::VSETALLNEZ_H;
9053 case LoongArch::PseudoVBNZ_W:
9054 CondOpc = LoongArch::VSETALLNEZ_W;
9056 case LoongArch::PseudoVBNZ_D:
9057 CondOpc = LoongArch::VSETALLNEZ_D;
9059 case LoongArch::PseudoXVBZ:
9060 CondOpc = LoongArch::XVSETEQZ_V;
9062 case LoongArch::PseudoXVBZ_B:
9063 CondOpc = LoongArch::XVSETANYEQZ_B;
9065 case LoongArch::PseudoXVBZ_H:
9066 CondOpc = LoongArch::XVSETANYEQZ_H;
9068 case LoongArch::PseudoXVBZ_W:
9069 CondOpc = LoongArch::XVSETANYEQZ_W;
9071 case LoongArch::PseudoXVBZ_D:
9072 CondOpc = LoongArch::XVSETANYEQZ_D;
9074 case LoongArch::PseudoXVBNZ:
9075 CondOpc = LoongArch::XVSETNEZ_V;
9077 case LoongArch::PseudoXVBNZ_B:
9078 CondOpc = LoongArch::XVSETALLNEZ_B;
9080 case LoongArch::PseudoXVBNZ_H:
9081 CondOpc = LoongArch::XVSETALLNEZ_H;
9083 case LoongArch::PseudoXVBNZ_W:
9084 CondOpc = LoongArch::XVSETALLNEZ_W;
9086 case LoongArch::PseudoXVBNZ_D:
9087 CondOpc = LoongArch::XVSETALLNEZ_D;
9102 F->insert(It, FalseBB);
9103 F->insert(It, TrueBB);
9104 F->insert(It, SinkBB);
9107 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
9136 MI.getOperand(0).getReg())
9143 MI.eraseFromParent();
9151 unsigned BroadcastOp;
9153 switch (
MI.getOpcode()) {
9156 case LoongArch::PseudoXVINSGR2VR_B:
9158 BroadcastOp = LoongArch::XVREPLGR2VR_B;
9159 InsOp = LoongArch::XVEXTRINS_B;
9161 case LoongArch::PseudoXVINSGR2VR_H:
9163 BroadcastOp = LoongArch::XVREPLGR2VR_H;
9164 InsOp = LoongArch::XVEXTRINS_H;
9176 unsigned Idx =
MI.getOperand(3).getImm();
9184 .
addReg(XSrc, {}, LoongArch::sub_128);
9186 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
9187 : LoongArch::VINSGR2VR_B),
9195 .
addImm(LoongArch::sub_128);
9202 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
9205 .
addImm(Idx >= HalfSize ? 48 : 18);
9210 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
9213 MI.eraseFromParent();
9220 assert(Subtarget.hasExtLSX());
9228 unsigned BroadcastOp, CTOp, PickOp;
9229 switch (
MI.getOpcode()) {
9232 case LoongArch::PseudoCTPOP_B:
9233 BroadcastOp = LoongArch::VREPLGR2VR_B;
9234 CTOp = LoongArch::VPCNT_B;
9235 PickOp = LoongArch::VPICKVE2GR_B;
9237 case LoongArch::PseudoCTPOP_H:
9238 case LoongArch::PseudoCTPOP_H_LA32:
9239 BroadcastOp = LoongArch::VREPLGR2VR_H;
9240 CTOp = LoongArch::VPCNT_H;
9241 PickOp = LoongArch::VPICKVE2GR_H;
9243 case LoongArch::PseudoCTPOP_W:
9244 case LoongArch::PseudoCTPOP_W_LA32:
9245 BroadcastOp = LoongArch::VREPLGR2VR_W;
9246 CTOp = LoongArch::VPCNT_W;
9247 PickOp = LoongArch::VPICKVE2GR_W;
9249 case LoongArch::PseudoCTPOP_D:
9250 BroadcastOp = LoongArch::VREPLGR2VR_D;
9251 CTOp = LoongArch::VPCNT_D;
9252 PickOp = LoongArch::VPICKVE2GR_D;
9262 MI.eraseFromParent();
9276 unsigned EleBits = 8;
9277 unsigned NotOpc = 0;
9280 switch (
MI.getOpcode()) {
9283 case LoongArch::PseudoVMSKLTZ_B:
9284 MskOpc = LoongArch::VMSKLTZ_B;
9286 case LoongArch::PseudoVMSKLTZ_H:
9287 MskOpc = LoongArch::VMSKLTZ_H;
9290 case LoongArch::PseudoVMSKLTZ_W:
9291 MskOpc = LoongArch::VMSKLTZ_W;
9294 case LoongArch::PseudoVMSKLTZ_D:
9295 MskOpc = LoongArch::VMSKLTZ_D;
9298 case LoongArch::PseudoVMSKGEZ_B:
9299 MskOpc = LoongArch::VMSKGEZ_B;
9301 case LoongArch::PseudoVMSKEQZ_B:
9302 MskOpc = LoongArch::VMSKNZ_B;
9303 NotOpc = LoongArch::VNOR_V;
9305 case LoongArch::PseudoVMSKNEZ_B:
9306 MskOpc = LoongArch::VMSKNZ_B;
9308 case LoongArch::PseudoXVMSKLTZ_B:
9309 MskOpc = LoongArch::XVMSKLTZ_B;
9310 RC = &LoongArch::LASX256RegClass;
9312 case LoongArch::PseudoXVMSKLTZ_H:
9313 MskOpc = LoongArch::XVMSKLTZ_H;
9314 RC = &LoongArch::LASX256RegClass;
9317 case LoongArch::PseudoXVMSKLTZ_W:
9318 MskOpc = LoongArch::XVMSKLTZ_W;
9319 RC = &LoongArch::LASX256RegClass;
9322 case LoongArch::PseudoXVMSKLTZ_D:
9323 MskOpc = LoongArch::XVMSKLTZ_D;
9324 RC = &LoongArch::LASX256RegClass;
9327 case LoongArch::PseudoXVMSKGEZ_B:
9328 MskOpc = LoongArch::XVMSKGEZ_B;
9329 RC = &LoongArch::LASX256RegClass;
9331 case LoongArch::PseudoXVMSKEQZ_B:
9332 MskOpc = LoongArch::XVMSKNZ_B;
9333 NotOpc = LoongArch::XVNOR_V;
9334 RC = &LoongArch::LASX256RegClass;
9336 case LoongArch::PseudoXVMSKNEZ_B:
9337 MskOpc = LoongArch::XVMSKNZ_B;
9338 RC = &LoongArch::LASX256RegClass;
9353 if (
TRI->getRegSizeInBits(*RC) > 128) {
9363 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
9364 : LoongArch::BSTRINS_W),
9368 .
addImm(256 / EleBits - 1)
9376 MI.eraseFromParent();
9383 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9384 "Unexpected instruction");
9396 MI.eraseFromParent();
9403 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9404 "Unexpected instruction");
9420 MI.eraseFromParent();
9425 switch (
MI.getOpcode()) {
9428 case LoongArch::Select_GPR_Using_CC_GPR:
9464 if (
MI.getOperand(2).isReg())
9465 RHS =
MI.getOperand(2).getReg();
9466 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9470 SelectDests.
insert(
MI.getOperand(0).getReg());
9474 SequenceMBBI !=
E; ++SequenceMBBI) {
9475 if (SequenceMBBI->isDebugInstr())
9478 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9479 !SequenceMBBI->getOperand(2).isReg() ||
9480 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9481 SequenceMBBI->getOperand(3).getImm() != CC ||
9482 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9483 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9485 LastSelectPseudo = &*SequenceMBBI;
9487 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9490 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9491 SequenceMBBI->mayLoadOrStore() ||
9492 SequenceMBBI->usesCustomInsertionHook())
9495 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9510 F->insert(
I, IfFalseMBB);
9511 F->insert(
I, TailMBB);
9514 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9520 TailMBB->
push_back(DebugInstr->removeFromParent());
9524 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9534 if (
MI.getOperand(2).isImm())
9546 auto SelectMBBI =
MI.getIterator();
9547 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9549 while (SelectMBBI != SelectEnd) {
9550 auto Next = std::next(SelectMBBI);
9554 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9555 .
addReg(SelectMBBI->getOperand(4).getReg())
9557 .
addReg(SelectMBBI->getOperand(5).getReg())
9564 F->getProperties().resetNoPHIs();
9570 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9573 switch (
MI.getOpcode()) {
9576 case LoongArch::DIV_W:
9577 case LoongArch::DIV_WU:
9578 case LoongArch::MOD_W:
9579 case LoongArch::MOD_WU:
9580 case LoongArch::DIV_D:
9581 case LoongArch::DIV_DU:
9582 case LoongArch::MOD_D:
9583 case LoongArch::MOD_DU:
9586 case LoongArch::WRFCSR: {
9588 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9589 .
addReg(
MI.getOperand(1).getReg());
9590 MI.eraseFromParent();
9593 case LoongArch::RDFCSR: {
9594 MachineInstr *ReadFCSR =
9596 MI.getOperand(0).getReg())
9597 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9599 MI.eraseFromParent();
9602 case LoongArch::Select_GPR_Using_CC_GPR:
9604 case LoongArch::BuildPairF64Pseudo:
9606 case LoongArch::SplitPairF64Pseudo:
9608 case LoongArch::PseudoVBZ:
9609 case LoongArch::PseudoVBZ_B:
9610 case LoongArch::PseudoVBZ_H:
9611 case LoongArch::PseudoVBZ_W:
9612 case LoongArch::PseudoVBZ_D:
9613 case LoongArch::PseudoVBNZ:
9614 case LoongArch::PseudoVBNZ_B:
9615 case LoongArch::PseudoVBNZ_H:
9616 case LoongArch::PseudoVBNZ_W:
9617 case LoongArch::PseudoVBNZ_D:
9618 case LoongArch::PseudoXVBZ:
9619 case LoongArch::PseudoXVBZ_B:
9620 case LoongArch::PseudoXVBZ_H:
9621 case LoongArch::PseudoXVBZ_W:
9622 case LoongArch::PseudoXVBZ_D:
9623 case LoongArch::PseudoXVBNZ:
9624 case LoongArch::PseudoXVBNZ_B:
9625 case LoongArch::PseudoXVBNZ_H:
9626 case LoongArch::PseudoXVBNZ_W:
9627 case LoongArch::PseudoXVBNZ_D:
9629 case LoongArch::PseudoXVINSGR2VR_B:
9630 case LoongArch::PseudoXVINSGR2VR_H:
9632 case LoongArch::PseudoCTPOP_B:
9633 case LoongArch::PseudoCTPOP_H:
9634 case LoongArch::PseudoCTPOP_W:
9635 case LoongArch::PseudoCTPOP_D:
9636 case LoongArch::PseudoCTPOP_H_LA32:
9637 case LoongArch::PseudoCTPOP_W_LA32:
9639 case LoongArch::PseudoVMSKLTZ_B:
9640 case LoongArch::PseudoVMSKLTZ_H:
9641 case LoongArch::PseudoVMSKLTZ_W:
9642 case LoongArch::PseudoVMSKLTZ_D:
9643 case LoongArch::PseudoVMSKGEZ_B:
9644 case LoongArch::PseudoVMSKEQZ_B:
9645 case LoongArch::PseudoVMSKNEZ_B:
9646 case LoongArch::PseudoXVMSKLTZ_B:
9647 case LoongArch::PseudoXVMSKLTZ_H:
9648 case LoongArch::PseudoXVMSKLTZ_W:
9649 case LoongArch::PseudoXVMSKLTZ_D:
9650 case LoongArch::PseudoXVMSKGEZ_B:
9651 case LoongArch::PseudoXVMSKEQZ_B:
9652 case LoongArch::PseudoXVMSKNEZ_B:
9654 case TargetOpcode::STATEPOINT:
9660 MI.addOperand(*
MI.getMF(),
9662 LoongArch::R1,
true,
9665 if (!Subtarget.is64Bit())
9668 case LoongArch::PROBED_STACKALLOC_DYN:
9675 unsigned *
Fast)
const {
9676 if (!Subtarget.hasUAL())
9694 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9695 LoongArch::R10, LoongArch::R11};
9710 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9711 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9712 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9713 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9714 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9715 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9721 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9722 LoongArch::F6, LoongArch::F7};
9725 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9726 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9729 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9730 LoongArch::VR6, LoongArch::VR7};
9733 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9734 LoongArch::XR6, LoongArch::XR7};
9737 switch (State.getCallingConv()) {
9739 if (!State.isVarArg())
9743 return State.AllocateReg(
ArgGPRs);
9751 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9753 unsigned GRLenInBytes = GRLen / 8;
9764 State.AllocateStack(GRLenInBytes, StackAlign),
9767 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9778 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9786 unsigned ValNo,
MVT ValVT,
9789 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9790 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9791 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9796 if (IsRet && ValNo > 1)
9800 bool UseGPRForFloat =
true;
9810 UseGPRForFloat = ArgFlags.
isVarArg();
9823 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9826 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9827 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9829 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9835 State.getPendingArgFlags();
9838 "PendingLocs and PendingArgFlags out of sync");
9842 UseGPRForFloat =
true;
9844 if (UseGPRForFloat && ValVT == MVT::f32) {
9847 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9850 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9853 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9895 PendingLocs.
size() <= 2) {
9896 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9901 PendingLocs.
clear();
9902 PendingArgFlags.
clear();
9909 unsigned StoreSizeBytes = GRLen / 8;
9912 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9914 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9918 UseGPRForFloat =
false;
9919 StoreSizeBytes = 16;
9920 StackAlign =
Align(16);
9923 UseGPRForFloat =
false;
9924 StoreSizeBytes = 32;
9925 StackAlign =
Align(32);
9931 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9935 if (!PendingLocs.
empty()) {
9937 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9938 for (
auto &It : PendingLocs) {
9940 It.convertToReg(
Reg);
9945 PendingLocs.clear();
9946 PendingArgFlags.
clear();
9949 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9950 "Expected an GRLenVT at this stage");
9967void LoongArchTargetLowering::analyzeInputArgs(
9970 LoongArchCCAssignFn Fn)
const {
9972 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9973 MVT ArgVT = Ins[i].VT;
9974 Type *ArgTy =
nullptr;
9976 ArgTy = FType->getReturnType();
9977 else if (Ins[i].isOrigArg())
9978 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9982 CCInfo, IsRet, ArgTy)) {
9983 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9990void LoongArchTargetLowering::analyzeOutputArgs(
9993 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9994 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9995 MVT ArgVT = Outs[i].VT;
9996 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
10000 CCInfo, IsRet, OrigTy)) {
10001 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
10020 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
10042 if (In.isOrigArg()) {
10047 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
10048 (
BitWidth < 32 && In.Flags.isZExt())) {
10098 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10111 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10115 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
10129 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
10141 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
10145 LoongArch::R23, LoongArch::R24, LoongArch::R25,
10146 LoongArch::R26, LoongArch::R27, LoongArch::R28,
10147 LoongArch::R29, LoongArch::R30, LoongArch::R31};
10154 if (LocVT == MVT::f32) {
10157 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
10158 LoongArch::F26, LoongArch::F27};
10165 if (LocVT == MVT::f64) {
10168 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
10169 LoongArch::F30_64, LoongArch::F31_64};
10188 switch (CallConv) {
10200 "GHC calling convention requires the F and D extensions");
10205 MVT GRLenVT = Subtarget.getGRLenVT();
10206 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
10215 return CI->isMustTailCall();
10220 std::vector<SDValue> OutChains;
10229 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
10231 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10248 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10257 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10258 assert(ArgPartOffset == 0);
10259 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10261 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10285 int VaArgOffset, VarArgsSaveSize;
10289 if (ArgRegs.
size() == Idx) {
10291 VarArgsSaveSize = 0;
10293 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10294 VaArgOffset = -VarArgsSaveSize;
10300 LoongArchFI->setVarArgsFrameIndex(FI);
10308 VarArgsSaveSize += GRLenInBytes;
10313 for (
unsigned I = Idx;
I < ArgRegs.
size();
10314 ++
I, VaArgOffset += GRLenInBytes) {
10315 const Register Reg = RegInfo.createVirtualRegister(RC);
10316 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10324 ->setValue((
Value *)
nullptr);
10325 OutChains.push_back(
Store);
10327 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10332 if (!OutChains.empty()) {
10333 OutChains.push_back(Chain);
10348 if (
N->getNumValues() != 1)
10350 if (!
N->hasNUsesOfValue(1, 0))
10353 SDNode *Copy = *
N->user_begin();
10359 if (Copy->getGluedNode())
10363 bool HasRet =
false;
10365 if (
Node->getOpcode() != LoongArchISD::RET)
10373 Chain = Copy->getOperand(0);
10378bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10382 auto CalleeCC = CLI.CallConv;
10383 auto &Outs = CLI.Outs;
10385 auto CallerCC = Caller.getCallingConv();
10387 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10396 for (
auto &Arg : Outs)
10397 if (Arg.Flags.isByVal())
10413 for (
auto &VA : ArgLocs)
10419 auto IsCallerStructRet = Caller.hasStructRetAttr();
10420 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10421 if (IsCallerStructRet || IsCalleeStructRet)
10426 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10427 if (CalleeCC != CallerCC) {
10428 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10429 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10455 MVT GRLenVT = Subtarget.getGRLenVT();
10467 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10471 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10477 "site marked musttail");
10484 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10486 if (!Flags.isByVal())
10490 unsigned Size = Flags.getByValSize();
10491 Align Alignment = Flags.getNonZeroByValAlign();
10498 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10500 false,
nullptr, std::nullopt,
10512 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10515 SDValue ArgValue = OutVals[OutIdx];
10523 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10524 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10536 if (!StackPtr.getNode())
10548 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10562 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10582 const Argument *FormalArg =
nullptr;
10583 unsigned FilteredIdx = 0;
10584 for (
const auto &CallArg : CLI.
CB->
args()) {
10585 if (CallArg->getType()->isEmptyTy())
10587 if (FilteredIdx == CallArgIdx) {
10596 unsigned FormalArgIdx = CallArgIdx;
10598 FormalArgIdx = FormalArg->
getArgNo();
10602 if (Arg.getType()->isEmptyTy())
10604 if (FilteredIdx == CallArgIdx) {
10605 FormalArgIdx = Arg.getArgNo();
10618 SDValue IncomingPtr = CopyOp;
10635 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10636 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10637 SDValue PartValue = OutVals[OutIdx + 1];
10638 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10649 ArgValue = IncomingPtr;
10653 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10665 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10666 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10667 assert(ArgPartOffset == 0);
10672 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10673 SDValue PartValue = OutVals[OutIdx + 1];
10674 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10686 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10688 for (
const auto &Part : Parts) {
10689 SDValue PartValue = Part.first;
10690 SDValue PartOffset = Part.second;
10697 ArgValue = SpillSlot;
10704 if (Flags.isByVal())
10705 ArgValue = ByValArgs[j++];
10713 "Tail call not allowed if stack is used for passing parameters");
10716 if (!StackPtr.getNode())
10729 if (!MemOpChains.
empty())
10735 for (
auto &Reg : RegsToPass) {
10736 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10758 Ops.push_back(Chain);
10759 Ops.push_back(Callee);
10763 for (
auto &Reg : RegsToPass)
10764 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10769 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10770 assert(Mask &&
"Missing call preserved mask for calling convention");
10776 Ops.push_back(Glue);
10785 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10788 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10791 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10792 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10814 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10817 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10818 auto &VA = RVLocs[i];
10826 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10827 assert(VA.needsCustom());
10832 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10833 RetValue, RetValue2);
10846 const Type *RetTy)
const {
10848 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10850 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10854 Outs[i].Flags, CCInfo,
true,
nullptr))
10880 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10881 SDValue Val = OutVals[OutIdx];
10890 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10894 Register RegHi = RVLocs[++i].getLocReg();
10919 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10927 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10928 uint64_t RequiredImm = 0;
10930 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10932 RequiredImm = (0b10101 << 8) | (V >> 8);
10933 return {
true, RequiredImm};
10934 }
else if (SplatBitSize == 32) {
10936 if (!(V & 0xFFFF00FF)) {
10937 RequiredImm = (0b10001 << 8) | (V >> 8);
10938 return {
true, RequiredImm};
10941 if (!(V & 0xFF00FFFF)) {
10942 RequiredImm = (0b10010 << 8) | (V >> 16);
10943 return {
true, RequiredImm};
10946 if (!(V & 0x00FFFFFF)) {
10947 RequiredImm = (0b10011 << 8) | (V >> 24);
10948 return {
true, RequiredImm};
10951 if ((V & 0xFFFF00FF) == 0xFF) {
10952 RequiredImm = (0b10110 << 8) | (V >> 8);
10953 return {
true, RequiredImm};
10956 if ((V & 0xFF00FFFF) == 0xFFFF) {
10957 RequiredImm = (0b10111 << 8) | (V >> 16);
10958 return {
true, RequiredImm};
10961 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
10963 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10964 return {
true, RequiredImm};
10966 }
else if (SplatBitSize == 64) {
10968 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
10969 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
10971 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10972 return {
true, RequiredImm};
10975 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
10976 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
10978 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
10979 return {
true, RequiredImm};
10982 auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {
10984 for (
int i = 0; i < 8; ++i) {
10986 if (
byte == 0 ||
byte == 0xFF)
10987 res |= ((
byte & 1) << i);
10992 return {
true, res};
10994 auto [IsSame, Suffix] = sameBitsPreByte(V);
10996 RequiredImm = (0b11001 << 8) | Suffix;
10997 return {
true, RequiredImm};
11000 return {
false, RequiredImm};
11005 if (!Subtarget.hasExtLSX())
11008 if (VT == MVT::f32) {
11009 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
11010 return (masked == 0x3e000000 || masked == 0x40000000);
11013 if (VT == MVT::f64) {
11014 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
11015 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
11021bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &
Imm,
EVT VT,
11022 bool ForCodeSize)
const {
11024 if (VT == MVT::f32 && !Subtarget.hasBasicF())
11026 if (VT == MVT::f64 && !Subtarget.hasBasicD())
11039bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
11049 Type *Ty =
I->getOperand(0)->getType();
11051 unsigned Size = Ty->getIntegerBitWidth();
11071 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
11076 if (Subtarget.hasExtLASX())
11078 else if (Subtarget.hasExtLSX())
11085 EVT VT =
Y.getValueType();
11088 return Subtarget.hasExtLSX() && VT.
isInteger();
11099 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
11100 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
11101 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
11102 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
11105 Info.memVT = MVT::i32;
11106 Info.ptrVal =
I.getArgOperand(0);
11108 Info.align =
Align(4);
11127 "Unable to expand");
11128 unsigned MinWordSize = 4;
11140 Value *AlignedAddr = Builder.CreateIntrinsic(
11141 Intrinsic::ptrmask, {PtrTy, IntTy},
11142 {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))},
nullptr,
11145 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
11146 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
11147 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
11148 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
11149 Value *Mask = Builder.CreateShl(
11150 ConstantInt::get(WordType,
11151 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
11153 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
11154 Value *ValOperand_Shifted =
11155 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
11156 ShiftAmt,
"ValOperand_Shifted");
11159 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
11161 NewOperand = ValOperand_Shifted;
11164 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
11167 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
11168 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
11169 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
11188 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
11196 if (Subtarget.hasLAMCAS()) {
11218 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
11220 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
11222 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
11224 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
11226 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
11228 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
11230 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
11232 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11242 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11244 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11246 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11248 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11250 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11252 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11254 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11256 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11268 if (Subtarget.hasLAMCAS())
11280 unsigned GRLen = Subtarget.getGRLen();
11282 Value *FailureOrdering =
11283 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t
>(FailOrd));
11284 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11286 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11287 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11288 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11289 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11292 Value *Result = Builder.CreateIntrinsic(
11293 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11295 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11311 Builder.CreateNot(Mask,
"Inv_Mask"),
11318 unsigned GRLen = Subtarget.getGRLen();
11320 Builder.getIntN(GRLen,
static_cast<uint64_t
>(AI->
getOrdering()));
11327 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11328 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11329 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11342 unsigned ValWidth =
11345 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11346 Result = Builder.CreateCall(LlwOpScwLoop,
11347 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11350 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11354 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11378 return LoongArch::R4;
11383 return LoongArch::R5;
11394 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11395 return RefinementSteps;
11400 assert(Subtarget.hasFrecipe() &&
11401 "Reciprocal estimate queried on unsupported target");
11412 return Subtarget.hasBasicD();
11416 return Subtarget.hasExtLSX();
11420 return Subtarget.hasExtLASX();
11429 int &RefinementSteps,
11430 bool &UseOneConstNR,
11431 bool Reciprocal)
const {
11433 "Enabled should never be Disabled here");
11435 if (!Subtarget.hasFrecipe())
11450 UseOneConstNR =
false;
11456 if (Reciprocal || RefinementSteps > 0)
11466 int &RefinementSteps)
const {
11468 "Enabled should never be Disabled here");
11470 if (!Subtarget.hasFrecipe())
11484 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11492LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11512 if (Constraint.
size() == 1) {
11513 switch (Constraint[0]) {
11529 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11538 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11545std::pair<unsigned, const TargetRegisterClass *>
11546LoongArchTargetLowering::getRegForInlineAsmConstraint(
11550 if (Constraint.
size() == 1) {
11551 switch (Constraint[0]) {
11556 return std::make_pair(0U, &LoongArch::GPRRegClass);
11558 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11560 if (Subtarget.hasBasicF() && VT == MVT::f32)
11561 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11562 if (Subtarget.hasBasicD() && VT == MVT::f64)
11563 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11564 if (Subtarget.hasExtLSX() &&
11565 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11566 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11567 if (Subtarget.hasExtLSX() && VT == MVT::i128)
11568 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11569 if (Subtarget.hasExtLASX() &&
11570 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11571 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11591 bool IsFP = Constraint[2] ==
'f';
11592 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11593 std::pair<unsigned, const TargetRegisterClass *>
R;
11598 unsigned RegNo =
R.first;
11599 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11600 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11601 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11602 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11612void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11616 if (Constraint.
size() == 1) {
11617 switch (Constraint[0]) {
11624 Subtarget.getGRLenVT()));
11633 Subtarget.getGRLenVT()));
11639 if (
C->getZExtValue() == 0)
11659#define GET_REGISTER_MATCHER
11660#include "LoongArchGenAsmMatcher.inc"
11666 std::string NewRegName = Name.second.str();
11672 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11673 if (!ReservedRegs.
test(Reg))
11690 const APInt &
Imm = ConstNode->getAPIntValue();
11692 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2() ||
11693 (1 -
Imm).isPowerOf2() || (-1 -
Imm).isPowerOf2())
11696 if (ConstNode->hasOneUse() &&
11697 ((
Imm - 2).isPowerOf2() || (
Imm - 4).isPowerOf2() ||
11698 (
Imm - 8).isPowerOf2() || (
Imm - 16).isPowerOf2()))
11704 if (ConstNode->hasOneUse() && !(
Imm.sge(-2048) &&
Imm.sle(4095))) {
11705 unsigned Shifts =
Imm.countr_zero();
11712 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11716 APInt ImmSmall =
APInt(
Imm.getBitWidth(), 1ULL << Shifts,
true);
11717 if ((
Imm - ImmSmall).isPowerOf2() || (
Imm + ImmSmall).isPowerOf2() ||
11718 (ImmSmall -
Imm).isPowerOf2())
11728 Type *Ty,
unsigned AS,
11747 switch (AM.
Scale) {
11783 EVT MemVT = LD->getMemoryVT();
11784 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11795 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11804 if (
Y.getValueType().isVector())
11816 Type *Ty,
bool IsSigned)
const {
11817 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11826 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11827 Type.getSizeInBits() < Subtarget.getGRLen()))
11837 Align &PrefAlign)
const {
11841 if (Subtarget.is64Bit()) {
11843 PrefAlign =
Align(8);
11846 PrefAlign =
Align(4);
11861bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11863 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
11864 bool IsABIRegCopy = CC.has_value();
11867 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11868 PartVT == MVT::f32) {
11883SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11885 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11886 bool IsABIRegCopy = CC.has_value();
11888 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11889 PartVT == MVT::f32) {
11890 SDValue Val = Parts[0];
11906 if (VT == MVT::f16 && Subtarget.hasBasicF())
11912unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11915 if (VT == MVT::f16 && Subtarget.hasBasicF())
11924 unsigned Opc =
Op.getOpcode();
11929 case LoongArchISD::VANYNONZERO:
11930 case LoongArchISD::VALLZERO: {
11932 Known.Zero.setBitsFrom(1);
11935 case LoongArchISD::VPICK_ZEXT_ELT: {
11939 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
11940 Known.Zero.setBitsFrom(VTBits);
11949 unsigned Depth)
const {
11950 EVT VT =
Op.getValueType();
11952 unsigned Opc =
Op.getOpcode();
11956 case LoongArchISD::CRC_W_B_W:
11957 case LoongArchISD::CRC_W_H_W:
11958 case LoongArchISD::CRCC_W_B_W:
11959 case LoongArchISD::CRCC_W_H_W: {
11961 APInt DemandedSrcBits =
11963 Opc == LoongArchISD::CRCC_W_B_W)
11967 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
11969 case LoongArchISD::VMSKLTZ:
11970 case LoongArchISD::XVMSKLTZ: {
11972 MVT SrcVT = Src.getSimpleValueType();
11977 if (OriginalDemandedBits.
countr_zero() >= NumElts)
11981 APInt KnownUndef, KnownZero;
11997 if (KnownSrc.
One[SrcBits - 1])
11998 Known.One.setLowBits(NumElts);
11999 else if (KnownSrc.
Zero[SrcBits - 1])
12000 Known.Zero.setLowBits(NumElts);
12004 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
12011 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
12035 unsigned Index)
const {
12046 unsigned Index)
const {
12050 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
12065 Align StackAlign)
const {
12069 unsigned StackProbeSize =
12073 return StackProbeSize ? StackProbeSize : StackAlign.
value();
12077LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
12091 const EVT VT =
Op.getValueType();
12102 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
12112 const Register TargetReg =
MI.getOperand(0).getReg();
12115 const bool IsLA64 = Subtarget.is64Bit();
12116 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
12123 MF.
insert(MBBInsertPoint, LoopTestMBB);
12126 MF.
insert(MBBInsertPoint, ExitMBB);
12137 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
12143 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
12149 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
12164 MBB->addSuccessor(LoopTestMBB);
12166 MI.eraseFromParent();
12168 return ExitMBB->
begin()->getParent();
static MCRegister MatchRegisterName(StringRef Name)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSELECT_CCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue performUINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performHorizWideningCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static std::pair< SDValue, EVT > stripSignExtendInReg(SDValue V)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static SDValue ExtendSrcToDst(SDNode *N, SelectionDAG &DAG, unsigned ExtendOp)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static SDValue performDemandedBitsCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static std::tuple< unsigned, SDValue, EVT > matchBinOpWithSharedOperand(SDValue BinV, SDValue X)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldVMskZeroTest(SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue matchDeinterleaveBuildVector(SDValue N, unsigned &StartIndex)
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVE0 (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue MergeBlocksConvert(SDNode *N, SelectionDAG &DAG, unsigned Opcode, unsigned BlockBits)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue convertRMEncoding(SelectionDAG &DAG, const SDLoc &DL, MVT GRLenVT, SDValue RMValue)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
LLVM_READONLY bool isOne() const
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type count() const
Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void setIncomingIndirectArg(unsigned ArgIndex, Register Reg)
void addSExt32Register(Register Reg)
Register getIncomingIndirectArg(unsigned ArgIndex) const
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchTargetLowering * getTargetLowering() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl, SDNodeFlags Flags={})
Constant fold a setcc to true or false.
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isZeroEltSplatMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses all elements with the same value as the first element of exa...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - 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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)