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()) {
517 if (Subtarget.hasExtLSX()) {
532 if (Subtarget.hasExtLASX()) {
557 if (Subtarget.hasLAMCAS())
560 if (Subtarget.hasSCQ()) {
580 switch (
Op.getOpcode()) {
582 return lowerATOMIC_FENCE(
Op, DAG);
584 return lowerEH_DWARF_CFA(
Op, DAG);
586 return lowerGlobalAddress(
Op, DAG);
588 return lowerGlobalTLSAddress(
Op, DAG);
590 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
592 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
594 return lowerINTRINSIC_VOID(
Op, DAG);
596 return lowerBlockAddress(
Op, DAG);
598 return lowerJumpTable(
Op, DAG);
600 return lowerShiftLeftParts(
Op, DAG);
602 return lowerShiftRightParts(
Op, DAG,
true);
604 return lowerShiftRightParts(
Op, DAG,
false);
606 return lowerConstantPool(
Op, DAG);
608 return lowerFP_TO_SINT(
Op, DAG);
610 return lowerFP_TO_UINT(
Op, DAG);
612 return lowerBITCAST(
Op, DAG);
614 return lowerUINT_TO_FP(
Op, DAG);
616 return lowerSINT_TO_FP(
Op, DAG);
618 return lowerVASTART(
Op, DAG);
620 return lowerFRAMEADDR(
Op, DAG);
622 return lowerRETURNADDR(
Op, DAG);
624 return lowerSET_ROUNDING(
Op, DAG);
626 return lowerGET_ROUNDING(
Op, DAG);
628 return lowerWRITE_REGISTER(
Op, DAG);
630 return lowerINSERT_VECTOR_ELT(
Op, DAG);
632 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
634 return lowerBUILD_VECTOR(
Op, DAG);
636 return lowerCONCAT_VECTORS(
Op, DAG);
638 return lowerVECTOR_SHUFFLE(
Op, DAG);
640 return lowerBITREVERSE(
Op, DAG);
642 return lowerSCALAR_TO_VECTOR(
Op, DAG);
644 return lowerPREFETCH(
Op, DAG);
646 return lowerSELECT(
Op, DAG);
648 return lowerBRCOND(
Op, DAG);
650 return lowerFP_TO_FP16(
Op, DAG);
652 return lowerFP16_TO_FP(
Op, DAG);
654 return lowerFP_TO_BF16(
Op, DAG);
656 return lowerBF16_TO_FP(
Op, DAG);
658 return lowerVECREDUCE_ADD(
Op, DAG);
661 return lowerRotate(
Op, DAG);
669 return lowerVECREDUCE(
Op, DAG);
671 return lowerConstantFP(
Op, DAG);
673 return lowerSETCC(
Op, DAG);
675 return lowerFP_ROUND(
Op, DAG);
677 return lowerFP_EXTEND(
Op, DAG);
679 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
681 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
683 return lowerANY_EXTEND(
Op, DAG);
692 EVT VT = V.getValueType();
698 return V.getOperand(0);
702 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
704 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
714 if (!V->isOnlyUserOf(SplatValue.getNode()))
718 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
726 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
754 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
755 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
762 if (Opcode0 != Opcode1)
765 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
772 EVT VT =
N.getValueType();
786 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
787 SSVT0 == MVT::v4f64) {
806 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
807 N->getOpcode() == LoongArchISD::VPERMI) &&
808 Opcode0 == LoongArchISD::VFCVT) {
813 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
816 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
817 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
823 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
839 MVT VT =
Op.getSimpleValueType();
840 MVT SVT =
In.getSimpleValueType();
842 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
855 EVT VT =
Op.getValueType();
857 EVT SVT = Src.getValueType();
860 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
862 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
863 if (!V2F32ToV2F64 && !V4F32ToV4F64)
875 const uint64_t
Imm =
Op.getConstantOperandVal(1);
890 if (
SDValue V = CheckVecHighPart(Src)) {
892 "Unexpected wide vector");
893 Opcode = LoongArchISD::VFCVTH;
896 Opcode = LoongArchISD::VFCVTL;
898 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
903 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
909 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
921 EVT VT =
Op.getValueType();
926 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
927 (VT == MVT::f64 && Subtarget.hasBasicD()));
944 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
954 if (Subtarget.is64Bit())
956 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
957 : LoongArchISD::MOVGR2FR_W,
961 if (Subtarget.is64Bit()) {
963 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
967 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
979 EVT ResultVT =
Op.getValueType();
980 EVT OperandVT =
Op.getOperand(0).getValueType();
985 if (ResultVT == SetCCResultVT)
988 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
989 "SETCC operands must have the same type!");
993 Op.getOperand(1),
Op.getOperand(2));
995 if (ResultVT.
bitsGT(SetCCResultVT))
997 else if (ResultVT.
bitsLT(SetCCResultVT))
1009SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1013 MVT SrcVT = Src.getSimpleValueType();
1014 MVT DstVT =
Op.getSimpleValueType();
1025 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1036 assert(Subtarget.hasExtLASX());
1055 MVT OpVT =
Op.getSimpleValueType();
1062 unsigned LegalVecSize = 128;
1063 bool isLASX256Vector =
1073 if (isLASX256Vector) {
1079 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1080 EleBits = std::min(EleBits, 64u);
1083 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1086 if (isLASX256Vector) {
1112 MVT OpVT =
Op.getSimpleValueType();
1125 MVT GRLenVT = Subtarget.getGRLenVT();
1127 for (
int i = NumEles; i > 1; i /= 2) {
1130 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1139 unsigned IsData =
Op.getConstantOperandVal(4);
1144 return Op.getOperand(0);
1151 MVT VT =
Op.getSimpleValueType();
1157 unsigned Opcode =
Op.getOpcode();
1160 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1166 CstSplatValue =
C->getAPIntValue();
1174 APInt CstSplatValue;
1175 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1179 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1195 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1211 if (
LHS == LHS2 &&
RHS == RHS2) {
1216 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1224 return std::nullopt;
1232 MVT VT =
N->getSimpleValueType(0);
1263 if (~TrueVal == FalseVal) {
1303 unsigned SelOpNo = 0;
1313 unsigned ConstSelOpNo = 1;
1314 unsigned OtherSelOpNo = 2;
1321 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1326 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1332 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1334 std::swap(NewConstOps[0], NewConstOps[1]);
1346 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1348 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1351 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1352 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1372 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1386 int64_t
C = RHSC->getSExtValue();
1429 MVT VT =
Op.getSimpleValueType();
1430 MVT GRLenVT = Subtarget.getGRLenVT();
1435 if (
Op.hasOneUse()) {
1436 unsigned UseOpc =
Op->user_begin()->getOpcode();
1438 SDNode *BinOp = *
Op->user_begin();
1445 return lowerSELECT(NewSel, DAG);
1462 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1485 if (TrueVal - 1 == FalseVal)
1487 if (TrueVal + 1 == FalseVal)
1494 RHS == TrueV &&
LHS == FalseV) {
1519 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1526 MVT GRLenVT = Subtarget.getGRLenVT();
1537 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1538 Op.getOperand(0),
LHS,
RHS, TargetCC,
1541 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1542 Op.getOperand(0), CondV,
Op.getOperand(2));
1546 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1552LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1555 MVT OpVT =
Op.getSimpleValueType();
1566 EVT ResTy =
Op->getValueType(0);
1571 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1581 for (
unsigned int i = 0; i < NewEltNum; i++) {
1584 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1585 ? (
unsigned)LoongArchISD::BITREV_8B
1603 for (
unsigned int i = 0; i < NewEltNum; i++)
1604 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1605 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1623 if (EltBits > 32 || EltBits == 1)
1651 int MaskOffset,
const APInt &Zeroable) {
1652 int Size = Mask.size();
1653 unsigned SizeInBits =
Size * ScalarSizeInBits;
1655 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1656 for (
int i = 0; i <
Size; i += Scale)
1657 for (
int j = 0; j < Shift; ++j)
1658 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1666 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1667 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1672 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1673 for (
int i = 0; i !=
Size; i += Scale) {
1674 unsigned Pos =
Left ? i + Shift : i;
1675 unsigned Low =
Left ? i : i + Shift;
1676 unsigned Len = Scale - Shift;
1681 int ShiftEltBits = ScalarSizeInBits * Scale;
1682 bool ByteShift = ShiftEltBits > 64;
1683 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1684 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1685 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1689 Scale = ByteShift ? Scale / 2 : Scale;
1695 return (
int)ShiftAmt;
1698 unsigned MaxWidth = 128;
1699 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1700 for (
int Shift = 1; Shift != Scale; ++Shift)
1701 for (
bool Left : {
true,
false})
1702 if (CheckZeros(Shift, Scale,
Left)) {
1703 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1728 const APInt &Zeroable) {
1729 int Size = Mask.size();
1743 Mask,
Size, Zeroable);
1751 "Illegal integer vector type");
1760template <
typename ValType>
1763 unsigned CheckStride,
1765 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1769 if (*
I != -1 && *
I != ExpectedIndex)
1771 ExpectedIndex += ExpectedIndexStride;
1775 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1787 int Size = Mask.size();
1796 int VectorSizeInBits =
V1.getValueSizeInBits();
1797 int ScalarSizeInBits = VectorSizeInBits /
Size;
1798 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1799 (void)ScalarSizeInBits;
1801 for (
int i = 0; i <
Size; ++i) {
1807 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1824 RepeatedMask.
assign(LaneSize, -1);
1825 int Size = Mask.size();
1826 for (
int i = 0; i <
Size; ++i) {
1827 assert(Mask[i] == -1 || Mask[i] >= 0);
1830 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1837 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1838 if (RepeatedMask[i % LaneSize] < 0)
1840 RepeatedMask[i % LaneSize] = LocalM;
1841 else if (RepeatedMask[i % LaneSize] != LocalM)
1858 int NumElts = RepeatedMask.
size();
1860 int Scale = 16 / NumElts;
1862 for (
int i = 0; i < NumElts; ++i) {
1863 int M = RepeatedMask[i];
1864 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1865 "Unexpected mask index.");
1870 int StartIdx = i - (M % NumElts);
1877 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1880 Rotation = CandidateRotation;
1881 else if (Rotation != CandidateRotation)
1896 else if (TargetV != MaskV)
1901 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1902 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1911 return Rotation * Scale;
1930 if (ByteRotation <= 0)
1937 int LoByteShift = 16 - ByteRotation;
1938 int HiByteShift = ByteRotation;
1961 const APInt &Zeroable) {
1975 for (
int i = 0; i < NumElements; i++) {
1979 if (i % Scale != 0) {
1991 M = M % NumElements;
1994 Offset = M - (i / Scale);
1997 if (
Offset % (NumElements / Scale))
1999 }
else if (InputV != V)
2002 if (M != (
Offset + (i / Scale)))
2012 unsigned VilVLoHi = LoongArchISD::VILVL;
2013 if (
Offset >= (NumElements / 2)) {
2014 VilVLoHi = LoongArchISD::VILVH;
2015 Offset -= (NumElements / 2);
2022 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2026 }
while (Scale > 1);
2032 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2033 NumExtElements *= 2) {
2053 int SplatIndex = -1;
2054 for (
const auto &M : Mask) {
2061 if (SplatIndex == -1)
2064 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2066 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2096 unsigned SubVecSize = 4;
2097 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2100 int SubMask[4] = {-1, -1, -1, -1};
2101 for (
unsigned i = 0; i < SubVecSize; ++i) {
2102 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2108 M -= 4 * (j / SubVecSize);
2109 if (M < 0 || M >= 4)
2115 if (SubMask[i] == -1)
2119 else if (M != -1 && M != SubMask[i])
2126 for (
int i = SubVecSize - 1; i >= 0; --i) {
2139 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2140 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2143 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2161 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2170 for (
int i = 0; i < WidenNumElts; ++i)
2171 WidenMask[i] = WidenNumElts - 1 - i;
2179 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2203 const auto &Begin = Mask.begin();
2204 const auto &End = Mask.end();
2221 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2243 const auto &Begin = Mask.begin();
2244 const auto &End = Mask.end();
2261 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2284 const auto &Begin = Mask.begin();
2285 const auto &End = Mask.end();
2286 unsigned HalfSize = Mask.size() / 2;
2304 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2327 const auto &Begin = Mask.begin();
2328 const auto &End = Mask.end();
2345 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2367 const auto &Begin = Mask.begin();
2368 const auto &Mid = Mask.begin() + Mask.size() / 2;
2369 const auto &End = Mask.end();
2387 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2409 const auto &Begin = Mask.begin();
2410 const auto &Mid = Mask.begin() + Mask.size() / 2;
2411 const auto &End = Mask.end();
2428 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2454 if (Mask.size() != NumElts)
2457 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2460 for (
unsigned i = 0; i < NumElts; ++i) {
2463 if (Mask[i] !=
int(
Base + i)) {
2476 int DiffMask = Mask[DiffPos];
2477 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2483 if (
unsigned(DiffMask) < NumElts) {
2488 SrcIdx =
unsigned(DiffMask) - NumElts;
2504 if (
SDValue Result = tryLowerToExtrAndIns(0))
2506 return tryLowerToExtrAndIns(NumElts);
2514 unsigned &MaskImm) {
2515 unsigned MaskSize = Mask.size();
2517 auto isValid = [&](
int M,
int Off) {
2518 return (M == -1) || (M >= Off && M < Off + 4);
2521 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2522 auto immPart = [&](
int M,
unsigned Off) {
2523 return (M == -1 ? 0 : (M - Off)) & 0x3;
2525 MaskImm |= immPart(MLo, Off) << (
I * 2);
2526 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2529 for (
unsigned i = 0; i < 4; i += 2) {
2531 int MHi = Mask[i + 1];
2533 if (MaskSize == 8) {
2534 auto isValid2 = [&](
int &M,
int M2) {
2541 if ((M2 % MaskSize) < 4)
2549 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2555 buildImm(MLo, MHi, 0, i);
2558 buildImm(MLo, MHi, MaskSize, i);
2588 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2593 unsigned MaskImm = 0;
2597 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2624 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2637 "Vector type is unsupported for lsx!");
2639 "Two operands have different types!");
2641 "Unexpected mask size for shuffle!");
2642 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2644 APInt KnownUndef, KnownZero;
2646 APInt Zeroable = KnownUndef | KnownZero;
2719 int SplatIndex = -1;
2720 for (
const auto &M : Mask) {
2727 if (SplatIndex == -1)
2730 const auto &Begin = Mask.begin();
2731 const auto &End = Mask.end();
2732 int HalfSize = Mask.size() / 2;
2734 if (SplatIndex >= HalfSize)
2737 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2741 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2755 if (Mask.size() == 4) {
2756 unsigned MaskImm = 0;
2757 for (
int i = 1; i >= 0; --i) {
2759 int MHi = Mask[i + 2];
2760 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2761 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2763 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2768 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2770 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2773 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2786 unsigned MaskSize = Mask.size();
2791 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2793 unsigned MaskImm = 0;
2797 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2802 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2803 unsigned MaskImm = 0;
2804 for (
unsigned i = 0; i < MaskSize; ++i) {
2807 if (Mask[i] >= (
int)MaskSize)
2809 MaskImm |= Mask[i] << (i * 2);
2812 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2824 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2828 unsigned HalfSize = NumElts / 2;
2829 bool FrontLo =
true, FrontHi =
true;
2830 bool BackLo =
true, BackHi =
true;
2832 auto inRange = [](
int val,
int low,
int high) {
2833 return (val == -1) || (val >= low && val < high);
2836 for (
unsigned i = 0; i < HalfSize; ++i) {
2837 int Fronti = Mask[i];
2838 int Backi = Mask[i + HalfSize];
2840 FrontLo &=
inRange(Fronti, 0, HalfSize);
2841 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2842 BackLo &=
inRange(Backi, 0, HalfSize);
2843 BackHi &=
inRange(Backi, HalfSize, NumElts);
2849 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2854 for (
unsigned i = 0; i < NumElts; ++i)
2859 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2881 const auto &Begin = Mask.begin();
2882 const auto &End = Mask.end();
2883 unsigned HalfSize = Mask.size() / 2;
2884 unsigned LeftSize = HalfSize / 2;
2892 Mask.size() + HalfSize - LeftSize, 1) &&
2894 Mask.size() + HalfSize + LeftSize, 1))
2905 Mask.size() + HalfSize - LeftSize, 1) &&
2907 Mask.size() + HalfSize + LeftSize, 1))
2912 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2920 const auto &Begin = Mask.begin();
2921 const auto &End = Mask.end();
2922 unsigned HalfSize = Mask.size() / 2;
2930 Mask.size() + HalfSize, 1))
2941 Mask.size() + HalfSize, 1))
2946 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2954 const auto &Begin = Mask.begin();
2955 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2956 const auto &Mid = Mask.begin() + Mask.size() / 2;
2957 const auto &RightMid = Mask.end() - Mask.size() / 4;
2958 const auto &End = Mask.end();
2959 unsigned HalfSize = Mask.size() / 2;
2981 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2989 const auto &Begin = Mask.begin();
2990 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2991 const auto &Mid = Mask.begin() + Mask.size() / 2;
2992 const auto &RightMid = Mask.end() - Mask.size() / 4;
2993 const auto &End = Mask.end();
2994 unsigned HalfSize = Mask.size() / 2;
3017 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3026 int HalfSize = NumElts / 2;
3030 if ((
int)Mask.size() != NumElts)
3033 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3035 for (
int i = 0; i < NumElts; ++i) {
3038 if (Mask[i] !=
Base + i) {
3040 if (DiffPos.
size() > 2)
3048 if (DiffPos.
size() == 1) {
3049 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3050 DiffPos.
push_back(DiffPos[0] + HalfSize);
3051 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3052 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3056 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3060 int DiffMaskLo = Mask[DiffPos[0]];
3061 int DiffMaskHi = Mask[DiffPos[1]];
3062 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3063 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3064 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3065 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3067 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3068 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3070 if (DiffMaskHi != DiffMaskLo + HalfSize)
3074 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3076 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3097 if (
SDValue Result = tryLowerToExtrAndIns(0))
3099 return tryLowerToExtrAndIns(NumElts);
3108 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3113 int MaskSize = Mask.size();
3119 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3121 for (
int i = 0; i < MaskSize; ++i) {
3122 if (Mask[i] ==
Base + i || Mask[i] == -1)
3124 if (Mask[i] != Replaced)
3135 int Idx = checkReplaceOne(0, MaskSize);
3137 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3141 Idx = checkReplaceOne(MaskSize, 0);
3143 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3154 int MaskSize = Mask.size();
3155 int HalfSize = Mask.size() / 2;
3156 const auto &Begin = Mask.begin();
3157 const auto &Mid = Mask.begin() + HalfSize;
3158 const auto &End = Mask.end();
3170 for (
auto it = Begin; it < Mid; it++) {
3173 else if ((*it >= 0 && *it < HalfSize) ||
3174 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3175 int M = *it < HalfSize ? *it : *it - HalfSize;
3180 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3182 for (
auto it = Mid; it < End; it++) {
3185 else if ((*it >= HalfSize && *it < MaskSize) ||
3186 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3187 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3192 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3196 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3224 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3226 int MaskSize = Mask.size();
3227 int HalfSize = Mask.size() / 2;
3230 HalfMaskType preMask =
None, postMask =
None;
3232 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3233 return M < 0 || (M >= 0 && M < HalfSize) ||
3234 (M >= MaskSize && M < MaskSize + HalfSize);
3236 preMask = HighLaneTy;
3237 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3238 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3239 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3241 preMask = LowLaneTy;
3243 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3244 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3245 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3247 postMask = LowLaneTy;
3248 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3249 return M < 0 || (M >= 0 && M < HalfSize) ||
3250 (M >= MaskSize && M < MaskSize + HalfSize);
3252 postMask = HighLaneTy;
3260 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3263 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3271 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3276 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3277 *it = *it < 0 ? *it : *it - HalfSize;
3279 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3280 *it = *it < 0 ? *it : *it + HalfSize;
3282 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3290 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3295 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3296 *it = *it < 0 ? *it : *it - HalfSize;
3298 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3306 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3311 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3312 *it = *it < 0 ? *it : *it + HalfSize;
3337 int Size = Mask.size();
3338 int LaneSize =
Size / 2;
3340 bool LaneCrossing[2] = {
false,
false};
3341 for (
int i = 0; i <
Size; ++i)
3342 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3343 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3346 if (!LaneCrossing[0] && !LaneCrossing[1])
3350 InLaneMask.
assign(Mask.begin(), Mask.end());
3351 for (
int i = 0; i <
Size; ++i) {
3352 int &M = InLaneMask[i];
3355 if (((M %
Size) / LaneSize) != (i / LaneSize))
3356 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3361 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3376 "Vector type is unsupported for lasx!");
3378 "Two operands have different types!");
3380 "Unexpected mask size for shuffle!");
3381 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3382 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3384 APInt KnownUndef, KnownZero;
3386 APInt Zeroable = KnownUndef | KnownZero;
3473 ArrayRef<int> OrigMask = SVOp->
getMask();
3476 MVT VT =
Op.getSimpleValueType();
3480 bool V1IsUndef =
V1.isUndef();
3481 bool V2IsUndef = V2.
isUndef();
3482 if (V1IsUndef && V2IsUndef)
3495 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3496 SmallVector<int, 8> NewMask(OrigMask);
3497 for (
int &M : NewMask)
3498 if (M >= NumElements)
3504 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3505 (void)MaskUpperLimit;
3507 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3508 "Out of bounds shuffle index");
3530 std::tie(Res, Chain) =
3531 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3532 if (Subtarget.is64Bit())
3533 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3545 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3549 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3550 CallOptions,
DL, Chain);
3556 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3562 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3563 if (Subtarget.is64Bit())
3564 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3570 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3571 MVT VT =
Op.getSimpleValueType();
3576 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3597 "Unsupported vector type for broadcast.");
3600 bool IsIdeneity =
true;
3602 for (
int i = 0; i !=
NumOps; i++) {
3604 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3616 auto ExtType = LN->getExtensionType();
3621 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3626 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3644 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3658 EVT ResTy,
unsigned first) {
3661 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3664 Node->op_begin() + first + NumElts);
3673 MVT VT =
Node->getSimpleValueType(0);
3674 EVT ResTy =
Op->getValueType(0);
3677 APInt SplatValue, SplatUndef;
3678 unsigned SplatBitSize;
3681 bool UseSameConstant =
true;
3686 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3687 (!Subtarget.hasExtLASX() || !Is256Vec))
3693 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3695 SplatBitSize <= 64) {
3697 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3701 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3708 if ((Is128Vec && ResTy == MVT::v4i32) ||
3709 (Is256Vec && ResTy == MVT::v8i32))
3715 switch (SplatBitSize) {
3719 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3722 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3725 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3728 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3736 if (ViaVecTy != ResTy)
3745 for (
unsigned i = 0; i < NumElts; ++i) {
3750 ConstantValue = Opi;
3751 else if (ConstantValue != Opi)
3752 UseSameConstant =
false;
3757 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3759 for (
unsigned i = 0; i < NumElts; ++i) {
3777 BitVector UndefElements;
3778 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3779 UndefElements.
count() == 0) {
3783 EVT FillTy = Is256Vec
3789 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3792 unsigned SplatLen = NumElts / SeqLen;
3798 if (SplatEltTy == MVT::i128)
3799 SplatTy = MVT::v4i64;
3807 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3808 : LoongArchISD::XVREPLVE0,
3809 DL, SplatTy, SrcVec);
3811 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3824 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3825 ResTy == MVT::v4f64) {
3826 unsigned NonUndefCount = 0;
3827 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3828 if (!
Node->getOperand(i).isUndef()) {
3830 if (NonUndefCount > 1)
3834 if (NonUndefCount == 1)
3847 VecTy, NumElts / 2);
3858 MVT ResVT =
Op.getSimpleValueType();
3866 unsigned NumFreezeUndef = 0;
3867 unsigned NumZero = 0;
3868 unsigned NumNonZero = 0;
3869 unsigned NonZeros = 0;
3870 SmallSet<SDValue, 4> Undefs;
3871 for (
unsigned i = 0; i != NumOperands; ++i) {
3886 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3893 if (NumNonZero > 2) {
3897 Ops.slice(0, NumOperands / 2));
3899 Ops.slice(NumOperands / 2));
3912 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3914 for (
unsigned i = 0; i != NumOperands; ++i) {
3915 if ((NonZeros & (1 << i)) == 0)
3926LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3928 MVT EltVT =
Op.getSimpleValueType();
3933 MVT GRLenVT = Subtarget.getGRLenVT();
3961 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3965 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3967 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3976 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3985LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3987 MVT VT =
Op.getSimpleValueType();
4010 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4012 for (
unsigned i = 0; i < NumElts; ++i) {
4020 for (
unsigned i = 0; i < NumElts; ++i) {
4029 for (
unsigned i = 0; i < NumElts; ++i)
4082 MVT GRLenVT = Subtarget.getGRLenVT();
4088 uint64_t
RM = CVal->getZExtValue();
4094 "rounding mode is not supported by LoongArch hardware",
4095 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4112 FCSRNo, RMValue, Chain);
4118 MVT GRLenVT = Subtarget.getGRLenVT();
4125 MVT::Other, FCSRNo, Chain);
4141 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4143 "On LA64, only 64-bit registers can be written.");
4144 return Op.getOperand(0);
4147 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4149 "On LA32, only 32-bit registers can be written.");
4150 return Op.getOperand(0);
4160 "be a constant integer");
4166 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4167 EVT VT =
Op.getValueType();
4170 unsigned Depth =
Op.getConstantOperandVal(0);
4171 int GRLenInBytes = Subtarget.getGRLen() / 8;
4174 int Offset = -(GRLenInBytes * 2);
4186 if (
Op.getConstantOperandVal(0) != 0) {
4188 "return address can only be determined for the current frame");
4194 MVT GRLenVT = Subtarget.getGRLenVT();
4206 auto Size = Subtarget.getGRLen() / 8;
4214 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4224 MachinePointerInfo(SV));
4231 EVT VT =
Op.getValueType();
4246 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4254 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4257 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4258 !Subtarget.hasBasicD() &&
"unexpected target features");
4262 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4266 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4276 EVT RetVT =
Op.getValueType();
4282 std::tie(Result, Chain) =
4289 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4290 !Subtarget.hasBasicD() &&
"unexpected target features");
4301 EVT RetVT =
Op.getValueType();
4307 std::tie(Result, Chain) =
4316 EVT VT =
Op.getValueType();
4320 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4321 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4323 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4325 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4328 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4342 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4343 !Subtarget.hasBasicD()) {
4345 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4355 if (!Subtarget.hasExtLSX())
4360 EVT VT =
Op.getValueType();
4361 EVT SrcVT = Src.getValueType();
4366 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4369 if (SrcVT == MVT::f32)
4391 N->getOffset(), Flags);
4399template <
class NodeTy>
4402 bool IsLocal)
const {
4413 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4494 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4496 const GlobalValue *GV =
N->getGlobal();
4508 unsigned Opc,
bool UseGOT,
4512 MVT GRLenVT = Subtarget.getGRLenVT();
4526 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4567 TargetLowering::CallLoweringInfo CLI(DAG);
4582 const GlobalValue *GV =
N->getGlobal();
4596LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4603 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4606 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4619 return getDynamicTLSAddr(
N, DAG,
4620 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4621 : LoongArch::PseudoLA_TLS_GD,
4628 return getDynamicTLSAddr(
N, DAG,
4629 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4630 : LoongArch::PseudoLA_TLS_LD,
4635 return getStaticTLSAddr(
N, DAG,
4636 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4637 : LoongArch::PseudoLA_TLS_IE,
4644 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4648 return getTLSDescAddr(
N, DAG,
4649 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4650 : LoongArch::PseudoLA_TLS_DESC,
4654template <
unsigned N>
4659 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4660 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4662 ": argument out of range.");
4669LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4671 switch (
Op.getConstantOperandVal(0)) {
4674 case Intrinsic::thread_pointer: {
4678 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4679 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4680 case Intrinsic::loongarch_lsx_vreplvei_d:
4681 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4683 case Intrinsic::loongarch_lsx_vreplvei_w:
4684 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4685 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4686 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4687 case Intrinsic::loongarch_lasx_xvpickve_d:
4688 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4690 case Intrinsic::loongarch_lasx_xvinsve0_d:
4692 case Intrinsic::loongarch_lsx_vsat_b:
4693 case Intrinsic::loongarch_lsx_vsat_bu:
4694 case Intrinsic::loongarch_lsx_vrotri_b:
4695 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4696 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4697 case Intrinsic::loongarch_lsx_vsrlri_b:
4698 case Intrinsic::loongarch_lsx_vsrari_b:
4699 case Intrinsic::loongarch_lsx_vreplvei_h:
4700 case Intrinsic::loongarch_lasx_xvsat_b:
4701 case Intrinsic::loongarch_lasx_xvsat_bu:
4702 case Intrinsic::loongarch_lasx_xvrotri_b:
4703 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4704 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4705 case Intrinsic::loongarch_lasx_xvsrlri_b:
4706 case Intrinsic::loongarch_lasx_xvsrari_b:
4707 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4708 case Intrinsic::loongarch_lasx_xvpickve_w:
4709 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4711 case Intrinsic::loongarch_lasx_xvinsve0_w:
4713 case Intrinsic::loongarch_lsx_vsat_h:
4714 case Intrinsic::loongarch_lsx_vsat_hu:
4715 case Intrinsic::loongarch_lsx_vrotri_h:
4716 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4717 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4718 case Intrinsic::loongarch_lsx_vsrlri_h:
4719 case Intrinsic::loongarch_lsx_vsrari_h:
4720 case Intrinsic::loongarch_lsx_vreplvei_b:
4721 case Intrinsic::loongarch_lasx_xvsat_h:
4722 case Intrinsic::loongarch_lasx_xvsat_hu:
4723 case Intrinsic::loongarch_lasx_xvrotri_h:
4724 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4725 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4726 case Intrinsic::loongarch_lasx_xvsrlri_h:
4727 case Intrinsic::loongarch_lasx_xvsrari_h:
4728 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4730 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4731 case Intrinsic::loongarch_lsx_vsrani_b_h:
4732 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4733 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4734 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4735 case Intrinsic::loongarch_lsx_vssrani_b_h:
4736 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4737 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4738 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4739 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4740 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4741 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4742 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4743 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4744 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4745 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4746 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4747 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4748 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4749 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4750 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4751 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4752 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4753 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4755 case Intrinsic::loongarch_lsx_vsat_w:
4756 case Intrinsic::loongarch_lsx_vsat_wu:
4757 case Intrinsic::loongarch_lsx_vrotri_w:
4758 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4759 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4760 case Intrinsic::loongarch_lsx_vsrlri_w:
4761 case Intrinsic::loongarch_lsx_vsrari_w:
4762 case Intrinsic::loongarch_lsx_vslei_bu:
4763 case Intrinsic::loongarch_lsx_vslei_hu:
4764 case Intrinsic::loongarch_lsx_vslei_wu:
4765 case Intrinsic::loongarch_lsx_vslei_du:
4766 case Intrinsic::loongarch_lsx_vslti_bu:
4767 case Intrinsic::loongarch_lsx_vslti_hu:
4768 case Intrinsic::loongarch_lsx_vslti_wu:
4769 case Intrinsic::loongarch_lsx_vslti_du:
4770 case Intrinsic::loongarch_lsx_vbsll_v:
4771 case Intrinsic::loongarch_lsx_vbsrl_v:
4772 case Intrinsic::loongarch_lasx_xvsat_w:
4773 case Intrinsic::loongarch_lasx_xvsat_wu:
4774 case Intrinsic::loongarch_lasx_xvrotri_w:
4775 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4776 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4777 case Intrinsic::loongarch_lasx_xvsrlri_w:
4778 case Intrinsic::loongarch_lasx_xvsrari_w:
4779 case Intrinsic::loongarch_lasx_xvslei_bu:
4780 case Intrinsic::loongarch_lasx_xvslei_hu:
4781 case Intrinsic::loongarch_lasx_xvslei_wu:
4782 case Intrinsic::loongarch_lasx_xvslei_du:
4783 case Intrinsic::loongarch_lasx_xvslti_bu:
4784 case Intrinsic::loongarch_lasx_xvslti_hu:
4785 case Intrinsic::loongarch_lasx_xvslti_wu:
4786 case Intrinsic::loongarch_lasx_xvslti_du:
4787 case Intrinsic::loongarch_lasx_xvbsll_v:
4788 case Intrinsic::loongarch_lasx_xvbsrl_v:
4790 case Intrinsic::loongarch_lsx_vseqi_b:
4791 case Intrinsic::loongarch_lsx_vseqi_h:
4792 case Intrinsic::loongarch_lsx_vseqi_w:
4793 case Intrinsic::loongarch_lsx_vseqi_d:
4794 case Intrinsic::loongarch_lsx_vslei_b:
4795 case Intrinsic::loongarch_lsx_vslei_h:
4796 case Intrinsic::loongarch_lsx_vslei_w:
4797 case Intrinsic::loongarch_lsx_vslei_d:
4798 case Intrinsic::loongarch_lsx_vslti_b:
4799 case Intrinsic::loongarch_lsx_vslti_h:
4800 case Intrinsic::loongarch_lsx_vslti_w:
4801 case Intrinsic::loongarch_lsx_vslti_d:
4802 case Intrinsic::loongarch_lasx_xvseqi_b:
4803 case Intrinsic::loongarch_lasx_xvseqi_h:
4804 case Intrinsic::loongarch_lasx_xvseqi_w:
4805 case Intrinsic::loongarch_lasx_xvseqi_d:
4806 case Intrinsic::loongarch_lasx_xvslei_b:
4807 case Intrinsic::loongarch_lasx_xvslei_h:
4808 case Intrinsic::loongarch_lasx_xvslei_w:
4809 case Intrinsic::loongarch_lasx_xvslei_d:
4810 case Intrinsic::loongarch_lasx_xvslti_b:
4811 case Intrinsic::loongarch_lasx_xvslti_h:
4812 case Intrinsic::loongarch_lasx_xvslti_w:
4813 case Intrinsic::loongarch_lasx_xvslti_d:
4815 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4816 case Intrinsic::loongarch_lsx_vsrani_h_w:
4817 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4818 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4819 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4820 case Intrinsic::loongarch_lsx_vssrani_h_w:
4821 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4822 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4823 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4824 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4825 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4826 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4827 case Intrinsic::loongarch_lsx_vfrstpi_b:
4828 case Intrinsic::loongarch_lsx_vfrstpi_h:
4829 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4830 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4831 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4832 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4833 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4834 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4835 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4836 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4837 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4838 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4839 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4840 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4841 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4842 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4844 case Intrinsic::loongarch_lsx_vsat_d:
4845 case Intrinsic::loongarch_lsx_vsat_du:
4846 case Intrinsic::loongarch_lsx_vrotri_d:
4847 case Intrinsic::loongarch_lsx_vsrlri_d:
4848 case Intrinsic::loongarch_lsx_vsrari_d:
4849 case Intrinsic::loongarch_lasx_xvsat_d:
4850 case Intrinsic::loongarch_lasx_xvsat_du:
4851 case Intrinsic::loongarch_lasx_xvrotri_d:
4852 case Intrinsic::loongarch_lasx_xvsrlri_d:
4853 case Intrinsic::loongarch_lasx_xvsrari_d:
4855 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4856 case Intrinsic::loongarch_lsx_vsrani_w_d:
4857 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4858 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4859 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4860 case Intrinsic::loongarch_lsx_vssrani_w_d:
4861 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4862 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4863 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4864 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4865 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4866 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4867 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4868 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4869 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4870 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4871 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4872 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4873 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4874 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4875 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4876 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4877 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4878 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4880 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4881 case Intrinsic::loongarch_lsx_vsrani_d_q:
4882 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4883 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4884 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4885 case Intrinsic::loongarch_lsx_vssrani_d_q:
4886 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4887 case Intrinsic::loongarch_lsx_vssrani_du_q:
4888 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4889 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4890 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4891 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4892 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4893 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4894 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4895 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4896 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4897 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4898 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4899 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4900 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4901 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4902 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4903 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4905 case Intrinsic::loongarch_lsx_vnori_b:
4906 case Intrinsic::loongarch_lsx_vshuf4i_b:
4907 case Intrinsic::loongarch_lsx_vshuf4i_h:
4908 case Intrinsic::loongarch_lsx_vshuf4i_w:
4909 case Intrinsic::loongarch_lasx_xvnori_b:
4910 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4911 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4912 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4913 case Intrinsic::loongarch_lasx_xvpermi_d:
4915 case Intrinsic::loongarch_lsx_vshuf4i_d:
4916 case Intrinsic::loongarch_lsx_vpermi_w:
4917 case Intrinsic::loongarch_lsx_vbitseli_b:
4918 case Intrinsic::loongarch_lsx_vextrins_b:
4919 case Intrinsic::loongarch_lsx_vextrins_h:
4920 case Intrinsic::loongarch_lsx_vextrins_w:
4921 case Intrinsic::loongarch_lsx_vextrins_d:
4922 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4923 case Intrinsic::loongarch_lasx_xvpermi_w:
4924 case Intrinsic::loongarch_lasx_xvpermi_q:
4925 case Intrinsic::loongarch_lasx_xvbitseli_b:
4926 case Intrinsic::loongarch_lasx_xvextrins_b:
4927 case Intrinsic::loongarch_lasx_xvextrins_h:
4928 case Intrinsic::loongarch_lasx_xvextrins_w:
4929 case Intrinsic::loongarch_lasx_xvextrins_d:
4931 case Intrinsic::loongarch_lsx_vrepli_b:
4932 case Intrinsic::loongarch_lsx_vrepli_h:
4933 case Intrinsic::loongarch_lsx_vrepli_w:
4934 case Intrinsic::loongarch_lsx_vrepli_d:
4935 case Intrinsic::loongarch_lasx_xvrepli_b:
4936 case Intrinsic::loongarch_lasx_xvrepli_h:
4937 case Intrinsic::loongarch_lasx_xvrepli_w:
4938 case Intrinsic::loongarch_lasx_xvrepli_d:
4940 case Intrinsic::loongarch_lsx_vldi:
4941 case Intrinsic::loongarch_lasx_xvldi:
4957LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4960 MVT GRLenVT = Subtarget.getGRLenVT();
4961 EVT VT =
Op.getValueType();
4963 const StringRef ErrorMsgOOR =
"argument out of range";
4964 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4965 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4967 switch (
Op.getConstantOperandVal(1)) {
4970 case Intrinsic::loongarch_crc_w_b_w:
4971 case Intrinsic::loongarch_crc_w_h_w:
4972 case Intrinsic::loongarch_crc_w_w_w:
4973 case Intrinsic::loongarch_crc_w_d_w:
4974 case Intrinsic::loongarch_crcc_w_b_w:
4975 case Intrinsic::loongarch_crcc_w_h_w:
4976 case Intrinsic::loongarch_crcc_w_w_w:
4977 case Intrinsic::loongarch_crcc_w_d_w:
4979 case Intrinsic::loongarch_csrrd_w:
4980 case Intrinsic::loongarch_csrrd_d: {
4981 unsigned Imm =
Op.getConstantOperandVal(2);
4984 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4987 case Intrinsic::loongarch_csrwr_w:
4988 case Intrinsic::loongarch_csrwr_d: {
4989 unsigned Imm =
Op.getConstantOperandVal(3);
4992 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4993 {Chain,
Op.getOperand(2),
4996 case Intrinsic::loongarch_csrxchg_w:
4997 case Intrinsic::loongarch_csrxchg_d: {
4998 unsigned Imm =
Op.getConstantOperandVal(4);
5001 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5002 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5005 case Intrinsic::loongarch_iocsrrd_d: {
5007 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5010#define IOCSRRD_CASE(NAME, NODE) \
5011 case Intrinsic::loongarch_##NAME: { \
5012 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5013 {Chain, Op.getOperand(2)}); \
5019 case Intrinsic::loongarch_cpucfg: {
5020 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5021 {Chain,
Op.getOperand(2)});
5023 case Intrinsic::loongarch_lddir_d: {
5024 unsigned Imm =
Op.getConstantOperandVal(3);
5029 case Intrinsic::loongarch_movfcsr2gr: {
5030 if (!Subtarget.hasBasicF())
5032 unsigned Imm =
Op.getConstantOperandVal(2);
5035 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5038 case Intrinsic::loongarch_lsx_vld:
5039 case Intrinsic::loongarch_lsx_vldrepl_b:
5040 case Intrinsic::loongarch_lasx_xvld:
5041 case Intrinsic::loongarch_lasx_xvldrepl_b:
5045 case Intrinsic::loongarch_lsx_vldrepl_h:
5046 case Intrinsic::loongarch_lasx_xvldrepl_h:
5050 Op,
"argument out of range or not a multiple of 2", DAG)
5052 case Intrinsic::loongarch_lsx_vldrepl_w:
5053 case Intrinsic::loongarch_lasx_xvldrepl_w:
5057 Op,
"argument out of range or not a multiple of 4", DAG)
5059 case Intrinsic::loongarch_lsx_vldrepl_d:
5060 case Intrinsic::loongarch_lasx_xvldrepl_d:
5064 Op,
"argument out of range or not a multiple of 8", DAG)
5075 return Op.getOperand(0);
5081 MVT GRLenVT = Subtarget.getGRLenVT();
5083 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5085 const StringRef ErrorMsgOOR =
"argument out of range";
5086 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5087 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5088 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5090 switch (IntrinsicEnum) {
5094 case Intrinsic::loongarch_cacop_d:
5095 case Intrinsic::loongarch_cacop_w: {
5096 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5098 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5107 case Intrinsic::loongarch_dbar: {
5114 case Intrinsic::loongarch_ibar: {
5121 case Intrinsic::loongarch_break: {
5128 case Intrinsic::loongarch_movgr2fcsr: {
5129 if (!Subtarget.hasBasicF())
5139 case Intrinsic::loongarch_syscall: {
5146#define IOCSRWR_CASE(NAME, NODE) \
5147 case Intrinsic::loongarch_##NAME: { \
5148 SDValue Op3 = Op.getOperand(3); \
5149 return Subtarget.is64Bit() \
5150 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5151 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5152 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5153 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5160 case Intrinsic::loongarch_iocsrwr_d: {
5161 return !Subtarget.is64Bit()
5168#define ASRT_LE_GT_CASE(NAME) \
5169 case Intrinsic::loongarch_##NAME: { \
5170 return !Subtarget.is64Bit() \
5171 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5176#undef ASRT_LE_GT_CASE
5177 case Intrinsic::loongarch_ldpte_d: {
5178 unsigned Imm =
Op.getConstantOperandVal(3);
5179 return !Subtarget.is64Bit()
5184 case Intrinsic::loongarch_lsx_vst:
5185 case Intrinsic::loongarch_lasx_xvst:
5189 case Intrinsic::loongarch_lasx_xvstelm_b:
5194 case Intrinsic::loongarch_lsx_vstelm_b:
5199 case Intrinsic::loongarch_lasx_xvstelm_h:
5204 Op,
"argument out of range or not a multiple of 2", DAG)
5206 case Intrinsic::loongarch_lsx_vstelm_h:
5211 Op,
"argument out of range or not a multiple of 2", DAG)
5213 case Intrinsic::loongarch_lasx_xvstelm_w:
5218 Op,
"argument out of range or not a multiple of 4", DAG)
5220 case Intrinsic::loongarch_lsx_vstelm_w:
5225 Op,
"argument out of range or not a multiple of 4", DAG)
5227 case Intrinsic::loongarch_lasx_xvstelm_d:
5232 Op,
"argument out of range or not a multiple of 8", DAG)
5234 case Intrinsic::loongarch_lsx_vstelm_d:
5239 Op,
"argument out of range or not a multiple of 8", DAG)
5250 EVT VT =
Lo.getValueType();
5291 EVT VT =
Lo.getValueType();
5345 return LoongArchISD::DIV_W;
5347 return LoongArchISD::DIV_WU;
5349 return LoongArchISD::MOD_W;
5351 return LoongArchISD::MOD_WU;
5353 return LoongArchISD::SLL_W;
5355 return LoongArchISD::SRA_W;
5357 return LoongArchISD::SRL_W;
5360 return LoongArchISD::ROTR_W;
5362 return LoongArchISD::CTZ_W;
5364 return LoongArchISD::CLZ_W;
5383 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5384 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5388 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5394 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5421 StringRef ErrorMsg,
bool WithChain =
true) {
5426 Results.push_back(
N->getOperand(0));
5429template <
unsigned N>
5434 const StringRef ErrorMsgOOR =
"argument out of range";
5435 unsigned Imm =
Node->getConstantOperandVal(2);
5469 switch (
N->getConstantOperandVal(0)) {
5472 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5474 LoongArchISD::VPICK_SEXT_ELT);
5476 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5477 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5479 LoongArchISD::VPICK_SEXT_ELT);
5481 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5483 LoongArchISD::VPICK_SEXT_ELT);
5485 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5487 LoongArchISD::VPICK_ZEXT_ELT);
5489 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5490 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5492 LoongArchISD::VPICK_ZEXT_ELT);
5494 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5496 LoongArchISD::VPICK_ZEXT_ELT);
5498 case Intrinsic::loongarch_lsx_bz_b:
5499 case Intrinsic::loongarch_lsx_bz_h:
5500 case Intrinsic::loongarch_lsx_bz_w:
5501 case Intrinsic::loongarch_lsx_bz_d:
5502 case Intrinsic::loongarch_lasx_xbz_b:
5503 case Intrinsic::loongarch_lasx_xbz_h:
5504 case Intrinsic::loongarch_lasx_xbz_w:
5505 case Intrinsic::loongarch_lasx_xbz_d:
5507 LoongArchISD::VALL_ZERO);
5509 case Intrinsic::loongarch_lsx_bz_v:
5510 case Intrinsic::loongarch_lasx_xbz_v:
5512 LoongArchISD::VANY_ZERO);
5514 case Intrinsic::loongarch_lsx_bnz_b:
5515 case Intrinsic::loongarch_lsx_bnz_h:
5516 case Intrinsic::loongarch_lsx_bnz_w:
5517 case Intrinsic::loongarch_lsx_bnz_d:
5518 case Intrinsic::loongarch_lasx_xbnz_b:
5519 case Intrinsic::loongarch_lasx_xbnz_h:
5520 case Intrinsic::loongarch_lasx_xbnz_w:
5521 case Intrinsic::loongarch_lasx_xbnz_d:
5523 LoongArchISD::VALL_NONZERO);
5525 case Intrinsic::loongarch_lsx_bnz_v:
5526 case Intrinsic::loongarch_lasx_xbnz_v:
5528 LoongArchISD::VANY_NONZERO);
5536 assert(
N->getValueType(0) == MVT::i128 &&
5537 "AtomicCmpSwap on types less than 128 should be legal");
5541 switch (
MemOp->getMergedOrdering()) {
5545 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5549 Opcode = LoongArch::PseudoCmpXchg128;
5556 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5557 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5558 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5559 NewVal.first, NewVal.second,
N->getOperand(0)};
5562 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5573 EVT VT =
N->getValueType(0);
5574 switch (
N->getOpcode()) {
5579 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5580 "Unexpected custom legalisation");
5587 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5588 "Unexpected custom legalisation");
5590 Subtarget.hasDiv32() && VT == MVT::i32
5597 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5598 "Unexpected custom legalisation");
5606 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5607 "Unexpected custom legalisation");
5614 MVT VT =
N->getSimpleValueType(0);
5615 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5616 "Unexpected custom legalisation");
5618 "Unexpected type action!");
5623 Ld->getPointerInfo(), Ld->getBaseAlign(),
5624 Ld->getMemOperand()->getFlags());
5635 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5636 "Unexpected custom legalisation");
5643 if (Src.getValueType() == MVT::f16)
5654 EVT OpVT = Src.getValueType();
5658 std::tie(Result, Chain) =
5665 EVT SrcVT = Src.getValueType();
5666 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5667 Subtarget.hasBasicF()) {
5669 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5671 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5673 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5681 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5682 "Unexpected custom legalisation");
5685 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5690 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5691 "Unexpected custom legalisation");
5697 if (OpVT == MVT::v2f64) {
5707 assert((VT == MVT::i16 || VT == MVT::i32) &&
5708 "Unexpected custom legalization");
5709 MVT GRLenVT = Subtarget.getGRLenVT();
5716 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5721 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5729 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5730 "Unexpected custom legalization");
5731 MVT GRLenVT = Subtarget.getGRLenVT();
5738 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5741 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5749 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5750 "Unexpected custom legalisation");
5757 MVT GRLenVT = Subtarget.getGRLenVT();
5758 const StringRef ErrorMsgOOR =
"argument out of range";
5759 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5760 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5762 switch (
N->getConstantOperandVal(1)) {
5765 case Intrinsic::loongarch_movfcsr2gr: {
5766 if (!Subtarget.hasBasicF()) {
5776 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5783#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5784 case Intrinsic::loongarch_##NAME: { \
5785 SDValue NODE = DAG.getNode( \
5786 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5787 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5788 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5789 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5790 Results.push_back(NODE.getValue(1)); \
5799#undef CRC_CASE_EXT_BINARYOP
5801#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5802 case Intrinsic::loongarch_##NAME: { \
5803 SDValue NODE = DAG.getNode( \
5804 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5806 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5807 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5808 Results.push_back(NODE.getValue(1)); \
5813#undef CRC_CASE_EXT_UNARYOP
5814#define CSR_CASE(ID) \
5815 case Intrinsic::loongarch_##ID: { \
5816 if (!Subtarget.is64Bit()) \
5817 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5825 case Intrinsic::loongarch_csrrd_w: {
5832 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5839 case Intrinsic::loongarch_csrwr_w: {
5840 unsigned Imm =
N->getConstantOperandVal(3);
5846 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5854 case Intrinsic::loongarch_csrxchg_w: {
5855 unsigned Imm =
N->getConstantOperandVal(4);
5861 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5870#define IOCSRRD_CASE(NAME, NODE) \
5871 case Intrinsic::loongarch_##NAME: { \
5872 SDValue IOCSRRDResults = \
5873 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5874 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5875 Results.push_back( \
5876 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5877 Results.push_back(IOCSRRDResults.getValue(1)); \
5884 case Intrinsic::loongarch_cpucfg: {
5886 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5893 case Intrinsic::loongarch_lddir_d: {
5894 if (!Subtarget.is64Bit()) {
5904 if (Subtarget.is64Bit())
5906 "On LA64, only 64-bit registers can be read.");
5909 "On LA32, only 32-bit registers can be read.");
5911 Results.push_back(
N->getOperand(0));
5922 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5935 MVT VT =
N->getSimpleValueType(0);
5941 EVT InVT = In.getValueType();
5951 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5956 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
5959 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5968 for (
unsigned I = 0;
I < MinElts; ++
I)
5969 TruncMask[
I] = Scale *
I;
5971 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5972 MVT SVT = In.getSimpleValueType().getScalarType();
5978 "Illegal vector type in truncation");
5990 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
5993 EVT DstVT =
N->getValueType(0);
5995 MVT SrcVT = Src.getSimpleValueType();
6009 unsigned WidenSrcElts = 128 / SrcEltBits;
6016 unsigned FirstStageEltBits = 128 / NumElts;
6020 SrcVT = FirstStageVT;
6021 SrcEltBits = FirstStageEltBits;
6028 while (SrcEltBits < DstEltBits) {
6029 unsigned NextEltBits = SrcEltBits * 2;
6032 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6050 Blocks = std::move(NextBlocks);
6051 SrcVT = NextBlockVT;
6052 SrcEltBits = NextEltBits;
6069 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6071 MVT VT =
N->getSimpleValueType(0);
6090 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6094 unsigned MinSizeInBits) {
6102 unsigned SplatBitSize;
6105 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6106 HasAnyUndefs, MinSizeInBits,
6118 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6129 unsigned EltIdx = IdxC->getZExtValue();
6131 Start = (int)EltIdx - (
int)(i * 2);
6132 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6138 else if (Src != CurSrc)
6142 if (!Src || Start < 0)
6152 if (!Subtarget.hasExtLSX())
6155 unsigned Opc =
N->getOpcode();
6158 EVT VT =
N->getValueType(0);
6165 unsigned ExtOpc =
LHS.getOpcode();
6173 if (ExtOpc !=
RHS.getOpcode())
6176 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6179 unsigned OddIdx, EvenIdx;
6183 if (!LHSVec || !RHSVec)
6185 if (OddIdx != 1 || EvenIdx != 0)
6195 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6208 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6210 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6212 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6224 EVT VT =
N->getValueType(0);
6290 if (
And.getOperand(0) ==
X) {
6319 if (ShiftVal != (SplatVal + 1))
6328 : LoongArchISD::VSRAR,
6338 SDValue FirstOperand =
N->getOperand(0);
6339 SDValue SecondOperand =
N->getOperand(1);
6340 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6341 EVT ValTy =
N->getValueType(0);
6344 unsigned SMIdx, SMLen;
6353 if (!Subtarget.has32S())
6409 NewOperand = FirstOperand;
6412 msb = lsb + SMLen - 1;
6416 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6430 EVT DstVT =
N.getValueType();
6439 EVT SrcVT = Src.getValueType();
6447 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6458 if (NumElts % 2 != 0)
6464 for (
unsigned I = 0;
I != NumElts; ++
I) {
6479 SrcVT = Src.getValueType();
6489 }
else if (ThisSrc != Src) {
6493 unsigned Half = NumElts / 2;
6494 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6495 ExpectedIdx += isLow ? 0 : Half;
6497 if (CI->getZExtValue() != ExpectedIdx)
6509 EVT VT =
N->getValueType(0);
6516 unsigned ExtOpc =
LHS.getOpcode();
6524 if (!
LHS.hasOneUse())
6528 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6544 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6553 if (!Subtarget.has32S())
6565 SDValue FirstOperand =
N->getOperand(0);
6567 EVT ValTy =
N->getValueType(0);
6570 unsigned MaskIdx, MaskLen;
6585 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6586 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6610 switch (Src.getOpcode()) {
6613 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6623 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6636 switch (Src.getOpcode()) {
6646 Src.getOpcode(),
DL, SExtVT,
6652 DL, SExtVT, Src.getOperand(0),
6664 EVT VT =
N->getValueType(0);
6666 EVT SrcVT = Src.getValueType();
6668 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6673 EVT CmpVT = Src.getOperand(0).getValueType();
6678 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6691 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6696 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6701 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6706 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6708 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6713 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6715 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6720 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6737 EVT VT =
N->getValueType(0);
6739 EVT SrcVT = Src.getValueType();
6756 bool UseLASX =
false;
6757 bool PropagateSExt =
false;
6759 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6760 EVT CmpVT = Src.getOperand(0).getValueType();
6769 SExtVT = MVT::v2i64;
6772 SExtVT = MVT::v4i32;
6774 SExtVT = MVT::v4i64;
6776 PropagateSExt =
true;
6780 SExtVT = MVT::v8i16;
6782 SExtVT = MVT::v8i32;
6784 PropagateSExt =
true;
6788 SExtVT = MVT::v16i8;
6790 SExtVT = MVT::v16i16;
6792 PropagateSExt =
true;
6796 SExtVT = MVT::v32i8;
6804 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6805 if (Src.getSimpleValueType() == MVT::v32i8) {
6813 }
else if (UseLASX) {
6819 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6832 EVT ValTy =
N->getValueType(0);
6833 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6837 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6839 bool SwapAndRetried =
false;
6842 if (!Subtarget.has32S())
6848 if (ValBits != 32 && ValBits != 64)
6863 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6866 (MaskIdx0 + MaskLen0 <= ValBits)) {
6887 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6888 (MaskIdx0 + MaskLen0 <= ValBits)) {
6905 (MaskIdx0 + MaskLen0 <= 64) &&
6913 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6914 : (MaskIdx0 + MaskLen0 - 1),
6930 (MaskIdx0 + MaskLen0 <= ValBits)) {
6953 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6954 : (MaskIdx0 + MaskLen0 - 1),
6969 unsigned MaskIdx, MaskLen;
6970 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6979 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6997 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7003 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7011 if (!SwapAndRetried) {
7013 SwapAndRetried =
true;
7017 SwapAndRetried =
false;
7034 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7043 if (!SwapAndRetried) {
7045 SwapAndRetried =
true;
7055 switch (V.getNode()->getOpcode()) {
7067 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7075 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7152 SDNode *AndNode =
N->getOperand(0).getNode();
7160 SDValue CmpInputValue =
N->getOperand(1);
7169 if (!CN || !CN->
isZero())
7171 AndInputValue1 = AndInputValue1.
getOperand(0);
7175 if (AndInputValue2 != CmpInputValue)
7208 TruncInputValue1, TruncInputValue2);
7210 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7223 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7226 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7251 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7279 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7312 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7313 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7329 EVT VT =
N->getValueType(0);
7332 if (TrueV == FalseV)
7363 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7364 {LHS, RHS, CC, TrueV, FalseV});
7369template <
unsigned N>
7373 bool IsSigned =
false) {
7377 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7378 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7380 ": argument out of range.");
7386template <
unsigned N>
7390 EVT ResTy =
Node->getValueType(0);
7394 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7395 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7397 ": argument out of range.");
7402 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7408 EVT ResTy =
Node->getValueType(0);
7416 EVT ResTy =
Node->getValueType(0);
7425template <
unsigned N>
7428 EVT ResTy =
Node->getValueType(0);
7433 ": argument out of range.");
7443template <
unsigned N>
7446 EVT ResTy =
Node->getValueType(0);
7451 ": argument out of range.");
7460template <
unsigned N>
7463 EVT ResTy =
Node->getValueType(0);
7468 ": argument out of range.");
7477template <
unsigned W>
7480 unsigned Imm =
N->getConstantOperandVal(2);
7482 const StringRef ErrorMsg =
"argument out of range";
7484 return DAG.
getUNDEF(
N->getValueType(0));
7490 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7498 switch (
N->getConstantOperandVal(0)) {
7501 case Intrinsic::loongarch_lsx_vadd_b:
7502 case Intrinsic::loongarch_lsx_vadd_h:
7503 case Intrinsic::loongarch_lsx_vadd_w:
7504 case Intrinsic::loongarch_lsx_vadd_d:
7505 case Intrinsic::loongarch_lasx_xvadd_b:
7506 case Intrinsic::loongarch_lasx_xvadd_h:
7507 case Intrinsic::loongarch_lasx_xvadd_w:
7508 case Intrinsic::loongarch_lasx_xvadd_d:
7511 case Intrinsic::loongarch_lsx_vaddi_bu:
7512 case Intrinsic::loongarch_lsx_vaddi_hu:
7513 case Intrinsic::loongarch_lsx_vaddi_wu:
7514 case Intrinsic::loongarch_lsx_vaddi_du:
7515 case Intrinsic::loongarch_lasx_xvaddi_bu:
7516 case Intrinsic::loongarch_lasx_xvaddi_hu:
7517 case Intrinsic::loongarch_lasx_xvaddi_wu:
7518 case Intrinsic::loongarch_lasx_xvaddi_du:
7521 case Intrinsic::loongarch_lsx_vsub_b:
7522 case Intrinsic::loongarch_lsx_vsub_h:
7523 case Intrinsic::loongarch_lsx_vsub_w:
7524 case Intrinsic::loongarch_lsx_vsub_d:
7525 case Intrinsic::loongarch_lasx_xvsub_b:
7526 case Intrinsic::loongarch_lasx_xvsub_h:
7527 case Intrinsic::loongarch_lasx_xvsub_w:
7528 case Intrinsic::loongarch_lasx_xvsub_d:
7531 case Intrinsic::loongarch_lsx_vsubi_bu:
7532 case Intrinsic::loongarch_lsx_vsubi_hu:
7533 case Intrinsic::loongarch_lsx_vsubi_wu:
7534 case Intrinsic::loongarch_lsx_vsubi_du:
7535 case Intrinsic::loongarch_lasx_xvsubi_bu:
7536 case Intrinsic::loongarch_lasx_xvsubi_hu:
7537 case Intrinsic::loongarch_lasx_xvsubi_wu:
7538 case Intrinsic::loongarch_lasx_xvsubi_du:
7541 case Intrinsic::loongarch_lsx_vneg_b:
7542 case Intrinsic::loongarch_lsx_vneg_h:
7543 case Intrinsic::loongarch_lsx_vneg_w:
7544 case Intrinsic::loongarch_lsx_vneg_d:
7545 case Intrinsic::loongarch_lasx_xvneg_b:
7546 case Intrinsic::loongarch_lasx_xvneg_h:
7547 case Intrinsic::loongarch_lasx_xvneg_w:
7548 case Intrinsic::loongarch_lasx_xvneg_d:
7552 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7554 SDLoc(
N),
N->getValueType(0)),
7556 case Intrinsic::loongarch_lsx_vmax_b:
7557 case Intrinsic::loongarch_lsx_vmax_h:
7558 case Intrinsic::loongarch_lsx_vmax_w:
7559 case Intrinsic::loongarch_lsx_vmax_d:
7560 case Intrinsic::loongarch_lasx_xvmax_b:
7561 case Intrinsic::loongarch_lasx_xvmax_h:
7562 case Intrinsic::loongarch_lasx_xvmax_w:
7563 case Intrinsic::loongarch_lasx_xvmax_d:
7566 case Intrinsic::loongarch_lsx_vmax_bu:
7567 case Intrinsic::loongarch_lsx_vmax_hu:
7568 case Intrinsic::loongarch_lsx_vmax_wu:
7569 case Intrinsic::loongarch_lsx_vmax_du:
7570 case Intrinsic::loongarch_lasx_xvmax_bu:
7571 case Intrinsic::loongarch_lasx_xvmax_hu:
7572 case Intrinsic::loongarch_lasx_xvmax_wu:
7573 case Intrinsic::loongarch_lasx_xvmax_du:
7576 case Intrinsic::loongarch_lsx_vmaxi_b:
7577 case Intrinsic::loongarch_lsx_vmaxi_h:
7578 case Intrinsic::loongarch_lsx_vmaxi_w:
7579 case Intrinsic::loongarch_lsx_vmaxi_d:
7580 case Intrinsic::loongarch_lasx_xvmaxi_b:
7581 case Intrinsic::loongarch_lasx_xvmaxi_h:
7582 case Intrinsic::loongarch_lasx_xvmaxi_w:
7583 case Intrinsic::loongarch_lasx_xvmaxi_d:
7586 case Intrinsic::loongarch_lsx_vmaxi_bu:
7587 case Intrinsic::loongarch_lsx_vmaxi_hu:
7588 case Intrinsic::loongarch_lsx_vmaxi_wu:
7589 case Intrinsic::loongarch_lsx_vmaxi_du:
7590 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7591 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7592 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7593 case Intrinsic::loongarch_lasx_xvmaxi_du:
7596 case Intrinsic::loongarch_lsx_vmin_b:
7597 case Intrinsic::loongarch_lsx_vmin_h:
7598 case Intrinsic::loongarch_lsx_vmin_w:
7599 case Intrinsic::loongarch_lsx_vmin_d:
7600 case Intrinsic::loongarch_lasx_xvmin_b:
7601 case Intrinsic::loongarch_lasx_xvmin_h:
7602 case Intrinsic::loongarch_lasx_xvmin_w:
7603 case Intrinsic::loongarch_lasx_xvmin_d:
7606 case Intrinsic::loongarch_lsx_vmin_bu:
7607 case Intrinsic::loongarch_lsx_vmin_hu:
7608 case Intrinsic::loongarch_lsx_vmin_wu:
7609 case Intrinsic::loongarch_lsx_vmin_du:
7610 case Intrinsic::loongarch_lasx_xvmin_bu:
7611 case Intrinsic::loongarch_lasx_xvmin_hu:
7612 case Intrinsic::loongarch_lasx_xvmin_wu:
7613 case Intrinsic::loongarch_lasx_xvmin_du:
7616 case Intrinsic::loongarch_lsx_vmini_b:
7617 case Intrinsic::loongarch_lsx_vmini_h:
7618 case Intrinsic::loongarch_lsx_vmini_w:
7619 case Intrinsic::loongarch_lsx_vmini_d:
7620 case Intrinsic::loongarch_lasx_xvmini_b:
7621 case Intrinsic::loongarch_lasx_xvmini_h:
7622 case Intrinsic::loongarch_lasx_xvmini_w:
7623 case Intrinsic::loongarch_lasx_xvmini_d:
7626 case Intrinsic::loongarch_lsx_vmini_bu:
7627 case Intrinsic::loongarch_lsx_vmini_hu:
7628 case Intrinsic::loongarch_lsx_vmini_wu:
7629 case Intrinsic::loongarch_lsx_vmini_du:
7630 case Intrinsic::loongarch_lasx_xvmini_bu:
7631 case Intrinsic::loongarch_lasx_xvmini_hu:
7632 case Intrinsic::loongarch_lasx_xvmini_wu:
7633 case Intrinsic::loongarch_lasx_xvmini_du:
7636 case Intrinsic::loongarch_lsx_vmul_b:
7637 case Intrinsic::loongarch_lsx_vmul_h:
7638 case Intrinsic::loongarch_lsx_vmul_w:
7639 case Intrinsic::loongarch_lsx_vmul_d:
7640 case Intrinsic::loongarch_lasx_xvmul_b:
7641 case Intrinsic::loongarch_lasx_xvmul_h:
7642 case Intrinsic::loongarch_lasx_xvmul_w:
7643 case Intrinsic::loongarch_lasx_xvmul_d:
7646 case Intrinsic::loongarch_lsx_vmadd_b:
7647 case Intrinsic::loongarch_lsx_vmadd_h:
7648 case Intrinsic::loongarch_lsx_vmadd_w:
7649 case Intrinsic::loongarch_lsx_vmadd_d:
7650 case Intrinsic::loongarch_lasx_xvmadd_b:
7651 case Intrinsic::loongarch_lasx_xvmadd_h:
7652 case Intrinsic::loongarch_lasx_xvmadd_w:
7653 case Intrinsic::loongarch_lasx_xvmadd_d: {
7654 EVT ResTy =
N->getValueType(0);
7659 case Intrinsic::loongarch_lsx_vmsub_b:
7660 case Intrinsic::loongarch_lsx_vmsub_h:
7661 case Intrinsic::loongarch_lsx_vmsub_w:
7662 case Intrinsic::loongarch_lsx_vmsub_d:
7663 case Intrinsic::loongarch_lasx_xvmsub_b:
7664 case Intrinsic::loongarch_lasx_xvmsub_h:
7665 case Intrinsic::loongarch_lasx_xvmsub_w:
7666 case Intrinsic::loongarch_lasx_xvmsub_d: {
7667 EVT ResTy =
N->getValueType(0);
7672 case Intrinsic::loongarch_lsx_vdiv_b:
7673 case Intrinsic::loongarch_lsx_vdiv_h:
7674 case Intrinsic::loongarch_lsx_vdiv_w:
7675 case Intrinsic::loongarch_lsx_vdiv_d:
7676 case Intrinsic::loongarch_lasx_xvdiv_b:
7677 case Intrinsic::loongarch_lasx_xvdiv_h:
7678 case Intrinsic::loongarch_lasx_xvdiv_w:
7679 case Intrinsic::loongarch_lasx_xvdiv_d:
7682 case Intrinsic::loongarch_lsx_vdiv_bu:
7683 case Intrinsic::loongarch_lsx_vdiv_hu:
7684 case Intrinsic::loongarch_lsx_vdiv_wu:
7685 case Intrinsic::loongarch_lsx_vdiv_du:
7686 case Intrinsic::loongarch_lasx_xvdiv_bu:
7687 case Intrinsic::loongarch_lasx_xvdiv_hu:
7688 case Intrinsic::loongarch_lasx_xvdiv_wu:
7689 case Intrinsic::loongarch_lasx_xvdiv_du:
7692 case Intrinsic::loongarch_lsx_vmod_b:
7693 case Intrinsic::loongarch_lsx_vmod_h:
7694 case Intrinsic::loongarch_lsx_vmod_w:
7695 case Intrinsic::loongarch_lsx_vmod_d:
7696 case Intrinsic::loongarch_lasx_xvmod_b:
7697 case Intrinsic::loongarch_lasx_xvmod_h:
7698 case Intrinsic::loongarch_lasx_xvmod_w:
7699 case Intrinsic::loongarch_lasx_xvmod_d:
7702 case Intrinsic::loongarch_lsx_vmod_bu:
7703 case Intrinsic::loongarch_lsx_vmod_hu:
7704 case Intrinsic::loongarch_lsx_vmod_wu:
7705 case Intrinsic::loongarch_lsx_vmod_du:
7706 case Intrinsic::loongarch_lasx_xvmod_bu:
7707 case Intrinsic::loongarch_lasx_xvmod_hu:
7708 case Intrinsic::loongarch_lasx_xvmod_wu:
7709 case Intrinsic::loongarch_lasx_xvmod_du:
7712 case Intrinsic::loongarch_lsx_vand_v:
7713 case Intrinsic::loongarch_lasx_xvand_v:
7716 case Intrinsic::loongarch_lsx_vor_v:
7717 case Intrinsic::loongarch_lasx_xvor_v:
7720 case Intrinsic::loongarch_lsx_vxor_v:
7721 case Intrinsic::loongarch_lasx_xvxor_v:
7724 case Intrinsic::loongarch_lsx_vnor_v:
7725 case Intrinsic::loongarch_lasx_xvnor_v: {
7730 case Intrinsic::loongarch_lsx_vandi_b:
7731 case Intrinsic::loongarch_lasx_xvandi_b:
7734 case Intrinsic::loongarch_lsx_vori_b:
7735 case Intrinsic::loongarch_lasx_xvori_b:
7738 case Intrinsic::loongarch_lsx_vxori_b:
7739 case Intrinsic::loongarch_lasx_xvxori_b:
7742 case Intrinsic::loongarch_lsx_vsll_b:
7743 case Intrinsic::loongarch_lsx_vsll_h:
7744 case Intrinsic::loongarch_lsx_vsll_w:
7745 case Intrinsic::loongarch_lsx_vsll_d:
7746 case Intrinsic::loongarch_lasx_xvsll_b:
7747 case Intrinsic::loongarch_lasx_xvsll_h:
7748 case Intrinsic::loongarch_lasx_xvsll_w:
7749 case Intrinsic::loongarch_lasx_xvsll_d:
7752 case Intrinsic::loongarch_lsx_vslli_b:
7753 case Intrinsic::loongarch_lasx_xvslli_b:
7756 case Intrinsic::loongarch_lsx_vslli_h:
7757 case Intrinsic::loongarch_lasx_xvslli_h:
7760 case Intrinsic::loongarch_lsx_vslli_w:
7761 case Intrinsic::loongarch_lasx_xvslli_w:
7764 case Intrinsic::loongarch_lsx_vslli_d:
7765 case Intrinsic::loongarch_lasx_xvslli_d:
7768 case Intrinsic::loongarch_lsx_vsrl_b:
7769 case Intrinsic::loongarch_lsx_vsrl_h:
7770 case Intrinsic::loongarch_lsx_vsrl_w:
7771 case Intrinsic::loongarch_lsx_vsrl_d:
7772 case Intrinsic::loongarch_lasx_xvsrl_b:
7773 case Intrinsic::loongarch_lasx_xvsrl_h:
7774 case Intrinsic::loongarch_lasx_xvsrl_w:
7775 case Intrinsic::loongarch_lasx_xvsrl_d:
7778 case Intrinsic::loongarch_lsx_vsrli_b:
7779 case Intrinsic::loongarch_lasx_xvsrli_b:
7782 case Intrinsic::loongarch_lsx_vsrli_h:
7783 case Intrinsic::loongarch_lasx_xvsrli_h:
7786 case Intrinsic::loongarch_lsx_vsrli_w:
7787 case Intrinsic::loongarch_lasx_xvsrli_w:
7790 case Intrinsic::loongarch_lsx_vsrli_d:
7791 case Intrinsic::loongarch_lasx_xvsrli_d:
7794 case Intrinsic::loongarch_lsx_vsra_b:
7795 case Intrinsic::loongarch_lsx_vsra_h:
7796 case Intrinsic::loongarch_lsx_vsra_w:
7797 case Intrinsic::loongarch_lsx_vsra_d:
7798 case Intrinsic::loongarch_lasx_xvsra_b:
7799 case Intrinsic::loongarch_lasx_xvsra_h:
7800 case Intrinsic::loongarch_lasx_xvsra_w:
7801 case Intrinsic::loongarch_lasx_xvsra_d:
7804 case Intrinsic::loongarch_lsx_vsrai_b:
7805 case Intrinsic::loongarch_lasx_xvsrai_b:
7808 case Intrinsic::loongarch_lsx_vsrai_h:
7809 case Intrinsic::loongarch_lasx_xvsrai_h:
7812 case Intrinsic::loongarch_lsx_vsrai_w:
7813 case Intrinsic::loongarch_lasx_xvsrai_w:
7816 case Intrinsic::loongarch_lsx_vsrai_d:
7817 case Intrinsic::loongarch_lasx_xvsrai_d:
7820 case Intrinsic::loongarch_lsx_vclz_b:
7821 case Intrinsic::loongarch_lsx_vclz_h:
7822 case Intrinsic::loongarch_lsx_vclz_w:
7823 case Intrinsic::loongarch_lsx_vclz_d:
7824 case Intrinsic::loongarch_lasx_xvclz_b:
7825 case Intrinsic::loongarch_lasx_xvclz_h:
7826 case Intrinsic::loongarch_lasx_xvclz_w:
7827 case Intrinsic::loongarch_lasx_xvclz_d:
7829 case Intrinsic::loongarch_lsx_vpcnt_b:
7830 case Intrinsic::loongarch_lsx_vpcnt_h:
7831 case Intrinsic::loongarch_lsx_vpcnt_w:
7832 case Intrinsic::loongarch_lsx_vpcnt_d:
7833 case Intrinsic::loongarch_lasx_xvpcnt_b:
7834 case Intrinsic::loongarch_lasx_xvpcnt_h:
7835 case Intrinsic::loongarch_lasx_xvpcnt_w:
7836 case Intrinsic::loongarch_lasx_xvpcnt_d:
7838 case Intrinsic::loongarch_lsx_vbitclr_b:
7839 case Intrinsic::loongarch_lsx_vbitclr_h:
7840 case Intrinsic::loongarch_lsx_vbitclr_w:
7841 case Intrinsic::loongarch_lsx_vbitclr_d:
7842 case Intrinsic::loongarch_lasx_xvbitclr_b:
7843 case Intrinsic::loongarch_lasx_xvbitclr_h:
7844 case Intrinsic::loongarch_lasx_xvbitclr_w:
7845 case Intrinsic::loongarch_lasx_xvbitclr_d:
7847 case Intrinsic::loongarch_lsx_vbitclri_b:
7848 case Intrinsic::loongarch_lasx_xvbitclri_b:
7850 case Intrinsic::loongarch_lsx_vbitclri_h:
7851 case Intrinsic::loongarch_lasx_xvbitclri_h:
7853 case Intrinsic::loongarch_lsx_vbitclri_w:
7854 case Intrinsic::loongarch_lasx_xvbitclri_w:
7856 case Intrinsic::loongarch_lsx_vbitclri_d:
7857 case Intrinsic::loongarch_lasx_xvbitclri_d:
7859 case Intrinsic::loongarch_lsx_vbitset_b:
7860 case Intrinsic::loongarch_lsx_vbitset_h:
7861 case Intrinsic::loongarch_lsx_vbitset_w:
7862 case Intrinsic::loongarch_lsx_vbitset_d:
7863 case Intrinsic::loongarch_lasx_xvbitset_b:
7864 case Intrinsic::loongarch_lasx_xvbitset_h:
7865 case Intrinsic::loongarch_lasx_xvbitset_w:
7866 case Intrinsic::loongarch_lasx_xvbitset_d: {
7867 EVT VecTy =
N->getValueType(0);
7873 case Intrinsic::loongarch_lsx_vbitseti_b:
7874 case Intrinsic::loongarch_lasx_xvbitseti_b:
7876 case Intrinsic::loongarch_lsx_vbitseti_h:
7877 case Intrinsic::loongarch_lasx_xvbitseti_h:
7879 case Intrinsic::loongarch_lsx_vbitseti_w:
7880 case Intrinsic::loongarch_lasx_xvbitseti_w:
7882 case Intrinsic::loongarch_lsx_vbitseti_d:
7883 case Intrinsic::loongarch_lasx_xvbitseti_d:
7885 case Intrinsic::loongarch_lsx_vbitrev_b:
7886 case Intrinsic::loongarch_lsx_vbitrev_h:
7887 case Intrinsic::loongarch_lsx_vbitrev_w:
7888 case Intrinsic::loongarch_lsx_vbitrev_d:
7889 case Intrinsic::loongarch_lasx_xvbitrev_b:
7890 case Intrinsic::loongarch_lasx_xvbitrev_h:
7891 case Intrinsic::loongarch_lasx_xvbitrev_w:
7892 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7893 EVT VecTy =
N->getValueType(0);
7899 case Intrinsic::loongarch_lsx_vbitrevi_b:
7900 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7902 case Intrinsic::loongarch_lsx_vbitrevi_h:
7903 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7905 case Intrinsic::loongarch_lsx_vbitrevi_w:
7906 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7908 case Intrinsic::loongarch_lsx_vbitrevi_d:
7909 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7911 case Intrinsic::loongarch_lsx_vfadd_s:
7912 case Intrinsic::loongarch_lsx_vfadd_d:
7913 case Intrinsic::loongarch_lasx_xvfadd_s:
7914 case Intrinsic::loongarch_lasx_xvfadd_d:
7917 case Intrinsic::loongarch_lsx_vfsub_s:
7918 case Intrinsic::loongarch_lsx_vfsub_d:
7919 case Intrinsic::loongarch_lasx_xvfsub_s:
7920 case Intrinsic::loongarch_lasx_xvfsub_d:
7923 case Intrinsic::loongarch_lsx_vfmul_s:
7924 case Intrinsic::loongarch_lsx_vfmul_d:
7925 case Intrinsic::loongarch_lasx_xvfmul_s:
7926 case Intrinsic::loongarch_lasx_xvfmul_d:
7929 case Intrinsic::loongarch_lsx_vfdiv_s:
7930 case Intrinsic::loongarch_lsx_vfdiv_d:
7931 case Intrinsic::loongarch_lasx_xvfdiv_s:
7932 case Intrinsic::loongarch_lasx_xvfdiv_d:
7935 case Intrinsic::loongarch_lsx_vfmadd_s:
7936 case Intrinsic::loongarch_lsx_vfmadd_d:
7937 case Intrinsic::loongarch_lasx_xvfmadd_s:
7938 case Intrinsic::loongarch_lasx_xvfmadd_d:
7940 N->getOperand(2),
N->getOperand(3));
7941 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7943 N->getOperand(1),
N->getOperand(2),
7945 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7946 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7948 N->getOperand(1),
N->getOperand(2),
7950 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7951 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7953 N->getOperand(1),
N->getOperand(2),
7955 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7957 N->getOperand(1),
N->getOperand(2),
7959 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7960 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7961 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7962 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7963 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7964 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7965 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7966 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7967 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7970 case Intrinsic::loongarch_lsx_vreplve_b:
7971 case Intrinsic::loongarch_lsx_vreplve_h:
7972 case Intrinsic::loongarch_lsx_vreplve_w:
7973 case Intrinsic::loongarch_lsx_vreplve_d:
7974 case Intrinsic::loongarch_lasx_xvreplve_b:
7975 case Intrinsic::loongarch_lasx_xvreplve_h:
7976 case Intrinsic::loongarch_lasx_xvreplve_w:
7977 case Intrinsic::loongarch_lasx_xvreplve_d:
7978 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7982 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7986 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7987 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7991 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7995 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7999 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8000 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8004 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8008 case Intrinsic::loongarch_lsx_bz_b:
8009 case Intrinsic::loongarch_lsx_bz_h:
8010 case Intrinsic::loongarch_lsx_bz_w:
8011 case Intrinsic::loongarch_lsx_bz_d:
8012 case Intrinsic::loongarch_lasx_xbz_b:
8013 case Intrinsic::loongarch_lasx_xbz_h:
8014 case Intrinsic::loongarch_lasx_xbz_w:
8015 case Intrinsic::loongarch_lasx_xbz_d:
8017 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8020 case Intrinsic::loongarch_lsx_bz_v:
8021 case Intrinsic::loongarch_lasx_xbz_v:
8023 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8026 case Intrinsic::loongarch_lsx_bnz_b:
8027 case Intrinsic::loongarch_lsx_bnz_h:
8028 case Intrinsic::loongarch_lsx_bnz_w:
8029 case Intrinsic::loongarch_lsx_bnz_d:
8030 case Intrinsic::loongarch_lasx_xbnz_b:
8031 case Intrinsic::loongarch_lasx_xbnz_h:
8032 case Intrinsic::loongarch_lasx_xbnz_w:
8033 case Intrinsic::loongarch_lasx_xbnz_d:
8035 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8038 case Intrinsic::loongarch_lsx_bnz_v:
8039 case Intrinsic::loongarch_lasx_xbnz_v:
8041 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8044 case Intrinsic::loongarch_lasx_concat_128_s:
8045 case Intrinsic::loongarch_lasx_concat_128_d:
8046 case Intrinsic::loongarch_lasx_concat_128:
8048 N->getOperand(1),
N->getOperand(2));
8060 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8072 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8074 "Unexpected value type!");
8083 MVT VT =
N->getSimpleValueType(0);
8104 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8117 APInt V =
C->getValueAPF().bitcastToAPInt();
8132 MVT VT =
N->getSimpleValueType(0);
8191 EVT VT =
N->getValueType(0);
8193 EVT SrcVT = Src.getValueType();
8199 if (SrcEltBits >= DstEltBits)
8206 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8218 unsigned BlockBits) {
8220 MVT DstVT =
N->getSimpleValueType(0);
8222 MVT SrcVT = Src.getSimpleValueType();
8229 Src.getOperand(0).getValueType() == BlockVT) {
8230 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8232 }
else if (SrcBits > BlockBits) {
8234 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8239 BlockBits = SrcBits;
8246 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8251 if (BlockBits == 256) {
8261 if (Blocks.
size() == 1)
8271 EVT VT =
N->getValueType(0);
8273 EVT SrcVT = Src.getValueType();
8279 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8282 if (SrcEltBits <= DstEltBits)
8285 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8295 if (VT != MVT::f32 && VT != MVT::f64)
8297 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8299 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8331 EVT VT =
N->getValueType(0);
8348 if (!Subtarget.hasExtLSX())
8352 EVT DstVT =
N->getValueType(0);
8354 EVT SrcVT = Src.getValueType();
8364 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8369 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8372 if (DstEltBits < 32) {
8378 if (SrcEltBits != 64 || DstEltBits != 32)
8383 if (Subtarget.hasExtLASX())
8444 Subtarget.hasExtLASX() && N1.
hasOneUse())
8456 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8466 EVT VT =
N.getValueType();
8483 switch (
N.getOpcode()) {
8499 EVT VT =
N->getValueType(0);
8507 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
8512 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
8514 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
8526 EVT VT =
N->getValueType(0);
8528 if (VT.
isVector() &&
N->getNumOperands() == 2)
8541 EVT VT =
N->getValueType(0);
8553 SDValue TrueVal =
N->getOperand(1);
8554 SDValue FalseVal =
N->getOperand(2);
8588 if (FalseVal.getOpcode() !=
ISD::ADD)
8591 SDValue Add0 = FalseVal.getOperand(0);
8592 SDValue Add1 = FalseVal.getOperand(1);
8662 : LoongArchISD::VSRAR,
8669 switch (
N->getOpcode()) {
8699 case LoongArchISD::BITREV_W:
8701 case LoongArchISD::BR_CC:
8703 case LoongArchISD::SELECT_CC:
8707 case LoongArchISD::MOVGR2FR_W_LA64:
8709 case LoongArchISD::MOVFR2GR_S_LA64:
8711 case LoongArchISD::CRC_W_B_W:
8712 case LoongArchISD::CRC_W_H_W:
8713 case LoongArchISD::CRCC_W_B_W:
8714 case LoongArchISD::CRCC_W_H_W:
8715 case LoongArchISD::VMSKLTZ:
8716 case LoongArchISD::XVMSKLTZ:
8718 case LoongArchISD::SPLIT_PAIR_F64:
8720 case LoongArchISD::VANDN:
8726 case LoongArchISD::VPACKEV:
8727 case LoongArchISD::VPERMI:
8753 MF->
insert(It, BreakMBB);
8757 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8758 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
8770 MBB->addSuccessor(BreakMBB);
8771 MBB->addSuccessor(SinkMBB);
8777 BreakMBB->addSuccessor(SinkMBB);
8789 switch (
MI.getOpcode()) {
8792 case LoongArch::PseudoVBZ:
8793 CondOpc = LoongArch::VSETEQZ_V;
8795 case LoongArch::PseudoVBZ_B:
8796 CondOpc = LoongArch::VSETANYEQZ_B;
8798 case LoongArch::PseudoVBZ_H:
8799 CondOpc = LoongArch::VSETANYEQZ_H;
8801 case LoongArch::PseudoVBZ_W:
8802 CondOpc = LoongArch::VSETANYEQZ_W;
8804 case LoongArch::PseudoVBZ_D:
8805 CondOpc = LoongArch::VSETANYEQZ_D;
8807 case LoongArch::PseudoVBNZ:
8808 CondOpc = LoongArch::VSETNEZ_V;
8810 case LoongArch::PseudoVBNZ_B:
8811 CondOpc = LoongArch::VSETALLNEZ_B;
8813 case LoongArch::PseudoVBNZ_H:
8814 CondOpc = LoongArch::VSETALLNEZ_H;
8816 case LoongArch::PseudoVBNZ_W:
8817 CondOpc = LoongArch::VSETALLNEZ_W;
8819 case LoongArch::PseudoVBNZ_D:
8820 CondOpc = LoongArch::VSETALLNEZ_D;
8822 case LoongArch::PseudoXVBZ:
8823 CondOpc = LoongArch::XVSETEQZ_V;
8825 case LoongArch::PseudoXVBZ_B:
8826 CondOpc = LoongArch::XVSETANYEQZ_B;
8828 case LoongArch::PseudoXVBZ_H:
8829 CondOpc = LoongArch::XVSETANYEQZ_H;
8831 case LoongArch::PseudoXVBZ_W:
8832 CondOpc = LoongArch::XVSETANYEQZ_W;
8834 case LoongArch::PseudoXVBZ_D:
8835 CondOpc = LoongArch::XVSETANYEQZ_D;
8837 case LoongArch::PseudoXVBNZ:
8838 CondOpc = LoongArch::XVSETNEZ_V;
8840 case LoongArch::PseudoXVBNZ_B:
8841 CondOpc = LoongArch::XVSETALLNEZ_B;
8843 case LoongArch::PseudoXVBNZ_H:
8844 CondOpc = LoongArch::XVSETALLNEZ_H;
8846 case LoongArch::PseudoXVBNZ_W:
8847 CondOpc = LoongArch::XVSETALLNEZ_W;
8849 case LoongArch::PseudoXVBNZ_D:
8850 CondOpc = LoongArch::XVSETALLNEZ_D;
8865 F->insert(It, FalseBB);
8866 F->insert(It, TrueBB);
8867 F->insert(It, SinkBB);
8870 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
8899 MI.getOperand(0).getReg())
8906 MI.eraseFromParent();
8914 unsigned BroadcastOp;
8916 switch (
MI.getOpcode()) {
8919 case LoongArch::PseudoXVINSGR2VR_B:
8921 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8922 InsOp = LoongArch::XVEXTRINS_B;
8924 case LoongArch::PseudoXVINSGR2VR_H:
8926 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8927 InsOp = LoongArch::XVEXTRINS_H;
8939 unsigned Idx =
MI.getOperand(3).getImm();
8947 .
addReg(XSrc, {}, LoongArch::sub_128);
8949 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8950 : LoongArch::VINSGR2VR_B),
8958 .
addImm(LoongArch::sub_128);
8965 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8968 .
addImm(Idx >= HalfSize ? 48 : 18);
8973 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8976 MI.eraseFromParent();
8983 assert(Subtarget.hasExtLSX());
8991 unsigned BroadcastOp, CTOp, PickOp;
8992 switch (
MI.getOpcode()) {
8995 case LoongArch::PseudoCTPOP_B:
8996 BroadcastOp = LoongArch::VREPLGR2VR_B;
8997 CTOp = LoongArch::VPCNT_B;
8998 PickOp = LoongArch::VPICKVE2GR_B;
9000 case LoongArch::PseudoCTPOP_H:
9001 case LoongArch::PseudoCTPOP_H_LA32:
9002 BroadcastOp = LoongArch::VREPLGR2VR_H;
9003 CTOp = LoongArch::VPCNT_H;
9004 PickOp = LoongArch::VPICKVE2GR_H;
9006 case LoongArch::PseudoCTPOP_W:
9007 case LoongArch::PseudoCTPOP_W_LA32:
9008 BroadcastOp = LoongArch::VREPLGR2VR_W;
9009 CTOp = LoongArch::VPCNT_W;
9010 PickOp = LoongArch::VPICKVE2GR_W;
9012 case LoongArch::PseudoCTPOP_D:
9013 BroadcastOp = LoongArch::VREPLGR2VR_D;
9014 CTOp = LoongArch::VPCNT_D;
9015 PickOp = LoongArch::VPICKVE2GR_D;
9025 MI.eraseFromParent();
9039 unsigned EleBits = 8;
9040 unsigned NotOpc = 0;
9043 switch (
MI.getOpcode()) {
9046 case LoongArch::PseudoVMSKLTZ_B:
9047 MskOpc = LoongArch::VMSKLTZ_B;
9049 case LoongArch::PseudoVMSKLTZ_H:
9050 MskOpc = LoongArch::VMSKLTZ_H;
9053 case LoongArch::PseudoVMSKLTZ_W:
9054 MskOpc = LoongArch::VMSKLTZ_W;
9057 case LoongArch::PseudoVMSKLTZ_D:
9058 MskOpc = LoongArch::VMSKLTZ_D;
9061 case LoongArch::PseudoVMSKGEZ_B:
9062 MskOpc = LoongArch::VMSKGEZ_B;
9064 case LoongArch::PseudoVMSKEQZ_B:
9065 MskOpc = LoongArch::VMSKNZ_B;
9066 NotOpc = LoongArch::VNOR_V;
9068 case LoongArch::PseudoVMSKNEZ_B:
9069 MskOpc = LoongArch::VMSKNZ_B;
9071 case LoongArch::PseudoXVMSKLTZ_B:
9072 MskOpc = LoongArch::XVMSKLTZ_B;
9073 RC = &LoongArch::LASX256RegClass;
9075 case LoongArch::PseudoXVMSKLTZ_H:
9076 MskOpc = LoongArch::XVMSKLTZ_H;
9077 RC = &LoongArch::LASX256RegClass;
9080 case LoongArch::PseudoXVMSKLTZ_W:
9081 MskOpc = LoongArch::XVMSKLTZ_W;
9082 RC = &LoongArch::LASX256RegClass;
9085 case LoongArch::PseudoXVMSKLTZ_D:
9086 MskOpc = LoongArch::XVMSKLTZ_D;
9087 RC = &LoongArch::LASX256RegClass;
9090 case LoongArch::PseudoXVMSKGEZ_B:
9091 MskOpc = LoongArch::XVMSKGEZ_B;
9092 RC = &LoongArch::LASX256RegClass;
9094 case LoongArch::PseudoXVMSKEQZ_B:
9095 MskOpc = LoongArch::XVMSKNZ_B;
9096 NotOpc = LoongArch::XVNOR_V;
9097 RC = &LoongArch::LASX256RegClass;
9099 case LoongArch::PseudoXVMSKNEZ_B:
9100 MskOpc = LoongArch::XVMSKNZ_B;
9101 RC = &LoongArch::LASX256RegClass;
9116 if (
TRI->getRegSizeInBits(*RC) > 128) {
9126 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
9127 : LoongArch::BSTRINS_W),
9131 .
addImm(256 / EleBits - 1)
9139 MI.eraseFromParent();
9146 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9147 "Unexpected instruction");
9159 MI.eraseFromParent();
9166 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9167 "Unexpected instruction");
9183 MI.eraseFromParent();
9188 switch (
MI.getOpcode()) {
9191 case LoongArch::Select_GPR_Using_CC_GPR:
9227 if (
MI.getOperand(2).isReg())
9228 RHS =
MI.getOperand(2).getReg();
9229 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9233 SelectDests.
insert(
MI.getOperand(0).getReg());
9237 SequenceMBBI !=
E; ++SequenceMBBI) {
9238 if (SequenceMBBI->isDebugInstr())
9241 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9242 !SequenceMBBI->getOperand(2).isReg() ||
9243 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9244 SequenceMBBI->getOperand(3).getImm() != CC ||
9245 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9246 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9248 LastSelectPseudo = &*SequenceMBBI;
9250 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9253 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9254 SequenceMBBI->mayLoadOrStore() ||
9255 SequenceMBBI->usesCustomInsertionHook())
9258 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9273 F->insert(
I, IfFalseMBB);
9274 F->insert(
I, TailMBB);
9277 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9283 TailMBB->
push_back(DebugInstr->removeFromParent());
9287 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9297 if (
MI.getOperand(2).isImm())
9309 auto SelectMBBI =
MI.getIterator();
9310 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9312 while (SelectMBBI != SelectEnd) {
9313 auto Next = std::next(SelectMBBI);
9317 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9318 .
addReg(SelectMBBI->getOperand(4).getReg())
9320 .
addReg(SelectMBBI->getOperand(5).getReg())
9327 F->getProperties().resetNoPHIs();
9333 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9336 switch (
MI.getOpcode()) {
9339 case LoongArch::DIV_W:
9340 case LoongArch::DIV_WU:
9341 case LoongArch::MOD_W:
9342 case LoongArch::MOD_WU:
9343 case LoongArch::DIV_D:
9344 case LoongArch::DIV_DU:
9345 case LoongArch::MOD_D:
9346 case LoongArch::MOD_DU:
9349 case LoongArch::WRFCSR: {
9351 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9352 .
addReg(
MI.getOperand(1).getReg());
9353 MI.eraseFromParent();
9356 case LoongArch::RDFCSR: {
9357 MachineInstr *ReadFCSR =
9359 MI.getOperand(0).getReg())
9360 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9362 MI.eraseFromParent();
9365 case LoongArch::Select_GPR_Using_CC_GPR:
9367 case LoongArch::BuildPairF64Pseudo:
9369 case LoongArch::SplitPairF64Pseudo:
9371 case LoongArch::PseudoVBZ:
9372 case LoongArch::PseudoVBZ_B:
9373 case LoongArch::PseudoVBZ_H:
9374 case LoongArch::PseudoVBZ_W:
9375 case LoongArch::PseudoVBZ_D:
9376 case LoongArch::PseudoVBNZ:
9377 case LoongArch::PseudoVBNZ_B:
9378 case LoongArch::PseudoVBNZ_H:
9379 case LoongArch::PseudoVBNZ_W:
9380 case LoongArch::PseudoVBNZ_D:
9381 case LoongArch::PseudoXVBZ:
9382 case LoongArch::PseudoXVBZ_B:
9383 case LoongArch::PseudoXVBZ_H:
9384 case LoongArch::PseudoXVBZ_W:
9385 case LoongArch::PseudoXVBZ_D:
9386 case LoongArch::PseudoXVBNZ:
9387 case LoongArch::PseudoXVBNZ_B:
9388 case LoongArch::PseudoXVBNZ_H:
9389 case LoongArch::PseudoXVBNZ_W:
9390 case LoongArch::PseudoXVBNZ_D:
9392 case LoongArch::PseudoXVINSGR2VR_B:
9393 case LoongArch::PseudoXVINSGR2VR_H:
9395 case LoongArch::PseudoCTPOP_B:
9396 case LoongArch::PseudoCTPOP_H:
9397 case LoongArch::PseudoCTPOP_W:
9398 case LoongArch::PseudoCTPOP_D:
9399 case LoongArch::PseudoCTPOP_H_LA32:
9400 case LoongArch::PseudoCTPOP_W_LA32:
9402 case LoongArch::PseudoVMSKLTZ_B:
9403 case LoongArch::PseudoVMSKLTZ_H:
9404 case LoongArch::PseudoVMSKLTZ_W:
9405 case LoongArch::PseudoVMSKLTZ_D:
9406 case LoongArch::PseudoVMSKGEZ_B:
9407 case LoongArch::PseudoVMSKEQZ_B:
9408 case LoongArch::PseudoVMSKNEZ_B:
9409 case LoongArch::PseudoXVMSKLTZ_B:
9410 case LoongArch::PseudoXVMSKLTZ_H:
9411 case LoongArch::PseudoXVMSKLTZ_W:
9412 case LoongArch::PseudoXVMSKLTZ_D:
9413 case LoongArch::PseudoXVMSKGEZ_B:
9414 case LoongArch::PseudoXVMSKEQZ_B:
9415 case LoongArch::PseudoXVMSKNEZ_B:
9417 case TargetOpcode::STATEPOINT:
9423 MI.addOperand(*
MI.getMF(),
9425 LoongArch::R1,
true,
9428 if (!Subtarget.is64Bit())
9431 case LoongArch::PROBED_STACKALLOC_DYN:
9438 unsigned *
Fast)
const {
9439 if (!Subtarget.hasUAL())
9457 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9458 LoongArch::R10, LoongArch::R11};
9473 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9474 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9475 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9476 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9477 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9478 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9484 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9485 LoongArch::F6, LoongArch::F7};
9488 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9489 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9492 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9493 LoongArch::VR6, LoongArch::VR7};
9496 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9497 LoongArch::XR6, LoongArch::XR7};
9500 switch (State.getCallingConv()) {
9502 if (!State.isVarArg())
9506 return State.AllocateReg(
ArgGPRs);
9514 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9516 unsigned GRLenInBytes = GRLen / 8;
9527 State.AllocateStack(GRLenInBytes, StackAlign),
9530 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9541 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9549 unsigned ValNo,
MVT ValVT,
9552 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9553 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9554 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9559 if (IsRet && ValNo > 1)
9563 bool UseGPRForFloat =
true;
9573 UseGPRForFloat = ArgFlags.
isVarArg();
9586 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9589 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9590 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9592 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9598 State.getPendingArgFlags();
9601 "PendingLocs and PendingArgFlags out of sync");
9605 UseGPRForFloat =
true;
9607 if (UseGPRForFloat && ValVT == MVT::f32) {
9610 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9613 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9616 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9658 PendingLocs.
size() <= 2) {
9659 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9664 PendingLocs.
clear();
9665 PendingArgFlags.
clear();
9672 unsigned StoreSizeBytes = GRLen / 8;
9675 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9677 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9681 UseGPRForFloat =
false;
9682 StoreSizeBytes = 16;
9683 StackAlign =
Align(16);
9686 UseGPRForFloat =
false;
9687 StoreSizeBytes = 32;
9688 StackAlign =
Align(32);
9694 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9698 if (!PendingLocs.
empty()) {
9700 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9701 for (
auto &It : PendingLocs) {
9703 It.convertToReg(
Reg);
9708 PendingLocs.clear();
9709 PendingArgFlags.
clear();
9712 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9713 "Expected an GRLenVT at this stage");
9730void LoongArchTargetLowering::analyzeInputArgs(
9733 LoongArchCCAssignFn Fn)
const {
9735 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9736 MVT ArgVT = Ins[i].VT;
9737 Type *ArgTy =
nullptr;
9739 ArgTy = FType->getReturnType();
9740 else if (Ins[i].isOrigArg())
9741 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9745 CCInfo, IsRet, ArgTy)) {
9746 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9753void LoongArchTargetLowering::analyzeOutputArgs(
9756 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9757 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9758 MVT ArgVT = Outs[i].VT;
9759 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
9763 CCInfo, IsRet, OrigTy)) {
9764 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
9783 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
9805 if (In.isOrigArg()) {
9810 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
9811 (
BitWidth < 32 && In.Flags.isZExt())) {
9861 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9874 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9878 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
9892 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
9904 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
9908 LoongArch::R23, LoongArch::R24, LoongArch::R25,
9909 LoongArch::R26, LoongArch::R27, LoongArch::R28,
9910 LoongArch::R29, LoongArch::R30, LoongArch::R31};
9917 if (LocVT == MVT::f32) {
9920 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9921 LoongArch::F26, LoongArch::F27};
9928 if (LocVT == MVT::f64) {
9931 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9932 LoongArch::F30_64, LoongArch::F31_64};
9963 "GHC calling convention requires the F and D extensions");
9968 MVT GRLenVT = Subtarget.getGRLenVT();
9969 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9978 return CI->isMustTailCall();
9983 std::vector<SDValue> OutChains;
9992 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9994 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10011 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10020 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10021 assert(ArgPartOffset == 0);
10022 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10024 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10048 int VaArgOffset, VarArgsSaveSize;
10052 if (ArgRegs.
size() == Idx) {
10054 VarArgsSaveSize = 0;
10056 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10057 VaArgOffset = -VarArgsSaveSize;
10063 LoongArchFI->setVarArgsFrameIndex(FI);
10071 VarArgsSaveSize += GRLenInBytes;
10076 for (
unsigned I = Idx;
I < ArgRegs.
size();
10077 ++
I, VaArgOffset += GRLenInBytes) {
10078 const Register Reg = RegInfo.createVirtualRegister(RC);
10079 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10087 ->setValue((
Value *)
nullptr);
10088 OutChains.push_back(
Store);
10090 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10095 if (!OutChains.empty()) {
10096 OutChains.push_back(Chain);
10111 if (
N->getNumValues() != 1)
10113 if (!
N->hasNUsesOfValue(1, 0))
10116 SDNode *Copy = *
N->user_begin();
10122 if (Copy->getGluedNode())
10126 bool HasRet =
false;
10128 if (
Node->getOpcode() != LoongArchISD::RET)
10136 Chain = Copy->getOperand(0);
10141bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10145 auto CalleeCC = CLI.CallConv;
10146 auto &Outs = CLI.Outs;
10148 auto CallerCC = Caller.getCallingConv();
10150 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10159 for (
auto &Arg : Outs)
10160 if (Arg.Flags.isByVal())
10176 for (
auto &VA : ArgLocs)
10182 auto IsCallerStructRet = Caller.hasStructRetAttr();
10183 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10184 if (IsCallerStructRet || IsCalleeStructRet)
10189 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10190 if (CalleeCC != CallerCC) {
10191 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10192 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10218 MVT GRLenVT = Subtarget.getGRLenVT();
10230 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10234 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10240 "site marked musttail");
10247 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10249 if (!Flags.isByVal())
10253 unsigned Size = Flags.getByValSize();
10254 Align Alignment = Flags.getNonZeroByValAlign();
10261 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10263 false,
nullptr, std::nullopt,
10275 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10278 SDValue ArgValue = OutVals[OutIdx];
10286 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10287 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10299 if (!StackPtr.getNode())
10311 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10325 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10345 const Argument *FormalArg =
nullptr;
10346 unsigned FilteredIdx = 0;
10347 for (
const auto &CallArg : CLI.
CB->
args()) {
10348 if (CallArg->getType()->isEmptyTy())
10350 if (FilteredIdx == CallArgIdx) {
10359 unsigned FormalArgIdx = CallArgIdx;
10361 FormalArgIdx = FormalArg->
getArgNo();
10365 if (Arg.getType()->isEmptyTy())
10367 if (FilteredIdx == CallArgIdx) {
10368 FormalArgIdx = Arg.getArgNo();
10381 SDValue IncomingPtr = CopyOp;
10398 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10399 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10400 SDValue PartValue = OutVals[OutIdx + 1];
10401 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10412 ArgValue = IncomingPtr;
10416 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10428 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10429 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10430 assert(ArgPartOffset == 0);
10435 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10436 SDValue PartValue = OutVals[OutIdx + 1];
10437 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10449 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10451 for (
const auto &Part : Parts) {
10452 SDValue PartValue = Part.first;
10453 SDValue PartOffset = Part.second;
10460 ArgValue = SpillSlot;
10467 if (Flags.isByVal())
10468 ArgValue = ByValArgs[j++];
10476 "Tail call not allowed if stack is used for passing parameters");
10479 if (!StackPtr.getNode())
10492 if (!MemOpChains.
empty())
10498 for (
auto &Reg : RegsToPass) {
10499 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10521 Ops.push_back(Chain);
10522 Ops.push_back(Callee);
10526 for (
auto &Reg : RegsToPass)
10527 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10532 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10533 assert(Mask &&
"Missing call preserved mask for calling convention");
10539 Ops.push_back(Glue);
10548 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10551 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10554 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10555 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10577 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10580 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10581 auto &VA = RVLocs[i];
10589 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10590 assert(VA.needsCustom());
10595 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10596 RetValue, RetValue2);
10609 const Type *RetTy)
const {
10611 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10613 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10617 Outs[i].Flags, CCInfo,
true,
nullptr))
10643 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10644 SDValue Val = OutVals[OutIdx];
10653 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10657 Register RegHi = RVLocs[++i].getLocReg();
10682 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10690 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10693 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10695 RequiredImm = (0b10101 << 8) | (V >> 8);
10696 return {
true, RequiredImm};
10697 }
else if (SplatBitSize == 32) {
10699 if (!(V & 0xFFFF00FF)) {
10700 RequiredImm = (0b10001 << 8) | (V >> 8);
10701 return {
true, RequiredImm};
10704 if (!(V & 0xFF00FFFF)) {
10705 RequiredImm = (0b10010 << 8) | (V >> 16);
10706 return {
true, RequiredImm};
10709 if (!(V & 0x00FFFFFF)) {
10710 RequiredImm = (0b10011 << 8) | (V >> 24);
10711 return {
true, RequiredImm};
10714 if ((V & 0xFFFF00FF) == 0xFF) {
10715 RequiredImm = (0b10110 << 8) | (V >> 8);
10716 return {
true, RequiredImm};
10719 if ((V & 0xFF00FFFF) == 0xFFFF) {
10720 RequiredImm = (0b10111 << 8) | (V >> 16);
10721 return {
true, RequiredImm};
10724 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
10726 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10727 return {
true, RequiredImm};
10729 }
else if (SplatBitSize == 64) {
10731 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
10732 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
10734 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10735 return {
true, RequiredImm};
10738 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
10739 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
10741 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
10742 return {
true, RequiredImm};
10745 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
10747 for (
int i = 0; i < 8; ++i) {
10749 if (
byte == 0 ||
byte == 0xFF)
10750 res |= ((
byte & 1) << i);
10755 return {
true, res};
10757 auto [IsSame, Suffix] = sameBitsPreByte(V);
10759 RequiredImm = (0b11001 << 8) | Suffix;
10760 return {
true, RequiredImm};
10763 return {
false, RequiredImm};
10768 if (!Subtarget.hasExtLSX())
10771 if (VT == MVT::f32) {
10772 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
10773 return (masked == 0x3e000000 || masked == 0x40000000);
10776 if (VT == MVT::f64) {
10777 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
10778 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
10784bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
10785 bool ForCodeSize)
const {
10787 if (VT == MVT::f32 && !Subtarget.hasBasicF())
10789 if (VT == MVT::f64 && !Subtarget.hasBasicD())
10802bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
10812 Type *Ty =
I->getOperand(0)->getType();
10814 unsigned Size = Ty->getIntegerBitWidth();
10834 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
10839 if (Subtarget.hasExtLASX())
10841 else if (Subtarget.hasExtLSX())
10848 EVT VT =
Y.getValueType();
10851 return Subtarget.hasExtLSX() && VT.
isInteger();
10862 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
10863 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
10864 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
10865 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
10868 Info.memVT = MVT::i32;
10869 Info.ptrVal =
I.getArgOperand(0);
10871 Info.align =
Align(4);
10890 "Unable to expand");
10891 unsigned MinWordSize = 4;
10903 Value *AlignedAddr = Builder.CreateIntrinsic(
10904 Intrinsic::ptrmask, {PtrTy, IntTy},
10905 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
10908 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
10909 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
10910 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
10911 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
10912 Value *Mask = Builder.CreateShl(
10913 ConstantInt::get(WordType,
10914 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
10916 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
10917 Value *ValOperand_Shifted =
10918 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
10919 ShiftAmt,
"ValOperand_Shifted");
10922 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
10924 NewOperand = ValOperand_Shifted;
10927 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
10930 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
10931 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
10932 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
10951 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
10959 if (Subtarget.hasLAMCAS()) {
10981 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
10983 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
10985 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
10987 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
10989 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
10991 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
10993 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
10995 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11005 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11007 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11009 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11011 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11013 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11015 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11017 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11019 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11031 if (Subtarget.hasLAMCAS())
11043 unsigned GRLen = Subtarget.getGRLen();
11045 Value *FailureOrdering =
11046 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
11047 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11049 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11050 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11051 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11052 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11055 Value *Result = Builder.CreateIntrinsic(
11056 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11058 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11074 Builder.CreateNot(Mask,
"Inv_Mask"),
11081 unsigned GRLen = Subtarget.getGRLen();
11090 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11091 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11092 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11105 unsigned ValWidth =
11108 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11109 Result = Builder.CreateCall(LlwOpScwLoop,
11110 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11113 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11117 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11140 const Constant *PersonalityFn)
const {
11141 return LoongArch::R4;
11145 const Constant *PersonalityFn)
const {
11146 return LoongArch::R5;
11157 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11158 return RefinementSteps;
11163 assert(Subtarget.hasFrecipe() &&
11164 "Reciprocal estimate queried on unsupported target");
11175 return Subtarget.hasBasicD();
11179 return Subtarget.hasExtLSX();
11183 return Subtarget.hasExtLASX();
11192 int &RefinementSteps,
11193 bool &UseOneConstNR,
11194 bool Reciprocal)
const {
11196 "Enabled should never be Disabled here");
11198 if (!Subtarget.hasFrecipe())
11213 UseOneConstNR =
false;
11219 if (Reciprocal || RefinementSteps > 0)
11229 int &RefinementSteps)
const {
11231 "Enabled should never be Disabled here");
11233 if (!Subtarget.hasFrecipe())
11247 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11255LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11275 if (Constraint.
size() == 1) {
11276 switch (Constraint[0]) {
11292 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11301 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11308std::pair<unsigned, const TargetRegisterClass *>
11309LoongArchTargetLowering::getRegForInlineAsmConstraint(
11313 if (Constraint.
size() == 1) {
11314 switch (Constraint[0]) {
11319 return std::make_pair(0U, &LoongArch::GPRRegClass);
11321 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11323 if (Subtarget.hasBasicF() && VT == MVT::f32)
11324 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11325 if (Subtarget.hasBasicD() && VT == MVT::f64)
11326 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11327 if (Subtarget.hasExtLSX() &&
11328 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11329 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11330 if (Subtarget.hasExtLASX() &&
11331 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11332 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11352 bool IsFP = Constraint[2] ==
'f';
11353 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11354 std::pair<unsigned, const TargetRegisterClass *>
R;
11359 unsigned RegNo =
R.first;
11360 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11361 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11362 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11363 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11373void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11377 if (Constraint.
size() == 1) {
11378 switch (Constraint[0]) {
11382 uint64_t CVal =
C->getSExtValue();
11385 Subtarget.getGRLenVT()));
11391 uint64_t CVal =
C->getSExtValue();
11394 Subtarget.getGRLenVT()));
11400 if (
C->getZExtValue() == 0)
11407 uint64_t CVal =
C->getZExtValue();
11420#define GET_REGISTER_MATCHER
11421#include "LoongArchGenAsmMatcher.inc"
11427 std::string NewRegName = Name.second.str();
11433 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11434 if (!ReservedRegs.
test(Reg))
11451 const APInt &Imm = ConstNode->getAPIntValue();
11453 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
11454 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
11457 if (ConstNode->hasOneUse() &&
11458 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
11459 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
11465 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
11466 unsigned Shifts = Imm.countr_zero();
11472 APInt ImmPop = Imm.ashr(Shifts);
11473 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11477 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
11478 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
11479 (ImmSmall - Imm).isPowerOf2())
11489 Type *Ty,
unsigned AS,
11508 switch (AM.
Scale) {
11544 EVT MemVT = LD->getMemoryVT();
11545 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11556 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11565 if (
Y.getValueType().isVector())
11577 Type *Ty,
bool IsSigned)
const {
11578 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11587 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11588 Type.getSizeInBits() < Subtarget.getGRLen()))
11598 Align &PrefAlign)
const {
11602 if (Subtarget.is64Bit()) {
11604 PrefAlign =
Align(8);
11607 PrefAlign =
Align(4);
11622bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11624 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
11625 bool IsABIRegCopy = CC.has_value();
11628 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11629 PartVT == MVT::f32) {
11644SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11646 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11647 bool IsABIRegCopy = CC.has_value();
11649 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11650 PartVT == MVT::f32) {
11667 if (VT == MVT::f16 && Subtarget.hasBasicF())
11673unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11676 if (VT == MVT::f16 && Subtarget.hasBasicF())
11685 unsigned Opc =
Op.getOpcode();
11690 case LoongArchISD::VPICK_ZEXT_ELT: {
11694 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
11695 Known.Zero.setBitsFrom(VTBits);
11704 unsigned Depth)
const {
11705 EVT VT =
Op.getValueType();
11707 unsigned Opc =
Op.getOpcode();
11711 case LoongArchISD::CRC_W_B_W:
11712 case LoongArchISD::CRC_W_H_W:
11713 case LoongArchISD::CRCC_W_B_W:
11714 case LoongArchISD::CRCC_W_H_W: {
11716 APInt DemandedSrcBits =
11718 Opc == LoongArchISD::CRCC_W_B_W)
11722 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
11724 case LoongArchISD::VMSKLTZ:
11725 case LoongArchISD::XVMSKLTZ: {
11727 MVT SrcVT = Src.getSimpleValueType();
11732 if (OriginalDemandedBits.
countr_zero() >= NumElts)
11736 APInt KnownUndef, KnownZero;
11752 if (KnownSrc.
One[SrcBits - 1])
11753 Known.One.setLowBits(NumElts);
11754 else if (KnownSrc.
Zero[SrcBits - 1])
11755 Known.Zero.setLowBits(NumElts);
11759 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
11766 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
11789 unsigned Index)
const {
11798 unsigned Index)
const {
11802 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
11817 Align StackAlign)
const {
11821 unsigned StackProbeSize =
11825 return StackProbeSize ? StackProbeSize : StackAlign.
value();
11829LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
11843 const EVT VT =
Op.getValueType();
11854 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
11864 const Register TargetReg =
MI.getOperand(0).getReg();
11867 const bool IsLA64 = Subtarget.is64Bit();
11868 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
11875 MF.
insert(MBBInsertPoint, LoopTestMBB);
11878 MF.
insert(MBBInsertPoint, ExitMBB);
11889 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
11895 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
11901 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
11916 MBB->addSuccessor(LoopTestMBB);
11918 MI.eraseFromParent();
11920 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< 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 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 SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue 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_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 LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, 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...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
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 getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
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.
@ 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.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ 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.
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...
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
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).
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)