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)
114 if (Subtarget.hasBasicF())
172 if (Subtarget.is64Bit()) {
200 if (!Subtarget.is64Bit()) {
206 if (Subtarget.hasBasicD())
218 if (Subtarget.hasBasicF()) {
252 if (Subtarget.is64Bit())
255 if (!Subtarget.hasBasicD()) {
257 if (Subtarget.is64Bit()) {
266 if (Subtarget.hasBasicD()) {
299 if (Subtarget.is64Bit())
305 if (Subtarget.hasExtLSX()) {
320 for (
MVT VT : LSXVTs) {
334 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
364 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
366 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
372 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
396 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
397 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
412 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
414 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
421 if (Subtarget.hasExtLASX()) {
422 for (
MVT VT : LASXVTs) {
437 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
466 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
468 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
470 for (
MVT VT : {MVT::v8i32, MVT::v4i64})
472 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
477 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
496 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
502 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
506 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
511 if (Subtarget.hasBasicF()) {
528 if (Subtarget.has32S())
533 if (Subtarget.hasExtLSX()) {
548 if (Subtarget.hasExtLASX()) {
573 if (Subtarget.hasLAMCAS())
576 if (Subtarget.hasSCQ()) {
596 switch (
Op.getOpcode()) {
598 return lowerATOMIC_FENCE(
Op, DAG);
600 return lowerEH_DWARF_CFA(
Op, DAG);
602 return lowerGlobalAddress(
Op, DAG);
604 return lowerGlobalTLSAddress(
Op, DAG);
606 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
608 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
610 return lowerINTRINSIC_VOID(
Op, DAG);
612 return lowerBlockAddress(
Op, DAG);
614 return lowerJumpTable(
Op, DAG);
616 return lowerShiftLeftParts(
Op, DAG);
618 return lowerShiftRightParts(
Op, DAG,
true);
620 return lowerShiftRightParts(
Op, DAG,
false);
622 return lowerConstantPool(
Op, DAG);
624 return lowerFP_TO_SINT(
Op, DAG);
626 return lowerFP_TO_UINT(
Op, DAG);
628 return lowerFP_TO_SINT_SAT(
Op, DAG);
630 return lowerBITCAST(
Op, DAG);
632 return lowerUINT_TO_FP(
Op, DAG);
634 return lowerSINT_TO_FP(
Op, DAG);
636 return lowerVASTART(
Op, DAG);
638 return lowerFRAMEADDR(
Op, DAG);
640 return lowerRETURNADDR(
Op, DAG);
642 return lowerSET_ROUNDING(
Op, DAG);
644 return lowerGET_ROUNDING(
Op, DAG);
646 return lowerWRITE_REGISTER(
Op, DAG);
648 return lowerINSERT_VECTOR_ELT(
Op, DAG);
650 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
652 return lowerBUILD_VECTOR(
Op, DAG);
654 return lowerCONCAT_VECTORS(
Op, DAG);
656 return lowerVECTOR_SHUFFLE(
Op, DAG);
658 return lowerBITREVERSE(
Op, DAG);
660 return lowerSCALAR_TO_VECTOR(
Op, DAG);
662 return lowerPREFETCH(
Op, DAG);
664 return lowerSELECT(
Op, DAG);
666 return lowerBRCOND(
Op, DAG);
668 return lowerFP_TO_FP16(
Op, DAG);
670 return lowerFP16_TO_FP(
Op, DAG);
672 return lowerFP_TO_BF16(
Op, DAG);
674 return lowerBF16_TO_FP(
Op, DAG);
676 return lowerVECREDUCE_ADD(
Op, DAG);
679 return lowerRotate(
Op, DAG);
687 return lowerVECREDUCE(
Op, DAG);
689 return lowerConstantFP(
Op, DAG);
691 return lowerSETCC(
Op, DAG);
693 return lowerFP_ROUND(
Op, DAG);
695 return lowerFP_EXTEND(
Op, DAG);
697 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
699 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
701 return lowerANY_EXTEND(
Op, DAG);
710 EVT VT =
V.getValueType();
716 return V.getOperand(0);
722 Not = DAG.
getBitcast(
V.getOperand(0).getValueType(), Not);
732 if (!
V->isOnlyUserOf(SplatValue.getNode()))
736 Not = DAG.
getBitcast(
V.getOperand(0).getValueType(), Not);
744 V.getOperand(0).hasOneUse() &&
V.getOperand(1).hasOneUse()) {
772 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
773 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
780 if (Opcode0 != Opcode1)
783 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
790 EVT VT =
N.getValueType();
805 SSVT0 == MVT::v4f64) {
824 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
825 N->getOpcode() == LoongArchISD::VPERMI) &&
826 Opcode0 == LoongArchISD::VFCVT) {
831 if (!
Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
834 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
835 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
841 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
857 MVT VT =
Op.getSimpleValueType();
858 MVT SVT =
In.getSimpleValueType();
860 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
873 EVT VT =
Op.getValueType();
875 EVT SVT = Src.getValueType();
878 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
880 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
881 if (!V2F32ToV2F64 && !V4F32ToV4F64)
908 if (
SDValue V = CheckVecHighPart(Src)) {
910 "Unexpected wide vector");
911 Opcode = LoongArchISD::VFCVTH;
914 Opcode = LoongArchISD::VFCVTL;
916 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
921 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
927 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
939 EVT VT =
Op.getValueType();
944 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
945 (VT == MVT::f64 && Subtarget.hasBasicD()));
963 if (VT == MVT::f32) {
964 assert(Subtarget.is64Bit());
967 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, VT, NewVal);
970 assert(VT == MVT::f64 && !Subtarget.is64Bit());
973 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
981 EVT ResultVT =
Op.getValueType();
982 EVT OperandVT =
Op.getOperand(0).getValueType();
987 if (ResultVT == SetCCResultVT)
990 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
991 "SETCC operands must have the same type!");
995 Op.getOperand(1),
Op.getOperand(2));
997 if (ResultVT.
bitsGT(SetCCResultVT))
999 else if (ResultVT.
bitsLT(SetCCResultVT))
1028SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1032 MVT SrcVT = Src.getSimpleValueType();
1033 MVT DstVT =
Op.getSimpleValueType();
1039 unsigned Ratio = DstEltBits / SrcEltBits;
1048 if (Ratio == 2 && !IsSignSplat)
1049 return DAG.
getNode(LoongArchISD::VSLLWIL,
DL, DstVT, Src,
1053 for (
unsigned EltBits = SrcEltBits; EltBits < DstEltBits; EltBits *= 2) {
1056 Res = DAG.
getNode(LoongArchISD::VILVL,
DL, VT, Res, Res);
1068 assert(Subtarget.hasExtLASX());
1087 MVT OpVT =
Op.getSimpleValueType();
1094 unsigned LegalVecSize = 128;
1095 bool isLASX256Vector =
1105 if (isLASX256Vector) {
1111 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1112 EleBits = std::min(EleBits, 64u);
1115 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1118 if (isLASX256Vector) {
1144 MVT OpVT =
Op.getSimpleValueType();
1157 MVT GRLenVT = Subtarget.getGRLenVT();
1159 for (
int i = NumEles; i > 1; i /= 2) {
1162 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1171 unsigned IsData =
Op.getConstantOperandVal(4);
1176 return Op.getOperand(0);
1183 MVT VT =
Op.getSimpleValueType();
1189 unsigned Opcode =
Op.getOpcode();
1192 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1198 CstSplatValue =
C->getAPIntValue();
1206 APInt CstSplatValue;
1207 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1211 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1227 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1243 if (
LHS == LHS2 &&
RHS == RHS2) {
1248 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1256 return std::nullopt;
1264 MVT VT =
N->getSimpleValueType(0);
1295 if (~TrueVal == FalseVal) {
1335 unsigned SelOpNo = 0;
1345 unsigned ConstSelOpNo = 1;
1346 unsigned OtherSelOpNo = 2;
1353 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1358 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1364 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1366 std::swap(NewConstOps[0], NewConstOps[1]);
1378 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1380 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1383 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1384 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1404 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1418 int64_t
C = RHSC->getSExtValue();
1461 MVT VT =
Op.getSimpleValueType();
1462 MVT GRLenVT = Subtarget.getGRLenVT();
1467 if (
Op.hasOneUse()) {
1468 unsigned UseOpc =
Op->user_begin()->getOpcode();
1470 SDNode *BinOp = *
Op->user_begin();
1477 return lowerSELECT(NewSel, DAG);
1494 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1517 if (TrueVal - 1 == FalseVal)
1519 if (TrueVal + 1 == FalseVal)
1526 RHS == TrueV &&
LHS == FalseV) {
1551 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1558 MVT GRLenVT = Subtarget.getGRLenVT();
1569 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1570 Op.getOperand(0),
LHS,
RHS, TargetCC,
1573 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1574 Op.getOperand(0), CondV,
Op.getOperand(2));
1578 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1584LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1587 MVT OpVT =
Op.getSimpleValueType();
1598 EVT ResTy =
Op->getValueType(0);
1603 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1613 for (
unsigned int i = 0; i < NewEltNum; i++) {
1616 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1617 ? (
unsigned)LoongArchISD::BITREV_8B
1635 for (
unsigned int i = 0; i < NewEltNum; i++)
1636 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1637 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1655 if (EltBits > 32 || EltBits == 1)
1683 int MaskOffset,
const APInt &Zeroable) {
1684 int Size = Mask.size();
1685 unsigned SizeInBits =
Size * ScalarSizeInBits;
1687 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1688 for (
int i = 0; i <
Size; i += Scale)
1689 for (
int j = 0; j < Shift; ++j)
1690 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1698 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1699 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1704 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1705 for (
int i = 0; i !=
Size; i += Scale) {
1706 unsigned Pos =
Left ? i + Shift : i;
1707 unsigned Low =
Left ? i : i + Shift;
1708 unsigned Len = Scale - Shift;
1713 int ShiftEltBits = ScalarSizeInBits * Scale;
1714 bool ByteShift = ShiftEltBits > 64;
1715 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1716 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1717 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1721 Scale = ByteShift ? Scale / 2 : Scale;
1727 return (
int)ShiftAmt;
1730 unsigned MaxWidth = 128;
1731 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1732 for (
int Shift = 1; Shift != Scale; ++Shift)
1733 for (
bool Left : {
true,
false})
1734 if (CheckZeros(Shift, Scale,
Left)) {
1735 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1760 const APInt &Zeroable) {
1761 int Size = Mask.size();
1775 Mask,
Size, Zeroable);
1783 "Illegal integer vector type");
1792template <
typename ValType>
1795 unsigned CheckStride,
1797 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1801 if (*
I != -1 && *
I != ExpectedIndex)
1803 ExpectedIndex += ExpectedIndexStride;
1807 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1819 int Size = Mask.size();
1828 int VectorSizeInBits =
V1.getValueSizeInBits();
1829 int ScalarSizeInBits = VectorSizeInBits /
Size;
1830 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1831 (void)ScalarSizeInBits;
1833 for (
int i = 0; i <
Size; ++i) {
1839 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1856 RepeatedMask.
assign(LaneSize, -1);
1857 int Size = Mask.size();
1858 for (
int i = 0; i <
Size; ++i) {
1859 assert(Mask[i] == -1 || Mask[i] >= 0);
1862 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1869 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1870 if (RepeatedMask[i % LaneSize] < 0)
1872 RepeatedMask[i % LaneSize] = LocalM;
1873 else if (RepeatedMask[i % LaneSize] != LocalM)
1890 int NumElts = RepeatedMask.
size();
1892 int Scale = 16 / NumElts;
1894 for (
int i = 0; i < NumElts; ++i) {
1895 int M = RepeatedMask[i];
1896 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1897 "Unexpected mask index.");
1902 int StartIdx = i - (M % NumElts);
1909 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1912 Rotation = CandidateRotation;
1913 else if (Rotation != CandidateRotation)
1928 else if (TargetV != MaskV)
1933 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1934 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1943 return Rotation * Scale;
1962 if (ByteRotation <= 0)
1969 int LoByteShift = 16 - ByteRotation;
1970 int HiByteShift = ByteRotation;
1993 const APInt &Zeroable) {
2007 for (
int i = 0; i < NumElements; i++) {
2011 if (i % Scale != 0) {
2023 M = M % NumElements;
2026 Offset = M - (i / Scale);
2029 if (
Offset % (NumElements / Scale))
2031 }
else if (InputV !=
V)
2034 if (M != (
Offset + (i / Scale)))
2044 unsigned VilVLoHi = LoongArchISD::VILVL;
2045 if (
Offset >= (NumElements / 2)) {
2046 VilVLoHi = LoongArchISD::VILVH;
2047 Offset -= (NumElements / 2);
2055 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2059 }
while (Scale > 1);
2065 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2066 NumExtElements *= 2) {
2086 int SplatIndex = -1;
2087 for (
const auto &M : Mask) {
2094 if (SplatIndex == -1)
2097 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2099 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2129 unsigned SubVecSize = 4;
2130 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2133 int SubMask[4] = {-1, -1, -1, -1};
2134 for (
unsigned i = 0; i < SubVecSize; ++i) {
2135 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2141 M -= 4 * (j / SubVecSize);
2142 if (M < 0 || M >= 4)
2148 if (SubMask[i] == -1)
2152 else if (M != -1 && M != SubMask[i])
2159 for (
int i = SubVecSize - 1; i >= 0; --i) {
2172 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2173 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2176 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2194 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2203 for (
int i = 0; i < WidenNumElts; ++i)
2204 WidenMask[i] = WidenNumElts - 1 - i;
2212 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2236 const auto &Begin = Mask.begin();
2237 const auto &
End = Mask.end();
2254 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2276 const auto &Begin = Mask.begin();
2277 const auto &
End = Mask.end();
2294 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2317 const auto &Begin = Mask.begin();
2318 const auto &
End = Mask.end();
2319 unsigned HalfSize = Mask.size() / 2;
2337 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2360 const auto &Begin = Mask.begin();
2361 const auto &
End = Mask.end();
2378 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2400 const auto &Begin = Mask.begin();
2401 const auto &Mid = Mask.begin() + Mask.size() / 2;
2402 const auto &
End = Mask.end();
2420 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2442 const auto &Begin = Mask.begin();
2443 const auto &Mid = Mask.begin() + Mask.size() / 2;
2444 const auto &
End = Mask.end();
2461 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2487 if (Mask.size() != NumElts)
2490 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2493 for (
unsigned i = 0; i < NumElts; ++i) {
2496 if (Mask[i] !=
int(
Base + i)) {
2509 int DiffMask = Mask[DiffPos];
2510 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2516 if (
unsigned(DiffMask) < NumElts) {
2521 SrcIdx =
unsigned(DiffMask) - NumElts;
2537 if (
SDValue Result = tryLowerToExtrAndIns(0))
2539 return tryLowerToExtrAndIns(NumElts);
2547 unsigned &MaskImm) {
2548 unsigned MaskSize = Mask.size();
2551 return (M == -1) || (M >=
Off && M <
Off + 4);
2554 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2555 auto immPart = [&](
int M,
unsigned Off) {
2556 return (M == -1 ? 0 : (M -
Off)) & 0x3;
2558 MaskImm |= immPart(MLo,
Off) << (
I * 2);
2559 MaskImm |= immPart(MHi,
Off) << ((
I + 1) * 2);
2562 for (
unsigned i = 0; i < 4; i += 2) {
2564 int MHi = Mask[i + 1];
2566 if (MaskSize == 8) {
2567 auto isValid2 = [&](
int &M,
int M2) {
2574 if ((M2 % MaskSize) < 4)
2582 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2588 buildImm(MLo, MHi, 0, i);
2591 buildImm(MLo, MHi, MaskSize, i);
2621 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2626 unsigned MaskImm = 0;
2630 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2657 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2670 "Vector type is unsupported for lsx!");
2672 "Two operands have different types!");
2674 "Unexpected mask size for shuffle!");
2675 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2677 APInt KnownUndef, KnownZero;
2679 APInt Zeroable = KnownUndef | KnownZero;
2752 int SplatIndex = -1;
2753 for (
const auto &M : Mask) {
2760 if (SplatIndex == -1)
2763 const auto &Begin = Mask.begin();
2764 const auto &
End = Mask.end();
2765 int HalfSize = Mask.size() / 2;
2767 if (SplatIndex >= HalfSize)
2770 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2774 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2788 if (Mask.size() == 4) {
2789 unsigned MaskImm = 0;
2790 for (
int i = 1; i >= 0; --i) {
2792 int MHi = Mask[i + 2];
2793 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2794 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2796 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2801 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2803 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2806 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2827 return DAG.
getNode(LoongArchISD::XVREPLVE0,
DL, VT,
V1);
2836 unsigned MaskSize = Mask.size();
2841 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2843 unsigned MaskImm = 0;
2847 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2852 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2853 unsigned MaskImm = 0;
2854 for (
unsigned i = 0; i < MaskSize; ++i) {
2857 if (Mask[i] >= (
int)MaskSize)
2859 MaskImm |= Mask[i] << (i * 2);
2862 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2874 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2878 unsigned HalfSize = NumElts / 2;
2879 bool FrontLo =
true, FrontHi =
true;
2880 bool BackLo =
true, BackHi =
true;
2882 auto inRange = [](
int val,
int low,
int high) {
2883 return (val == -1) || (val >= low && val < high);
2886 for (
unsigned i = 0; i < HalfSize; ++i) {
2887 int Fronti = Mask[i];
2888 int Backi = Mask[i + HalfSize];
2890 FrontLo &=
inRange(Fronti, 0, HalfSize);
2891 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2892 BackLo &=
inRange(Backi, 0, HalfSize);
2893 BackHi &=
inRange(Backi, HalfSize, NumElts);
2899 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2904 for (
unsigned i = 0; i < NumElts; ++i)
2909 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2931 const auto &Begin = Mask.begin();
2932 const auto &
End = Mask.end();
2933 unsigned HalfSize = Mask.size() / 2;
2934 unsigned LeftSize = HalfSize / 2;
2942 Mask.size() + HalfSize - LeftSize, 1) &&
2944 Mask.size() + HalfSize + LeftSize, 1))
2955 Mask.size() + HalfSize - LeftSize, 1) &&
2957 Mask.size() + HalfSize + LeftSize, 1))
2962 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2970 const auto &Begin = Mask.begin();
2971 const auto &
End = Mask.end();
2972 unsigned HalfSize = Mask.size() / 2;
2980 Mask.size() + HalfSize, 1))
2991 Mask.size() + HalfSize, 1))
2996 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
3004 const auto &Begin = Mask.begin();
3005 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3006 const auto &Mid = Mask.begin() + Mask.size() / 2;
3007 const auto &RightMid = Mask.end() - Mask.size() / 4;
3008 const auto &
End = Mask.end();
3009 unsigned HalfSize = Mask.size() / 2;
3031 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
3039 const auto &Begin = Mask.begin();
3040 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3041 const auto &Mid = Mask.begin() + Mask.size() / 2;
3042 const auto &RightMid = Mask.end() - Mask.size() / 4;
3043 const auto &
End = Mask.end();
3044 unsigned HalfSize = Mask.size() / 2;
3067 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3076 int HalfSize = NumElts / 2;
3080 if ((
int)Mask.size() != NumElts)
3083 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3085 for (
int i = 0; i < NumElts; ++i) {
3088 if (Mask[i] !=
Base + i) {
3090 if (DiffPos.
size() > 2)
3098 if (DiffPos.
size() == 1) {
3099 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3100 DiffPos.
push_back(DiffPos[0] + HalfSize);
3101 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3102 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3106 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3110 int DiffMaskLo = Mask[DiffPos[0]];
3111 int DiffMaskHi = Mask[DiffPos[1]];
3112 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3113 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3114 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3115 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3117 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3118 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3120 if (DiffMaskHi != DiffMaskLo + HalfSize)
3124 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3126 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3147 if (
SDValue Result = tryLowerToExtrAndIns(0))
3149 return tryLowerToExtrAndIns(NumElts);
3158 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3163 int MaskSize = Mask.size();
3169 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3171 for (
int i = 0; i < MaskSize; ++i) {
3172 if (Mask[i] ==
Base + i || Mask[i] == -1)
3174 if (Mask[i] != Replaced)
3185 int Idx = checkReplaceOne(0, MaskSize);
3187 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3191 Idx = checkReplaceOne(MaskSize, 0);
3193 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3204 int MaskSize = Mask.size();
3205 int HalfSize = Mask.size() / 2;
3206 const auto &Begin = Mask.begin();
3207 const auto &Mid = Mask.begin() + HalfSize;
3208 const auto &
End = Mask.end();
3220 for (
auto it = Begin; it < Mid; it++) {
3223 else if ((*it >= 0 && *it < HalfSize) ||
3224 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3225 int M = *it < HalfSize ? *it : *it - HalfSize;
3230 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3232 for (
auto it = Mid; it <
End; it++) {
3235 else if ((*it >= HalfSize && *it < MaskSize) ||
3236 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3237 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3242 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3246 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3274 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3276 int MaskSize = Mask.size();
3277 int HalfSize = Mask.size() / 2;
3280 HalfMaskType preMask =
None, postMask =
None;
3282 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3283 return M < 0 || (M >= 0 && M < HalfSize) ||
3284 (M >= MaskSize && M < MaskSize + HalfSize);
3286 preMask = HighLaneTy;
3287 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3288 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3289 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3291 preMask = LowLaneTy;
3293 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3294 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3295 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3297 postMask = LowLaneTy;
3298 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3299 return M < 0 || (M >= 0 && M < HalfSize) ||
3300 (M >= MaskSize && M < MaskSize + HalfSize);
3302 postMask = HighLaneTy;
3310 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3313 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3321 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3326 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3327 *it = *it < 0 ? *it : *it - HalfSize;
3329 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3330 *it = *it < 0 ? *it : *it + HalfSize;
3332 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3340 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3345 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3346 *it = *it < 0 ? *it : *it - HalfSize;
3348 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3356 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3361 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3362 *it = *it < 0 ? *it : *it + HalfSize;
3389 int Lo = LaneMask[0] < 0 ? 0 : LaneMask[0];
3390 int Hi = LaneMask[1] < 0 ? 1 : LaneMask[1];
3392 LoongArchISD::XVPERMIQ,
DL, VT, V2,
V1,
3425 int Size = Mask.size();
3426 int LaneSize =
Size / 2;
3430 int LaneSrcs[2][2] = {{-1, -1}, {-1, -1}};
3432 bool LaneCrossing =
false;
3433 for (
int i = 0; i <
Size; ++i) {
3437 int Lane = i / LaneSize;
3438 int SrcLane = M / LaneSize;
3442 int Op = (SrcLane % 2) != Lane;
3444 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3446 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3448 LaneSrcs[Lane][
Op] = SrcLane;
3449 InLaneMask[i] =
Op *
Size + Lane * LaneSize + M % LaneSize;
3460 for (
int i = LaneSize; i <
Size; ++i)
3461 if (SwappedMask[i] >= 0)
3462 SwappedMask[i] = (SwappedMask[i] +
Size) % (2 *
Size);
3464 std::swap(LaneSrcs[1][0], LaneSrcs[1][1]);
3465 InLaneMask = SwappedMask;
3471 for (
int Op = 0;
Op < 2; ++
Op) {
3473 for (
int Lane = 0; Lane < 2; ++Lane)
3474 if (LaneSrcs[Lane][
Op] >= 0)
3475 for (
int i = 0; i < LaneSize; ++i)
3476 LaneMask[Lane * LaneSize + i] = LaneSrcs[Lane][
Op] * LaneSize + i;
3482 if (SVN->getMask() == Mask)
3498 "Vector type is unsupported for lasx!");
3500 "Two operands have different types!");
3502 "Unexpected mask size for shuffle!");
3503 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3504 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3506 APInt KnownUndef, KnownZero;
3508 APInt Zeroable = KnownUndef | KnownZero;
3599 ArrayRef<int> OrigMask = SVOp->
getMask();
3602 MVT VT =
Op.getSimpleValueType();
3606 bool V1IsUndef =
V1.isUndef();
3607 bool V2IsUndef = V2.
isUndef();
3608 if (V1IsUndef && V2IsUndef)
3621 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3622 SmallVector<int, 8> NewMask(OrigMask);
3623 for (
int &M : NewMask)
3624 if (M >= NumElements)
3630 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3631 (void)MaskUpperLimit;
3633 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3634 "Out of bounds shuffle index");
3656 std::tie(Res, Chain) =
3657 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3658 if (Subtarget.is64Bit())
3659 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3671 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3675 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3676 CallOptions,
DL, Chain);
3682 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3688 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3689 if (Subtarget.is64Bit())
3690 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3696 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3697 MVT VT =
Op.getSimpleValueType();
3702 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3723 "Unsupported vector type for broadcast.");
3726 bool IsIdeneity =
true;
3728 for (
int i = 0; i !=
NumOps; i++) {
3730 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3742 auto ExtType = LN->getExtensionType();
3747 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3752 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3770 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3784 EVT ResTy,
unsigned first) {
3787 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3790 Node->op_begin() + first + NumElts);
3799 MVT VT =
Node->getSimpleValueType(0);
3800 EVT ResTy =
Op->getValueType(0);
3803 APInt SplatValue, SplatUndef;
3804 unsigned SplatBitSize;
3807 bool UseSameConstant =
true;
3812 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3813 (!Subtarget.hasExtLASX() || !Is256Vec))
3819 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3821 SplatBitSize <= 64) {
3823 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3827 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3834 if ((Is128Vec && ResTy == MVT::v4i32) ||
3835 (Is256Vec && ResTy == MVT::v8i32))
3841 switch (SplatBitSize) {
3845 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3848 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3851 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3854 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3862 if (ViaVecTy != ResTy)
3871 for (
unsigned i = 0; i < NumElts; ++i) {
3876 ConstantValue = Opi;
3877 else if (ConstantValue != Opi)
3878 UseSameConstant =
false;
3883 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3885 for (
unsigned i = 0; i < NumElts; ++i) {
3903 BitVector UndefElements;
3904 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3905 UndefElements.
count() == 0) {
3909 EVT FillTy = Is256Vec
3915 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3918 unsigned SplatLen = NumElts / SeqLen;
3924 if (SplatEltTy == MVT::i128)
3925 SplatTy = MVT::v4i64;
3933 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3934 : LoongArchISD::XVREPLVE0,
3935 DL, SplatTy, SrcVec);
3937 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3950 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3951 ResTy == MVT::v4f64) {
3952 unsigned NonUndefCount = 0;
3953 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3954 if (!
Node->getOperand(i).isUndef()) {
3956 if (NonUndefCount > 1)
3960 if (NonUndefCount == 1)
3973 VecTy, NumElts / 2);
3984 MVT ResVT =
Op.getSimpleValueType();
3992 unsigned NumFreezeUndef = 0;
3993 unsigned NumZero = 0;
3994 unsigned NumNonZero = 0;
3995 unsigned NonZeros = 0;
3996 SmallSet<SDValue, 4> Undefs;
3997 for (
unsigned i = 0; i != NumOperands; ++i) {
4012 assert(i <
sizeof(NonZeros) * CHAR_BIT);
4019 if (NumNonZero > 2) {
4023 Ops.slice(0, NumOperands / 2));
4025 Ops.slice(NumOperands / 2));
4038 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
4040 for (
unsigned i = 0; i != NumOperands; ++i) {
4041 if ((NonZeros & (1 << i)) == 0)
4052LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
4054 MVT EltVT =
Op.getSimpleValueType();
4059 MVT GRLenVT = Subtarget.getGRLenVT();
4087 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
4091 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
4093 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
4102 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
4111LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
4113 MVT VT =
Op.getSimpleValueType();
4135 auto ExtType = LN->getExtensionType();
4136 if (LN->isSimple() &&
4138 LN->getMemoryVT().getSizeInBits() == EltSizeInBits) {
4140 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
4142 if (EltSizeInBits >= 32) {
4147 FltVT,
DL, LN->getChain(), LN->getBasePtr(), LN->getPointerInfo(),
4148 LN->getAlign(), LN->getMemOperand()->getFlags(), LN->getAAInfo());
4154 SDVTList Tys = DAG.
getVTList(VT, MVT::Other);
4155 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
4157 LN->getMemoryVT(), LN->getMemOperand());
4178 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4180 for (
unsigned i = 0; i < NumElts; ++i) {
4188 for (
unsigned i = 0; i < NumElts; ++i) {
4197 for (
unsigned i = 0; i < NumElts; ++i)
4250 MVT GRLenVT = Subtarget.getGRLenVT();
4262 "rounding mode is not supported by LoongArch hardware",
4263 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4280 FCSRNo, RMValue, Chain);
4286 MVT GRLenVT = Subtarget.getGRLenVT();
4293 MVT::Other, FCSRNo, Chain);
4309 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4311 "On LA64, only 64-bit registers can be written.");
4312 return Op.getOperand(0);
4315 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4317 "On LA32, only 32-bit registers can be written.");
4318 return Op.getOperand(0);
4328 "be a constant integer");
4334 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4335 EVT VT =
Op.getValueType();
4338 unsigned Depth =
Op.getConstantOperandVal(0);
4339 int GRLenInBytes = Subtarget.getGRLen() / 8;
4342 int Offset = -(GRLenInBytes * 2);
4354 if (
Op.getConstantOperandVal(0) != 0) {
4356 "return address can only be determined for the current frame");
4362 MVT GRLenVT = Subtarget.getGRLenVT();
4374 auto Size = Subtarget.getGRLen() / 8;
4382 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4392 MachinePointerInfo(SV));
4399 EVT VT =
Op.getValueType();
4414 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4422 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4425 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4426 !Subtarget.hasBasicD() &&
"unexpected target features");
4430 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4434 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4444 EVT RetVT =
Op.getValueType();
4450 std::tie(Result, Chain) =
4457 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4458 !Subtarget.hasBasicD() &&
"unexpected target features");
4469 EVT RetVT =
Op.getValueType();
4475 std::tie(Result, Chain) =
4484 EVT VT =
Op.getValueType();
4488 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4489 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4491 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4493 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4496 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4510 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4511 !Subtarget.hasBasicD()) {
4513 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4528 EVT VT =
Op.getValueType();
4529 EVT SrcVT = Src.getValueType();
4530 unsigned SatWidth =
cast<VTSDNode>(
Op.getOperand(1))->getVT().getSizeInBits();
4540 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4543 if (SatWidth == 32) {
4545 if (Subtarget.is64Bit())
4546 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, VT, Ftint);
4550 if (SatWidth == 64 && Subtarget.is64Bit() && Subtarget.hasBasicD()) {
4560 if (!Subtarget.hasExtLSX())
4565 EVT VT =
Op.getValueType();
4566 EVT SrcVT = Src.getValueType();
4571 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4574 if (SrcVT == MVT::f32)
4596 N->getOffset(), Flags);
4604template <
class NodeTy>
4607 bool IsLocal)
const {
4618 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4699 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4701 const GlobalValue *GV =
N->getGlobal();
4713 unsigned Opc,
bool UseGOT,
4717 MVT GRLenVT = Subtarget.getGRLenVT();
4731 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4772 TargetLowering::CallLoweringInfo CLI(DAG);
4787 const GlobalValue *GV =
N->getGlobal();
4801LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4808 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4811 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4824 return getDynamicTLSAddr(
N, DAG,
4825 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4826 : LoongArch::PseudoLA_TLS_GD,
4833 return getDynamicTLSAddr(
N, DAG,
4834 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4835 : LoongArch::PseudoLA_TLS_LD,
4840 return getStaticTLSAddr(
N, DAG,
4841 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4842 : LoongArch::PseudoLA_TLS_IE,
4849 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4853 return getTLSDescAddr(
N, DAG,
4854 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4855 : LoongArch::PseudoLA_TLS_DESC,
4859template <
unsigned N>
4864 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4865 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4867 ": argument out of range.");
4874LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4876 switch (
Op.getConstantOperandVal(0)) {
4879 case Intrinsic::thread_pointer: {
4883 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4884 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4885 case Intrinsic::loongarch_lsx_vreplvei_d:
4886 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4888 case Intrinsic::loongarch_lsx_vreplvei_w:
4889 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4890 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4891 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4892 case Intrinsic::loongarch_lasx_xvpickve_d:
4893 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4895 case Intrinsic::loongarch_lasx_xvinsve0_d:
4897 case Intrinsic::loongarch_lsx_vsat_b:
4898 case Intrinsic::loongarch_lsx_vsat_bu:
4899 case Intrinsic::loongarch_lsx_vrotri_b:
4900 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4901 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4902 case Intrinsic::loongarch_lsx_vsrlri_b:
4903 case Intrinsic::loongarch_lsx_vsrari_b:
4904 case Intrinsic::loongarch_lsx_vreplvei_h:
4905 case Intrinsic::loongarch_lasx_xvsat_b:
4906 case Intrinsic::loongarch_lasx_xvsat_bu:
4907 case Intrinsic::loongarch_lasx_xvrotri_b:
4908 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4909 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4910 case Intrinsic::loongarch_lasx_xvsrlri_b:
4911 case Intrinsic::loongarch_lasx_xvsrari_b:
4912 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4913 case Intrinsic::loongarch_lasx_xvpickve_w:
4914 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4916 case Intrinsic::loongarch_lasx_xvinsve0_w:
4918 case Intrinsic::loongarch_lsx_vsat_h:
4919 case Intrinsic::loongarch_lsx_vsat_hu:
4920 case Intrinsic::loongarch_lsx_vrotri_h:
4921 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4922 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4923 case Intrinsic::loongarch_lsx_vsrlri_h:
4924 case Intrinsic::loongarch_lsx_vsrari_h:
4925 case Intrinsic::loongarch_lsx_vreplvei_b:
4926 case Intrinsic::loongarch_lasx_xvsat_h:
4927 case Intrinsic::loongarch_lasx_xvsat_hu:
4928 case Intrinsic::loongarch_lasx_xvrotri_h:
4929 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4930 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4931 case Intrinsic::loongarch_lasx_xvsrlri_h:
4932 case Intrinsic::loongarch_lasx_xvsrari_h:
4933 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4935 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4936 case Intrinsic::loongarch_lsx_vsrani_b_h:
4937 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4938 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4939 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4940 case Intrinsic::loongarch_lsx_vssrani_b_h:
4941 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4942 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4943 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4944 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4945 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4946 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4947 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4948 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4949 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4950 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4951 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4952 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4953 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4954 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4955 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4956 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4957 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4958 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4960 case Intrinsic::loongarch_lsx_vsat_w:
4961 case Intrinsic::loongarch_lsx_vsat_wu:
4962 case Intrinsic::loongarch_lsx_vrotri_w:
4963 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4964 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4965 case Intrinsic::loongarch_lsx_vsrlri_w:
4966 case Intrinsic::loongarch_lsx_vsrari_w:
4967 case Intrinsic::loongarch_lsx_vslei_bu:
4968 case Intrinsic::loongarch_lsx_vslei_hu:
4969 case Intrinsic::loongarch_lsx_vslei_wu:
4970 case Intrinsic::loongarch_lsx_vslei_du:
4971 case Intrinsic::loongarch_lsx_vslti_bu:
4972 case Intrinsic::loongarch_lsx_vslti_hu:
4973 case Intrinsic::loongarch_lsx_vslti_wu:
4974 case Intrinsic::loongarch_lsx_vslti_du:
4975 case Intrinsic::loongarch_lsx_vbsll_v:
4976 case Intrinsic::loongarch_lsx_vbsrl_v:
4977 case Intrinsic::loongarch_lasx_xvsat_w:
4978 case Intrinsic::loongarch_lasx_xvsat_wu:
4979 case Intrinsic::loongarch_lasx_xvrotri_w:
4980 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4981 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4982 case Intrinsic::loongarch_lasx_xvsrlri_w:
4983 case Intrinsic::loongarch_lasx_xvsrari_w:
4984 case Intrinsic::loongarch_lasx_xvslei_bu:
4985 case Intrinsic::loongarch_lasx_xvslei_hu:
4986 case Intrinsic::loongarch_lasx_xvslei_wu:
4987 case Intrinsic::loongarch_lasx_xvslei_du:
4988 case Intrinsic::loongarch_lasx_xvslti_bu:
4989 case Intrinsic::loongarch_lasx_xvslti_hu:
4990 case Intrinsic::loongarch_lasx_xvslti_wu:
4991 case Intrinsic::loongarch_lasx_xvslti_du:
4992 case Intrinsic::loongarch_lasx_xvbsll_v:
4993 case Intrinsic::loongarch_lasx_xvbsrl_v:
4995 case Intrinsic::loongarch_lsx_vseqi_b:
4996 case Intrinsic::loongarch_lsx_vseqi_h:
4997 case Intrinsic::loongarch_lsx_vseqi_w:
4998 case Intrinsic::loongarch_lsx_vseqi_d:
4999 case Intrinsic::loongarch_lsx_vslei_b:
5000 case Intrinsic::loongarch_lsx_vslei_h:
5001 case Intrinsic::loongarch_lsx_vslei_w:
5002 case Intrinsic::loongarch_lsx_vslei_d:
5003 case Intrinsic::loongarch_lsx_vslti_b:
5004 case Intrinsic::loongarch_lsx_vslti_h:
5005 case Intrinsic::loongarch_lsx_vslti_w:
5006 case Intrinsic::loongarch_lsx_vslti_d:
5007 case Intrinsic::loongarch_lasx_xvseqi_b:
5008 case Intrinsic::loongarch_lasx_xvseqi_h:
5009 case Intrinsic::loongarch_lasx_xvseqi_w:
5010 case Intrinsic::loongarch_lasx_xvseqi_d:
5011 case Intrinsic::loongarch_lasx_xvslei_b:
5012 case Intrinsic::loongarch_lasx_xvslei_h:
5013 case Intrinsic::loongarch_lasx_xvslei_w:
5014 case Intrinsic::loongarch_lasx_xvslei_d:
5015 case Intrinsic::loongarch_lasx_xvslti_b:
5016 case Intrinsic::loongarch_lasx_xvslti_h:
5017 case Intrinsic::loongarch_lasx_xvslti_w:
5018 case Intrinsic::loongarch_lasx_xvslti_d:
5020 case Intrinsic::loongarch_lsx_vsrlni_h_w:
5021 case Intrinsic::loongarch_lsx_vsrani_h_w:
5022 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
5023 case Intrinsic::loongarch_lsx_vsrarni_h_w:
5024 case Intrinsic::loongarch_lsx_vssrlni_h_w:
5025 case Intrinsic::loongarch_lsx_vssrani_h_w:
5026 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
5027 case Intrinsic::loongarch_lsx_vssrani_hu_w:
5028 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
5029 case Intrinsic::loongarch_lsx_vssrarni_h_w:
5030 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
5031 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
5032 case Intrinsic::loongarch_lsx_vfrstpi_b:
5033 case Intrinsic::loongarch_lsx_vfrstpi_h:
5034 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
5035 case Intrinsic::loongarch_lasx_xvsrani_h_w:
5036 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
5037 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
5038 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
5039 case Intrinsic::loongarch_lasx_xvssrani_h_w:
5040 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
5041 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
5042 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
5043 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
5044 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
5045 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
5046 case Intrinsic::loongarch_lasx_xvfrstpi_b:
5047 case Intrinsic::loongarch_lasx_xvfrstpi_h:
5049 case Intrinsic::loongarch_lsx_vsat_d:
5050 case Intrinsic::loongarch_lsx_vsat_du:
5051 case Intrinsic::loongarch_lsx_vrotri_d:
5052 case Intrinsic::loongarch_lsx_vsrlri_d:
5053 case Intrinsic::loongarch_lsx_vsrari_d:
5054 case Intrinsic::loongarch_lasx_xvsat_d:
5055 case Intrinsic::loongarch_lasx_xvsat_du:
5056 case Intrinsic::loongarch_lasx_xvrotri_d:
5057 case Intrinsic::loongarch_lasx_xvsrlri_d:
5058 case Intrinsic::loongarch_lasx_xvsrari_d:
5060 case Intrinsic::loongarch_lsx_vsrlni_w_d:
5061 case Intrinsic::loongarch_lsx_vsrani_w_d:
5062 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
5063 case Intrinsic::loongarch_lsx_vsrarni_w_d:
5064 case Intrinsic::loongarch_lsx_vssrlni_w_d:
5065 case Intrinsic::loongarch_lsx_vssrani_w_d:
5066 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
5067 case Intrinsic::loongarch_lsx_vssrani_wu_d:
5068 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
5069 case Intrinsic::loongarch_lsx_vssrarni_w_d:
5070 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
5071 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
5072 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
5073 case Intrinsic::loongarch_lasx_xvsrani_w_d:
5074 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
5075 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
5076 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
5077 case Intrinsic::loongarch_lasx_xvssrani_w_d:
5078 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
5079 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
5080 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
5081 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
5082 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
5083 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
5085 case Intrinsic::loongarch_lsx_vsrlni_d_q:
5086 case Intrinsic::loongarch_lsx_vsrani_d_q:
5087 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
5088 case Intrinsic::loongarch_lsx_vsrarni_d_q:
5089 case Intrinsic::loongarch_lsx_vssrlni_d_q:
5090 case Intrinsic::loongarch_lsx_vssrani_d_q:
5091 case Intrinsic::loongarch_lsx_vssrlni_du_q:
5092 case Intrinsic::loongarch_lsx_vssrani_du_q:
5093 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
5094 case Intrinsic::loongarch_lsx_vssrarni_d_q:
5095 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
5096 case Intrinsic::loongarch_lsx_vssrarni_du_q:
5097 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
5098 case Intrinsic::loongarch_lasx_xvsrani_d_q:
5099 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
5100 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
5101 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
5102 case Intrinsic::loongarch_lasx_xvssrani_d_q:
5103 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
5104 case Intrinsic::loongarch_lasx_xvssrani_du_q:
5105 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
5106 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
5107 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
5108 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
5110 case Intrinsic::loongarch_lsx_vnori_b:
5111 case Intrinsic::loongarch_lsx_vshuf4i_b:
5112 case Intrinsic::loongarch_lsx_vshuf4i_h:
5113 case Intrinsic::loongarch_lsx_vshuf4i_w:
5114 case Intrinsic::loongarch_lasx_xvnori_b:
5115 case Intrinsic::loongarch_lasx_xvshuf4i_b:
5116 case Intrinsic::loongarch_lasx_xvshuf4i_h:
5117 case Intrinsic::loongarch_lasx_xvshuf4i_w:
5118 case Intrinsic::loongarch_lasx_xvpermi_d:
5120 case Intrinsic::loongarch_lsx_vshuf4i_d:
5121 case Intrinsic::loongarch_lsx_vpermi_w:
5122 case Intrinsic::loongarch_lsx_vbitseli_b:
5123 case Intrinsic::loongarch_lsx_vextrins_b:
5124 case Intrinsic::loongarch_lsx_vextrins_h:
5125 case Intrinsic::loongarch_lsx_vextrins_w:
5126 case Intrinsic::loongarch_lsx_vextrins_d:
5127 case Intrinsic::loongarch_lasx_xvshuf4i_d:
5128 case Intrinsic::loongarch_lasx_xvpermi_w:
5129 case Intrinsic::loongarch_lasx_xvpermi_q:
5130 case Intrinsic::loongarch_lasx_xvbitseli_b:
5131 case Intrinsic::loongarch_lasx_xvextrins_b:
5132 case Intrinsic::loongarch_lasx_xvextrins_h:
5133 case Intrinsic::loongarch_lasx_xvextrins_w:
5134 case Intrinsic::loongarch_lasx_xvextrins_d:
5136 case Intrinsic::loongarch_lsx_vrepli_b:
5137 case Intrinsic::loongarch_lsx_vrepli_h:
5138 case Intrinsic::loongarch_lsx_vrepli_w:
5139 case Intrinsic::loongarch_lsx_vrepli_d:
5140 case Intrinsic::loongarch_lasx_xvrepli_b:
5141 case Intrinsic::loongarch_lasx_xvrepli_h:
5142 case Intrinsic::loongarch_lasx_xvrepli_w:
5143 case Intrinsic::loongarch_lasx_xvrepli_d:
5145 case Intrinsic::loongarch_lsx_vldi:
5146 case Intrinsic::loongarch_lasx_xvldi:
5162LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
5165 MVT GRLenVT = Subtarget.getGRLenVT();
5166 EVT VT =
Op.getValueType();
5168 const StringRef ErrorMsgOOR =
"argument out of range";
5169 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5170 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5172 switch (
Op.getConstantOperandVal(1)) {
5175 case Intrinsic::loongarch_crc_w_b_w:
5176 case Intrinsic::loongarch_crc_w_h_w:
5177 case Intrinsic::loongarch_crc_w_w_w:
5178 case Intrinsic::loongarch_crc_w_d_w:
5179 case Intrinsic::loongarch_crcc_w_b_w:
5180 case Intrinsic::loongarch_crcc_w_h_w:
5181 case Intrinsic::loongarch_crcc_w_w_w:
5182 case Intrinsic::loongarch_crcc_w_d_w:
5184 case Intrinsic::loongarch_csrrd_w:
5185 case Intrinsic::loongarch_csrrd_d: {
5186 unsigned Imm =
Op.getConstantOperandVal(2);
5189 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5192 case Intrinsic::loongarch_csrwr_w:
5193 case Intrinsic::loongarch_csrwr_d: {
5194 unsigned Imm =
Op.getConstantOperandVal(3);
5197 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5198 {Chain,
Op.getOperand(2),
5201 case Intrinsic::loongarch_csrxchg_w:
5202 case Intrinsic::loongarch_csrxchg_d: {
5203 unsigned Imm =
Op.getConstantOperandVal(4);
5206 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5207 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5210 case Intrinsic::loongarch_iocsrrd_d: {
5212 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5215#define IOCSRRD_CASE(NAME, NODE) \
5216 case Intrinsic::loongarch_##NAME: { \
5217 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5218 {Chain, Op.getOperand(2)}); \
5224 case Intrinsic::loongarch_cpucfg: {
5225 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5226 {Chain,
Op.getOperand(2)});
5228 case Intrinsic::loongarch_lddir_d: {
5229 unsigned Imm =
Op.getConstantOperandVal(3);
5234 case Intrinsic::loongarch_movfcsr2gr: {
5235 if (!Subtarget.hasBasicF())
5237 unsigned Imm =
Op.getConstantOperandVal(2);
5240 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5243 case Intrinsic::loongarch_lsx_vld:
5244 case Intrinsic::loongarch_lsx_vldrepl_b:
5245 case Intrinsic::loongarch_lasx_xvld:
5246 case Intrinsic::loongarch_lasx_xvldrepl_b:
5250 case Intrinsic::loongarch_lsx_vldrepl_h:
5251 case Intrinsic::loongarch_lasx_xvldrepl_h:
5255 Op,
"argument out of range or not a multiple of 2", DAG)
5257 case Intrinsic::loongarch_lsx_vldrepl_w:
5258 case Intrinsic::loongarch_lasx_xvldrepl_w:
5262 Op,
"argument out of range or not a multiple of 4", DAG)
5264 case Intrinsic::loongarch_lsx_vldrepl_d:
5265 case Intrinsic::loongarch_lasx_xvldrepl_d:
5269 Op,
"argument out of range or not a multiple of 8", DAG)
5280 return Op.getOperand(0);
5286 MVT GRLenVT = Subtarget.getGRLenVT();
5288 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5290 const StringRef ErrorMsgOOR =
"argument out of range";
5291 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5292 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5293 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5295 switch (IntrinsicEnum) {
5299 case Intrinsic::loongarch_cacop_d:
5300 case Intrinsic::loongarch_cacop_w: {
5301 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5303 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5312 case Intrinsic::loongarch_dbar: {
5319 case Intrinsic::loongarch_ibar: {
5326 case Intrinsic::loongarch_break: {
5333 case Intrinsic::loongarch_movgr2fcsr: {
5334 if (!Subtarget.hasBasicF())
5344 case Intrinsic::loongarch_syscall: {
5351#define IOCSRWR_CASE(NAME, NODE) \
5352 case Intrinsic::loongarch_##NAME: { \
5353 SDValue Op3 = Op.getOperand(3); \
5354 return Subtarget.is64Bit() \
5355 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5356 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5357 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5358 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5365 case Intrinsic::loongarch_iocsrwr_d: {
5366 return !Subtarget.is64Bit()
5373#define ASRT_LE_GT_CASE(NAME) \
5374 case Intrinsic::loongarch_##NAME: { \
5375 return !Subtarget.is64Bit() \
5376 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5381#undef ASRT_LE_GT_CASE
5382 case Intrinsic::loongarch_ldpte_d: {
5383 unsigned Imm =
Op.getConstantOperandVal(3);
5384 return !Subtarget.is64Bit()
5389 case Intrinsic::loongarch_lsx_vst:
5390 case Intrinsic::loongarch_lasx_xvst:
5394 case Intrinsic::loongarch_lasx_xvstelm_b:
5399 case Intrinsic::loongarch_lsx_vstelm_b:
5404 case Intrinsic::loongarch_lasx_xvstelm_h:
5409 Op,
"argument out of range or not a multiple of 2", DAG)
5411 case Intrinsic::loongarch_lsx_vstelm_h:
5416 Op,
"argument out of range or not a multiple of 2", DAG)
5418 case Intrinsic::loongarch_lasx_xvstelm_w:
5423 Op,
"argument out of range or not a multiple of 4", DAG)
5425 case Intrinsic::loongarch_lsx_vstelm_w:
5430 Op,
"argument out of range or not a multiple of 4", DAG)
5432 case Intrinsic::loongarch_lasx_xvstelm_d:
5437 Op,
"argument out of range or not a multiple of 8", DAG)
5439 case Intrinsic::loongarch_lsx_vstelm_d:
5444 Op,
"argument out of range or not a multiple of 8", DAG)
5455 EVT VT =
Lo.getValueType();
5496 EVT VT =
Lo.getValueType();
5550 return LoongArchISD::DIV_W;
5552 return LoongArchISD::DIV_WU;
5554 return LoongArchISD::MOD_W;
5556 return LoongArchISD::MOD_WU;
5558 return LoongArchISD::SLL_W;
5560 return LoongArchISD::SRA_W;
5562 return LoongArchISD::SRL_W;
5565 return LoongArchISD::ROTR_W;
5567 return LoongArchISD::CTZ_W;
5569 return LoongArchISD::CLZ_W;
5588 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5589 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5593 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5599 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5626 StringRef ErrorMsg,
bool WithChain =
true) {
5631 Results.push_back(
N->getOperand(0));
5634template <
unsigned N>
5639 const StringRef ErrorMsgOOR =
"argument out of range";
5640 unsigned Imm =
Node->getConstantOperandVal(2);
5674 switch (
N->getConstantOperandVal(0)) {
5677 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5679 LoongArchISD::VPICK_SEXT_ELT);
5681 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5682 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5684 LoongArchISD::VPICK_SEXT_ELT);
5686 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5688 LoongArchISD::VPICK_SEXT_ELT);
5690 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5692 LoongArchISD::VPICK_ZEXT_ELT);
5694 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5695 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5697 LoongArchISD::VPICK_ZEXT_ELT);
5699 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5701 LoongArchISD::VPICK_ZEXT_ELT);
5703 case Intrinsic::loongarch_lsx_bz_b:
5704 case Intrinsic::loongarch_lsx_bz_h:
5705 case Intrinsic::loongarch_lsx_bz_w:
5706 case Intrinsic::loongarch_lsx_bz_d:
5707 case Intrinsic::loongarch_lasx_xbz_b:
5708 case Intrinsic::loongarch_lasx_xbz_h:
5709 case Intrinsic::loongarch_lasx_xbz_w:
5710 case Intrinsic::loongarch_lasx_xbz_d:
5712 LoongArchISD::VALL_ZERO);
5714 case Intrinsic::loongarch_lsx_bz_v:
5715 case Intrinsic::loongarch_lasx_xbz_v:
5717 LoongArchISD::VANY_ZERO);
5719 case Intrinsic::loongarch_lsx_bnz_b:
5720 case Intrinsic::loongarch_lsx_bnz_h:
5721 case Intrinsic::loongarch_lsx_bnz_w:
5722 case Intrinsic::loongarch_lsx_bnz_d:
5723 case Intrinsic::loongarch_lasx_xbnz_b:
5724 case Intrinsic::loongarch_lasx_xbnz_h:
5725 case Intrinsic::loongarch_lasx_xbnz_w:
5726 case Intrinsic::loongarch_lasx_xbnz_d:
5728 LoongArchISD::VALL_NONZERO);
5730 case Intrinsic::loongarch_lsx_bnz_v:
5731 case Intrinsic::loongarch_lasx_xbnz_v:
5733 LoongArchISD::VANY_NONZERO);
5741 assert(
N->getValueType(0) == MVT::i128 &&
5742 "AtomicCmpSwap on types less than 128 should be legal");
5746 switch (
MemOp->getMergedOrdering()) {
5750 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5754 Opcode = LoongArch::PseudoCmpXchg128;
5761 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5762 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5763 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5764 NewVal.first, NewVal.second,
N->getOperand(0)};
5767 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5778 EVT VT =
N->getValueType(0);
5779 switch (
N->getOpcode()) {
5784 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5785 "Unexpected custom legalisation");
5792 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5793 "Unexpected custom legalisation");
5795 Subtarget.hasDiv32() && VT == MVT::i32
5802 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5803 "Unexpected custom legalisation");
5811 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5812 "Unexpected custom legalisation");
5819 MVT VT =
N->getSimpleValueType(0);
5820 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5821 "Unexpected custom legalisation");
5823 "Unexpected type action!");
5828 Ld->getPointerInfo(), Ld->getBaseAlign(),
5829 Ld->getMemOperand()->getFlags());
5840 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5841 "Unexpected custom legalisation");
5848 if (Src.getValueType() == MVT::f16)
5859 EVT OpVT = Src.getValueType();
5863 std::tie(Result, Chain) =
5870 EVT SrcVT = Src.getValueType();
5871 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5872 Subtarget.hasBasicF()) {
5874 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5876 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5878 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5886 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5887 "Unexpected custom legalisation");
5890 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5895 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5896 "Unexpected custom legalisation");
5902 if (OpVT == MVT::v2f64) {
5912 assert((VT == MVT::i16 || VT == MVT::i32) &&
5913 "Unexpected custom legalization");
5914 MVT GRLenVT = Subtarget.getGRLenVT();
5921 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5926 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5934 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5935 "Unexpected custom legalization");
5936 MVT GRLenVT = Subtarget.getGRLenVT();
5943 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5946 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5954 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5955 "Unexpected custom legalisation");
5962 MVT GRLenVT = Subtarget.getGRLenVT();
5963 const StringRef ErrorMsgOOR =
"argument out of range";
5964 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5965 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5967 switch (
N->getConstantOperandVal(1)) {
5970 case Intrinsic::loongarch_movfcsr2gr: {
5971 if (!Subtarget.hasBasicF()) {
5981 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5988#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5989 case Intrinsic::loongarch_##NAME: { \
5990 SDValue NODE = DAG.getNode( \
5991 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5992 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5993 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5994 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5995 Results.push_back(NODE.getValue(1)); \
6004#undef CRC_CASE_EXT_BINARYOP
6006#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
6007 case Intrinsic::loongarch_##NAME: { \
6008 SDValue NODE = DAG.getNode( \
6009 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6011 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
6012 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
6013 Results.push_back(NODE.getValue(1)); \
6018#undef CRC_CASE_EXT_UNARYOP
6019#define CSR_CASE(ID) \
6020 case Intrinsic::loongarch_##ID: { \
6021 if (!Subtarget.is64Bit()) \
6022 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
6030 case Intrinsic::loongarch_csrrd_w: {
6037 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
6044 case Intrinsic::loongarch_csrwr_w: {
6045 unsigned Imm =
N->getConstantOperandVal(3);
6051 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
6059 case Intrinsic::loongarch_csrxchg_w: {
6060 unsigned Imm =
N->getConstantOperandVal(4);
6066 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
6075#define IOCSRRD_CASE(NAME, NODE) \
6076 case Intrinsic::loongarch_##NAME: { \
6077 SDValue IOCSRRDResults = \
6078 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6079 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
6080 Results.push_back( \
6081 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
6082 Results.push_back(IOCSRRDResults.getValue(1)); \
6089 case Intrinsic::loongarch_cpucfg: {
6091 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
6098 case Intrinsic::loongarch_lddir_d: {
6099 if (!Subtarget.is64Bit()) {
6109 if (Subtarget.is64Bit())
6111 "On LA64, only 64-bit registers can be read.");
6114 "On LA32, only 32-bit registers can be read.");
6116 Results.push_back(
N->getOperand(0));
6127 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
6140 MVT VT =
N->getSimpleValueType(0);
6146 EVT InVT = In.getValueType();
6156 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6161 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
6164 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6173 for (
unsigned I = 0;
I < MinElts; ++
I)
6174 TruncMask[
I] = Scale *
I;
6176 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
6177 MVT SVT = In.getSimpleValueType().getScalarType();
6183 "Illegal vector type in truncation");
6195 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
6198 EVT DstVT =
N->getValueType(0);
6200 MVT SrcVT = Src.getSimpleValueType();
6218 unsigned WidenSrcElts = 128 / SrcEltBits;
6225 unsigned FirstStageEltBits = 128 / NumElts;
6229 SrcVT = FirstStageVT;
6230 SrcEltBits = FirstStageEltBits;
6238 while (SrcEltBits < DstEltBits) {
6239 unsigned NextEltBits = SrcEltBits * 2;
6242 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6261 Blocks = std::move(NextBlocks);
6262 SrcVT = NextBlockVT;
6263 SrcEltBits = NextEltBits;
6280 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6282 MVT VT =
N->getSimpleValueType(0);
6301 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6305 unsigned MinSizeInBits) {
6313 unsigned SplatBitSize;
6316 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6317 HasAnyUndefs, MinSizeInBits,
6329 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6340 unsigned EltIdx = IdxC->getZExtValue();
6342 Start = (int)EltIdx - (
int)(i * 2);
6343 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6349 else if (Src != CurSrc)
6353 if (!Src || Start < 0)
6366 unsigned Opc =
N->getOpcode();
6369 EVT VT =
N->getValueType(0);
6376 unsigned ExtOpc =
LHS.getOpcode();
6384 if (ExtOpc !=
RHS.getOpcode())
6387 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6390 unsigned OddIdx, EvenIdx;
6394 if (!LHSVec || !RHSVec)
6396 if (OddIdx != 1 || EvenIdx != 0)
6406 if (!
TLI.isTypeLegal(VT) || !
TLI.isTypeLegal(SrcVT))
6419 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6421 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6423 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6435 EVT VT =
N->getValueType(0);
6501 if (
And.getOperand(0) ==
X) {
6530 if (ShiftVal != (SplatVal + 1))
6539 : LoongArchISD::VSRAR,
6549 SDValue FirstOperand =
N->getOperand(0);
6550 SDValue SecondOperand =
N->getOperand(1);
6551 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6552 EVT ValTy =
N->getValueType(0);
6555 unsigned SMIdx, SMLen;
6620 NewOperand = FirstOperand;
6623 msb = lsb + SMLen - 1;
6627 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6641 EVT DstVT =
N.getValueType();
6650 EVT SrcVT = Src.getValueType();
6658 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6669 if (NumElts % 2 != 0)
6675 for (
unsigned I = 0;
I != NumElts; ++
I) {
6690 SrcVT = Src.getValueType();
6700 }
else if (ThisSrc != Src) {
6704 unsigned Half = NumElts / 2;
6705 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6706 ExpectedIdx += isLow ? 0 : Half;
6708 if (CI->getZExtValue() != ExpectedIdx)
6720 EVT VT =
N->getValueType(0);
6727 unsigned ExtOpc =
LHS.getOpcode();
6735 if (!
LHS.hasOneUse())
6739 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6755 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6776 SDValue FirstOperand =
N->getOperand(0);
6778 EVT ValTy =
N->getValueType(0);
6781 unsigned MaskIdx, MaskLen;
6796 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6797 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6821 switch (Src.getOpcode()) {
6824 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6834 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6847 switch (Src.getOpcode()) {
6857 Src.getOpcode(),
DL, SExtVT,
6863 DL, SExtVT, Src.getOperand(0),
6875 EVT VT =
N->getValueType(0);
6877 EVT SrcVT = Src.getValueType();
6879 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6884 EVT CmpVT = Src.getOperand(0).getValueType();
6896 switch (Src.getOperandCondCode(2)) {
6902 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6907 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6912 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6917 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6919 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6924 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6926 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6931 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6948 EVT VT =
N->getValueType(0);
6950 EVT SrcVT = Src.getValueType();
6967 bool UseLASX =
false;
6968 bool PropagateSExt =
false;
6970 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6971 EVT CmpVT = Src.getOperand(0).getValueType();
6980 SExtVT = MVT::v2i64;
6983 SExtVT = MVT::v4i32;
6985 SExtVT = MVT::v4i64;
6987 PropagateSExt =
true;
6991 SExtVT = MVT::v8i16;
6993 SExtVT = MVT::v8i32;
6995 PropagateSExt =
true;
6999 SExtVT = MVT::v16i8;
7001 SExtVT = MVT::v16i16;
7003 PropagateSExt =
true;
7007 SExtVT = MVT::v32i8;
7016 if (Src.getSimpleValueType() == MVT::v32i8) {
7024 }
else if (UseLASX) {
7030 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
7043 EVT ValTy =
N->getValueType(0);
7044 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
7048 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
7050 bool SwapAndRetried =
false;
7059 if (ValBits != 32 && ValBits != 64)
7074 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
7077 (MaskIdx0 + MaskLen0 <= ValBits)) {
7098 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
7099 (MaskIdx0 + MaskLen0 <= ValBits)) {
7116 (MaskIdx0 + MaskLen0 <= 64) &&
7124 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7125 : (MaskIdx0 + MaskLen0 - 1),
7141 (MaskIdx0 + MaskLen0 <= ValBits)) {
7164 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7165 : (MaskIdx0 + MaskLen0 - 1),
7180 unsigned MaskIdx, MaskLen;
7181 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
7190 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7208 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7214 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7222 if (!SwapAndRetried) {
7224 SwapAndRetried =
true;
7228 SwapAndRetried =
false;
7245 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7254 if (!SwapAndRetried) {
7256 SwapAndRetried =
true;
7266 switch (
V.getNode()->getOpcode()) {
7278 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7286 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7316 unsigned MskOpc =
LHS.getOpcode();
7317 if (MskOpc != LoongArchISD::VMSKLTZ && MskOpc != LoongArchISD::XVMSKLTZ)
7320 if (!
LHS.hasOneUse())
7324 EVT SrcVT = Src.getValueType();
7331 : LoongArchISD::VALLZERO,
7399 if (
N->getValueType(0) ==
Subtarget.getGRLenVT())
7404 SDNode *AndNode =
N->getOperand(0).getNode();
7412 SDValue CmpInputValue =
N->getOperand(1);
7421 if (!CN || !CN->
isZero())
7423 AndInputValue1 = AndInputValue1.
getOperand(0);
7427 if (AndInputValue2 != CmpInputValue)
7460 TruncInputValue1, TruncInputValue2);
7502static std::tuple<unsigned, SDValue, EVT>
7506 unsigned Opc = Inner.getOpcode();
7511 if (Inner.getOperand(0) ==
X)
7512 return {
Opc, Inner.getOperand(1), ExtVT};
7513 if (Inner.getOperand(1) ==
X)
7514 return {
Opc, Inner.getOperand(0), ExtVT};
7518 if (Inner.getOperand(0) ==
X)
7519 return {
Opc, Inner.getOperand(1), ExtVT};
7541 EVT VT =
N->getValueType(0);
7553 bool BinIsTrueArm) ->
SDValue {
7561 if (Delta.getNode() ==
N)
7583 if (
SDValue R = TryFold(TrueV, FalseV,
true))
7585 if (
SDValue R = TryFold(FalseV, TrueV,
false))
7599 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7602 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7627 LHS.getOperand(0).getValueType() ==
Subtarget.getGRLenVT()) {
7631 CCVal =
LHS.getOperandCondCode(2);
7655 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7682 unsigned Sht =
LHS.getConstantOperandVal(1);
7686 if ((EleBits + Sht) ==
Subtarget.getGRLen()) {
7696 EVT VT =
LHS.getValueType();
7721 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7722 N->getOperand(0),
V,
7727 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7728 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
7744 EVT VT =
N->getValueType(0);
7747 if (TrueV == FalseV)
7778 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7779 {LHS, RHS, CC, TrueV, FalseV});
7784template <
unsigned N>
7788 bool IsSigned =
false) {
7792 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7793 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7795 ": argument out of range.");
7801template <
unsigned N>
7805 EVT ResTy =
Node->getValueType(0);
7809 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7810 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7812 ": argument out of range.");
7817 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7823 EVT ResTy =
Node->getValueType(0);
7831 EVT ResTy =
Node->getValueType(0);
7840template <
unsigned N>
7843 EVT ResTy =
Node->getValueType(0);
7848 ": argument out of range.");
7858template <
unsigned N>
7861 EVT ResTy =
Node->getValueType(0);
7866 ": argument out of range.");
7875template <
unsigned N>
7878 EVT ResTy =
Node->getValueType(0);
7883 ": argument out of range.");
7892template <
unsigned W>
7895 unsigned Imm =
N->getConstantOperandVal(2);
7897 const StringRef ErrorMsg =
"argument out of range";
7899 return DAG.
getUNDEF(
N->getValueType(0));
7905 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7913 switch (
N->getConstantOperandVal(0)) {
7916 case Intrinsic::loongarch_lsx_vadd_b:
7917 case Intrinsic::loongarch_lsx_vadd_h:
7918 case Intrinsic::loongarch_lsx_vadd_w:
7919 case Intrinsic::loongarch_lsx_vadd_d:
7920 case Intrinsic::loongarch_lasx_xvadd_b:
7921 case Intrinsic::loongarch_lasx_xvadd_h:
7922 case Intrinsic::loongarch_lasx_xvadd_w:
7923 case Intrinsic::loongarch_lasx_xvadd_d:
7926 case Intrinsic::loongarch_lsx_vaddi_bu:
7927 case Intrinsic::loongarch_lsx_vaddi_hu:
7928 case Intrinsic::loongarch_lsx_vaddi_wu:
7929 case Intrinsic::loongarch_lsx_vaddi_du:
7930 case Intrinsic::loongarch_lasx_xvaddi_bu:
7931 case Intrinsic::loongarch_lasx_xvaddi_hu:
7932 case Intrinsic::loongarch_lasx_xvaddi_wu:
7933 case Intrinsic::loongarch_lasx_xvaddi_du:
7936 case Intrinsic::loongarch_lsx_vsub_b:
7937 case Intrinsic::loongarch_lsx_vsub_h:
7938 case Intrinsic::loongarch_lsx_vsub_w:
7939 case Intrinsic::loongarch_lsx_vsub_d:
7940 case Intrinsic::loongarch_lasx_xvsub_b:
7941 case Intrinsic::loongarch_lasx_xvsub_h:
7942 case Intrinsic::loongarch_lasx_xvsub_w:
7943 case Intrinsic::loongarch_lasx_xvsub_d:
7946 case Intrinsic::loongarch_lsx_vsubi_bu:
7947 case Intrinsic::loongarch_lsx_vsubi_hu:
7948 case Intrinsic::loongarch_lsx_vsubi_wu:
7949 case Intrinsic::loongarch_lsx_vsubi_du:
7950 case Intrinsic::loongarch_lasx_xvsubi_bu:
7951 case Intrinsic::loongarch_lasx_xvsubi_hu:
7952 case Intrinsic::loongarch_lasx_xvsubi_wu:
7953 case Intrinsic::loongarch_lasx_xvsubi_du:
7956 case Intrinsic::loongarch_lsx_vneg_b:
7957 case Intrinsic::loongarch_lsx_vneg_h:
7958 case Intrinsic::loongarch_lsx_vneg_w:
7959 case Intrinsic::loongarch_lsx_vneg_d:
7960 case Intrinsic::loongarch_lasx_xvneg_b:
7961 case Intrinsic::loongarch_lasx_xvneg_h:
7962 case Intrinsic::loongarch_lasx_xvneg_w:
7963 case Intrinsic::loongarch_lasx_xvneg_d:
7967 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7969 SDLoc(
N),
N->getValueType(0)),
7971 case Intrinsic::loongarch_lsx_vmax_b:
7972 case Intrinsic::loongarch_lsx_vmax_h:
7973 case Intrinsic::loongarch_lsx_vmax_w:
7974 case Intrinsic::loongarch_lsx_vmax_d:
7975 case Intrinsic::loongarch_lasx_xvmax_b:
7976 case Intrinsic::loongarch_lasx_xvmax_h:
7977 case Intrinsic::loongarch_lasx_xvmax_w:
7978 case Intrinsic::loongarch_lasx_xvmax_d:
7981 case Intrinsic::loongarch_lsx_vmax_bu:
7982 case Intrinsic::loongarch_lsx_vmax_hu:
7983 case Intrinsic::loongarch_lsx_vmax_wu:
7984 case Intrinsic::loongarch_lsx_vmax_du:
7985 case Intrinsic::loongarch_lasx_xvmax_bu:
7986 case Intrinsic::loongarch_lasx_xvmax_hu:
7987 case Intrinsic::loongarch_lasx_xvmax_wu:
7988 case Intrinsic::loongarch_lasx_xvmax_du:
7991 case Intrinsic::loongarch_lsx_vmaxi_b:
7992 case Intrinsic::loongarch_lsx_vmaxi_h:
7993 case Intrinsic::loongarch_lsx_vmaxi_w:
7994 case Intrinsic::loongarch_lsx_vmaxi_d:
7995 case Intrinsic::loongarch_lasx_xvmaxi_b:
7996 case Intrinsic::loongarch_lasx_xvmaxi_h:
7997 case Intrinsic::loongarch_lasx_xvmaxi_w:
7998 case Intrinsic::loongarch_lasx_xvmaxi_d:
8001 case Intrinsic::loongarch_lsx_vmaxi_bu:
8002 case Intrinsic::loongarch_lsx_vmaxi_hu:
8003 case Intrinsic::loongarch_lsx_vmaxi_wu:
8004 case Intrinsic::loongarch_lsx_vmaxi_du:
8005 case Intrinsic::loongarch_lasx_xvmaxi_bu:
8006 case Intrinsic::loongarch_lasx_xvmaxi_hu:
8007 case Intrinsic::loongarch_lasx_xvmaxi_wu:
8008 case Intrinsic::loongarch_lasx_xvmaxi_du:
8011 case Intrinsic::loongarch_lsx_vmin_b:
8012 case Intrinsic::loongarch_lsx_vmin_h:
8013 case Intrinsic::loongarch_lsx_vmin_w:
8014 case Intrinsic::loongarch_lsx_vmin_d:
8015 case Intrinsic::loongarch_lasx_xvmin_b:
8016 case Intrinsic::loongarch_lasx_xvmin_h:
8017 case Intrinsic::loongarch_lasx_xvmin_w:
8018 case Intrinsic::loongarch_lasx_xvmin_d:
8021 case Intrinsic::loongarch_lsx_vmin_bu:
8022 case Intrinsic::loongarch_lsx_vmin_hu:
8023 case Intrinsic::loongarch_lsx_vmin_wu:
8024 case Intrinsic::loongarch_lsx_vmin_du:
8025 case Intrinsic::loongarch_lasx_xvmin_bu:
8026 case Intrinsic::loongarch_lasx_xvmin_hu:
8027 case Intrinsic::loongarch_lasx_xvmin_wu:
8028 case Intrinsic::loongarch_lasx_xvmin_du:
8031 case Intrinsic::loongarch_lsx_vmini_b:
8032 case Intrinsic::loongarch_lsx_vmini_h:
8033 case Intrinsic::loongarch_lsx_vmini_w:
8034 case Intrinsic::loongarch_lsx_vmini_d:
8035 case Intrinsic::loongarch_lasx_xvmini_b:
8036 case Intrinsic::loongarch_lasx_xvmini_h:
8037 case Intrinsic::loongarch_lasx_xvmini_w:
8038 case Intrinsic::loongarch_lasx_xvmini_d:
8041 case Intrinsic::loongarch_lsx_vmini_bu:
8042 case Intrinsic::loongarch_lsx_vmini_hu:
8043 case Intrinsic::loongarch_lsx_vmini_wu:
8044 case Intrinsic::loongarch_lsx_vmini_du:
8045 case Intrinsic::loongarch_lasx_xvmini_bu:
8046 case Intrinsic::loongarch_lasx_xvmini_hu:
8047 case Intrinsic::loongarch_lasx_xvmini_wu:
8048 case Intrinsic::loongarch_lasx_xvmini_du:
8051 case Intrinsic::loongarch_lsx_vmul_b:
8052 case Intrinsic::loongarch_lsx_vmul_h:
8053 case Intrinsic::loongarch_lsx_vmul_w:
8054 case Intrinsic::loongarch_lsx_vmul_d:
8055 case Intrinsic::loongarch_lasx_xvmul_b:
8056 case Intrinsic::loongarch_lasx_xvmul_h:
8057 case Intrinsic::loongarch_lasx_xvmul_w:
8058 case Intrinsic::loongarch_lasx_xvmul_d:
8061 case Intrinsic::loongarch_lsx_vmadd_b:
8062 case Intrinsic::loongarch_lsx_vmadd_h:
8063 case Intrinsic::loongarch_lsx_vmadd_w:
8064 case Intrinsic::loongarch_lsx_vmadd_d:
8065 case Intrinsic::loongarch_lasx_xvmadd_b:
8066 case Intrinsic::loongarch_lasx_xvmadd_h:
8067 case Intrinsic::loongarch_lasx_xvmadd_w:
8068 case Intrinsic::loongarch_lasx_xvmadd_d: {
8069 EVT ResTy =
N->getValueType(0);
8074 case Intrinsic::loongarch_lsx_vmsub_b:
8075 case Intrinsic::loongarch_lsx_vmsub_h:
8076 case Intrinsic::loongarch_lsx_vmsub_w:
8077 case Intrinsic::loongarch_lsx_vmsub_d:
8078 case Intrinsic::loongarch_lasx_xvmsub_b:
8079 case Intrinsic::loongarch_lasx_xvmsub_h:
8080 case Intrinsic::loongarch_lasx_xvmsub_w:
8081 case Intrinsic::loongarch_lasx_xvmsub_d: {
8082 EVT ResTy =
N->getValueType(0);
8087 case Intrinsic::loongarch_lsx_vdiv_b:
8088 case Intrinsic::loongarch_lsx_vdiv_h:
8089 case Intrinsic::loongarch_lsx_vdiv_w:
8090 case Intrinsic::loongarch_lsx_vdiv_d:
8091 case Intrinsic::loongarch_lasx_xvdiv_b:
8092 case Intrinsic::loongarch_lasx_xvdiv_h:
8093 case Intrinsic::loongarch_lasx_xvdiv_w:
8094 case Intrinsic::loongarch_lasx_xvdiv_d:
8097 case Intrinsic::loongarch_lsx_vdiv_bu:
8098 case Intrinsic::loongarch_lsx_vdiv_hu:
8099 case Intrinsic::loongarch_lsx_vdiv_wu:
8100 case Intrinsic::loongarch_lsx_vdiv_du:
8101 case Intrinsic::loongarch_lasx_xvdiv_bu:
8102 case Intrinsic::loongarch_lasx_xvdiv_hu:
8103 case Intrinsic::loongarch_lasx_xvdiv_wu:
8104 case Intrinsic::loongarch_lasx_xvdiv_du:
8107 case Intrinsic::loongarch_lsx_vmod_b:
8108 case Intrinsic::loongarch_lsx_vmod_h:
8109 case Intrinsic::loongarch_lsx_vmod_w:
8110 case Intrinsic::loongarch_lsx_vmod_d:
8111 case Intrinsic::loongarch_lasx_xvmod_b:
8112 case Intrinsic::loongarch_lasx_xvmod_h:
8113 case Intrinsic::loongarch_lasx_xvmod_w:
8114 case Intrinsic::loongarch_lasx_xvmod_d:
8117 case Intrinsic::loongarch_lsx_vmod_bu:
8118 case Intrinsic::loongarch_lsx_vmod_hu:
8119 case Intrinsic::loongarch_lsx_vmod_wu:
8120 case Intrinsic::loongarch_lsx_vmod_du:
8121 case Intrinsic::loongarch_lasx_xvmod_bu:
8122 case Intrinsic::loongarch_lasx_xvmod_hu:
8123 case Intrinsic::loongarch_lasx_xvmod_wu:
8124 case Intrinsic::loongarch_lasx_xvmod_du:
8127 case Intrinsic::loongarch_lsx_vand_v:
8128 case Intrinsic::loongarch_lasx_xvand_v:
8131 case Intrinsic::loongarch_lsx_vor_v:
8132 case Intrinsic::loongarch_lasx_xvor_v:
8135 case Intrinsic::loongarch_lsx_vxor_v:
8136 case Intrinsic::loongarch_lasx_xvxor_v:
8139 case Intrinsic::loongarch_lsx_vnor_v:
8140 case Intrinsic::loongarch_lasx_xvnor_v: {
8145 case Intrinsic::loongarch_lsx_vandi_b:
8146 case Intrinsic::loongarch_lasx_xvandi_b:
8149 case Intrinsic::loongarch_lsx_vori_b:
8150 case Intrinsic::loongarch_lasx_xvori_b:
8153 case Intrinsic::loongarch_lsx_vxori_b:
8154 case Intrinsic::loongarch_lasx_xvxori_b:
8157 case Intrinsic::loongarch_lsx_vsll_b:
8158 case Intrinsic::loongarch_lsx_vsll_h:
8159 case Intrinsic::loongarch_lsx_vsll_w:
8160 case Intrinsic::loongarch_lsx_vsll_d:
8161 case Intrinsic::loongarch_lasx_xvsll_b:
8162 case Intrinsic::loongarch_lasx_xvsll_h:
8163 case Intrinsic::loongarch_lasx_xvsll_w:
8164 case Intrinsic::loongarch_lasx_xvsll_d:
8167 case Intrinsic::loongarch_lsx_vslli_b:
8168 case Intrinsic::loongarch_lasx_xvslli_b:
8171 case Intrinsic::loongarch_lsx_vslli_h:
8172 case Intrinsic::loongarch_lasx_xvslli_h:
8175 case Intrinsic::loongarch_lsx_vslli_w:
8176 case Intrinsic::loongarch_lasx_xvslli_w:
8179 case Intrinsic::loongarch_lsx_vslli_d:
8180 case Intrinsic::loongarch_lasx_xvslli_d:
8183 case Intrinsic::loongarch_lsx_vsrl_b:
8184 case Intrinsic::loongarch_lsx_vsrl_h:
8185 case Intrinsic::loongarch_lsx_vsrl_w:
8186 case Intrinsic::loongarch_lsx_vsrl_d:
8187 case Intrinsic::loongarch_lasx_xvsrl_b:
8188 case Intrinsic::loongarch_lasx_xvsrl_h:
8189 case Intrinsic::loongarch_lasx_xvsrl_w:
8190 case Intrinsic::loongarch_lasx_xvsrl_d:
8193 case Intrinsic::loongarch_lsx_vsrli_b:
8194 case Intrinsic::loongarch_lasx_xvsrli_b:
8197 case Intrinsic::loongarch_lsx_vsrli_h:
8198 case Intrinsic::loongarch_lasx_xvsrli_h:
8201 case Intrinsic::loongarch_lsx_vsrli_w:
8202 case Intrinsic::loongarch_lasx_xvsrli_w:
8205 case Intrinsic::loongarch_lsx_vsrli_d:
8206 case Intrinsic::loongarch_lasx_xvsrli_d:
8209 case Intrinsic::loongarch_lsx_vsra_b:
8210 case Intrinsic::loongarch_lsx_vsra_h:
8211 case Intrinsic::loongarch_lsx_vsra_w:
8212 case Intrinsic::loongarch_lsx_vsra_d:
8213 case Intrinsic::loongarch_lasx_xvsra_b:
8214 case Intrinsic::loongarch_lasx_xvsra_h:
8215 case Intrinsic::loongarch_lasx_xvsra_w:
8216 case Intrinsic::loongarch_lasx_xvsra_d:
8219 case Intrinsic::loongarch_lsx_vsrai_b:
8220 case Intrinsic::loongarch_lasx_xvsrai_b:
8223 case Intrinsic::loongarch_lsx_vsrai_h:
8224 case Intrinsic::loongarch_lasx_xvsrai_h:
8227 case Intrinsic::loongarch_lsx_vsrai_w:
8228 case Intrinsic::loongarch_lasx_xvsrai_w:
8231 case Intrinsic::loongarch_lsx_vsrai_d:
8232 case Intrinsic::loongarch_lasx_xvsrai_d:
8235 case Intrinsic::loongarch_lsx_vclz_b:
8236 case Intrinsic::loongarch_lsx_vclz_h:
8237 case Intrinsic::loongarch_lsx_vclz_w:
8238 case Intrinsic::loongarch_lsx_vclz_d:
8239 case Intrinsic::loongarch_lasx_xvclz_b:
8240 case Intrinsic::loongarch_lasx_xvclz_h:
8241 case Intrinsic::loongarch_lasx_xvclz_w:
8242 case Intrinsic::loongarch_lasx_xvclz_d:
8244 case Intrinsic::loongarch_lsx_vpcnt_b:
8245 case Intrinsic::loongarch_lsx_vpcnt_h:
8246 case Intrinsic::loongarch_lsx_vpcnt_w:
8247 case Intrinsic::loongarch_lsx_vpcnt_d:
8248 case Intrinsic::loongarch_lasx_xvpcnt_b:
8249 case Intrinsic::loongarch_lasx_xvpcnt_h:
8250 case Intrinsic::loongarch_lasx_xvpcnt_w:
8251 case Intrinsic::loongarch_lasx_xvpcnt_d:
8253 case Intrinsic::loongarch_lsx_vbitclr_b:
8254 case Intrinsic::loongarch_lsx_vbitclr_h:
8255 case Intrinsic::loongarch_lsx_vbitclr_w:
8256 case Intrinsic::loongarch_lsx_vbitclr_d:
8257 case Intrinsic::loongarch_lasx_xvbitclr_b:
8258 case Intrinsic::loongarch_lasx_xvbitclr_h:
8259 case Intrinsic::loongarch_lasx_xvbitclr_w:
8260 case Intrinsic::loongarch_lasx_xvbitclr_d:
8262 case Intrinsic::loongarch_lsx_vbitclri_b:
8263 case Intrinsic::loongarch_lasx_xvbitclri_b:
8265 case Intrinsic::loongarch_lsx_vbitclri_h:
8266 case Intrinsic::loongarch_lasx_xvbitclri_h:
8268 case Intrinsic::loongarch_lsx_vbitclri_w:
8269 case Intrinsic::loongarch_lasx_xvbitclri_w:
8271 case Intrinsic::loongarch_lsx_vbitclri_d:
8272 case Intrinsic::loongarch_lasx_xvbitclri_d:
8274 case Intrinsic::loongarch_lsx_vbitset_b:
8275 case Intrinsic::loongarch_lsx_vbitset_h:
8276 case Intrinsic::loongarch_lsx_vbitset_w:
8277 case Intrinsic::loongarch_lsx_vbitset_d:
8278 case Intrinsic::loongarch_lasx_xvbitset_b:
8279 case Intrinsic::loongarch_lasx_xvbitset_h:
8280 case Intrinsic::loongarch_lasx_xvbitset_w:
8281 case Intrinsic::loongarch_lasx_xvbitset_d: {
8282 EVT VecTy =
N->getValueType(0);
8288 case Intrinsic::loongarch_lsx_vbitseti_b:
8289 case Intrinsic::loongarch_lasx_xvbitseti_b:
8291 case Intrinsic::loongarch_lsx_vbitseti_h:
8292 case Intrinsic::loongarch_lasx_xvbitseti_h:
8294 case Intrinsic::loongarch_lsx_vbitseti_w:
8295 case Intrinsic::loongarch_lasx_xvbitseti_w:
8297 case Intrinsic::loongarch_lsx_vbitseti_d:
8298 case Intrinsic::loongarch_lasx_xvbitseti_d:
8300 case Intrinsic::loongarch_lsx_vbitrev_b:
8301 case Intrinsic::loongarch_lsx_vbitrev_h:
8302 case Intrinsic::loongarch_lsx_vbitrev_w:
8303 case Intrinsic::loongarch_lsx_vbitrev_d:
8304 case Intrinsic::loongarch_lasx_xvbitrev_b:
8305 case Intrinsic::loongarch_lasx_xvbitrev_h:
8306 case Intrinsic::loongarch_lasx_xvbitrev_w:
8307 case Intrinsic::loongarch_lasx_xvbitrev_d: {
8308 EVT VecTy =
N->getValueType(0);
8314 case Intrinsic::loongarch_lsx_vbitrevi_b:
8315 case Intrinsic::loongarch_lasx_xvbitrevi_b:
8317 case Intrinsic::loongarch_lsx_vbitrevi_h:
8318 case Intrinsic::loongarch_lasx_xvbitrevi_h:
8320 case Intrinsic::loongarch_lsx_vbitrevi_w:
8321 case Intrinsic::loongarch_lasx_xvbitrevi_w:
8323 case Intrinsic::loongarch_lsx_vbitrevi_d:
8324 case Intrinsic::loongarch_lasx_xvbitrevi_d:
8326 case Intrinsic::loongarch_lsx_vfadd_s:
8327 case Intrinsic::loongarch_lsx_vfadd_d:
8328 case Intrinsic::loongarch_lasx_xvfadd_s:
8329 case Intrinsic::loongarch_lasx_xvfadd_d:
8332 case Intrinsic::loongarch_lsx_vfsub_s:
8333 case Intrinsic::loongarch_lsx_vfsub_d:
8334 case Intrinsic::loongarch_lasx_xvfsub_s:
8335 case Intrinsic::loongarch_lasx_xvfsub_d:
8338 case Intrinsic::loongarch_lsx_vfmul_s:
8339 case Intrinsic::loongarch_lsx_vfmul_d:
8340 case Intrinsic::loongarch_lasx_xvfmul_s:
8341 case Intrinsic::loongarch_lasx_xvfmul_d:
8344 case Intrinsic::loongarch_lsx_vfdiv_s:
8345 case Intrinsic::loongarch_lsx_vfdiv_d:
8346 case Intrinsic::loongarch_lasx_xvfdiv_s:
8347 case Intrinsic::loongarch_lasx_xvfdiv_d:
8350 case Intrinsic::loongarch_lsx_vfmadd_s:
8351 case Intrinsic::loongarch_lsx_vfmadd_d:
8352 case Intrinsic::loongarch_lasx_xvfmadd_s:
8353 case Intrinsic::loongarch_lasx_xvfmadd_d:
8355 N->getOperand(2),
N->getOperand(3));
8356 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
8358 N->getOperand(1),
N->getOperand(2),
8360 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
8361 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
8363 N->getOperand(1),
N->getOperand(2),
8365 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
8366 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
8368 N->getOperand(1),
N->getOperand(2),
8370 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
8372 N->getOperand(1),
N->getOperand(2),
8374 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
8375 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
8376 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
8377 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
8378 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
8379 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
8380 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
8381 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
8382 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
8385 case Intrinsic::loongarch_lsx_vreplve_b:
8386 case Intrinsic::loongarch_lsx_vreplve_h:
8387 case Intrinsic::loongarch_lsx_vreplve_w:
8388 case Intrinsic::loongarch_lsx_vreplve_d:
8389 case Intrinsic::loongarch_lasx_xvreplve_b:
8390 case Intrinsic::loongarch_lasx_xvreplve_h:
8391 case Intrinsic::loongarch_lasx_xvreplve_w:
8392 case Intrinsic::loongarch_lasx_xvreplve_d:
8393 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
8397 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8401 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8402 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8406 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8410 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8414 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8415 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8419 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8423 case Intrinsic::loongarch_lsx_bz_b:
8424 case Intrinsic::loongarch_lsx_bz_h:
8425 case Intrinsic::loongarch_lsx_bz_w:
8426 case Intrinsic::loongarch_lsx_bz_d:
8427 case Intrinsic::loongarch_lasx_xbz_b:
8428 case Intrinsic::loongarch_lasx_xbz_h:
8429 case Intrinsic::loongarch_lasx_xbz_w:
8430 case Intrinsic::loongarch_lasx_xbz_d:
8432 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8435 case Intrinsic::loongarch_lsx_bz_v:
8436 case Intrinsic::loongarch_lasx_xbz_v:
8438 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8441 case Intrinsic::loongarch_lsx_bnz_b:
8442 case Intrinsic::loongarch_lsx_bnz_h:
8443 case Intrinsic::loongarch_lsx_bnz_w:
8444 case Intrinsic::loongarch_lsx_bnz_d:
8445 case Intrinsic::loongarch_lasx_xbnz_b:
8446 case Intrinsic::loongarch_lasx_xbnz_h:
8447 case Intrinsic::loongarch_lasx_xbnz_w:
8448 case Intrinsic::loongarch_lasx_xbnz_d:
8450 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8453 case Intrinsic::loongarch_lsx_bnz_v:
8454 case Intrinsic::loongarch_lasx_xbnz_v:
8456 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8459 case Intrinsic::loongarch_lasx_concat_128_s:
8460 case Intrinsic::loongarch_lasx_concat_128_d:
8461 case Intrinsic::loongarch_lasx_concat_128:
8463 N->getOperand(1),
N->getOperand(2));
8475 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8487 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8489 "Unexpected value type!");
8498 MVT VT =
N->getSimpleValueType(0);
8504 if (
TLI.SimplifyDemandedBits(
SDValue(
N, 0), DemandedMask, DCI))
8519 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8532 APInt V =
C->getValueAPF().bitcastToAPInt();
8547 MVT VT =
N->getSimpleValueType(0);
8606 EVT VT =
N->getValueType(0);
8608 EVT SrcVT = Src.getValueType();
8614 if (SrcEltBits >= DstEltBits)
8621 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8633 unsigned BlockBits) {
8635 MVT DstVT =
N->getSimpleValueType(0);
8637 MVT SrcVT = Src.getSimpleValueType();
8644 Src.getOperand(0).getValueType() == BlockVT) {
8645 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8647 }
else if (SrcBits > BlockBits) {
8649 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8654 BlockBits = SrcBits;
8661 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8666 if (BlockBits == 256) {
8676 if (Blocks.
size() == 1)
8686 EVT VT =
N->getValueType(0);
8688 EVT SrcVT = Src.getValueType();
8694 unsigned BlockBits =
Subtarget.hasExtLASX() ? 256 : 128;
8697 if (SrcEltBits <= DstEltBits)
8700 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8714 if (VT != MVT::f32 && VT != MVT::f64)
8716 if (VT == MVT::f32 && !
Subtarget.hasBasicF())
8718 if (VT == MVT::f64 && !
Subtarget.hasBasicD())
8750 EVT VT =
N->getValueType(0);
8771 EVT DstVT =
N->getValueType(0);
8773 EVT SrcVT = Src.getValueType();
8783 unsigned BlockBits =
Subtarget.hasExtLASX() ? 256 : 128;
8788 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8791 if (DstEltBits < 32) {
8797 if (SrcEltBits != 64 || DstEltBits != 32)
8836 if (!
TLI.isOperationLegalOrPromote(
N.getOpcode(), VT))
8875 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8885 EVT VT =
N.getValueType();
8902 switch (
N.getOpcode()) {
8918 EVT VT =
N->getValueType(0);
8926 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
8931 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
8933 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
8945 EVT VT =
N->getValueType(0);
8947 if (VT.
isVector() &&
N->getNumOperands() == 2)
8960 EVT VT =
N->getValueType(0);
8972 SDValue TrueVal =
N->getOperand(1);
8973 SDValue FalseVal =
N->getOperand(2);
9006 if (FalseVal.getOpcode() !=
ISD::ADD)
9009 SDValue Add0 = FalseVal.getOperand(0);
9010 SDValue Add1 = FalseVal.getOperand(1);
9080 : LoongArchISD::VSRAR,
9087 switch (
N->getOpcode()) {
9119 case LoongArchISD::BITREV_W:
9121 case LoongArchISD::BR_CC:
9123 case LoongArchISD::SELECT_CC:
9127 case LoongArchISD::MOVGR2FR_W_LA64:
9129 case LoongArchISD::MOVFR2GR_S_LA64:
9131 case LoongArchISD::CRC_W_B_W:
9132 case LoongArchISD::CRC_W_H_W:
9133 case LoongArchISD::CRCC_W_B_W:
9134 case LoongArchISD::CRCC_W_H_W:
9135 case LoongArchISD::VMSKLTZ:
9136 case LoongArchISD::XVMSKLTZ:
9138 case LoongArchISD::SPLIT_PAIR_F64:
9140 case LoongArchISD::VANDN:
9146 case LoongArchISD::VPACKEV:
9147 case LoongArchISD::VPERMI:
9173 MF->
insert(It, BreakMBB);
9177 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
9178 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
9190 MBB->addSuccessor(BreakMBB);
9191 MBB->addSuccessor(SinkMBB);
9197 BreakMBB->addSuccessor(SinkMBB);
9209 unsigned BroadcastOp;
9211 switch (
MI.getOpcode()) {
9214 case LoongArch::PseudoXVINSGR2VR_B:
9216 BroadcastOp = LoongArch::XVREPLGR2VR_B;
9217 InsOp = LoongArch::XVEXTRINS_B;
9219 case LoongArch::PseudoXVINSGR2VR_H:
9221 BroadcastOp = LoongArch::XVREPLGR2VR_H;
9222 InsOp = LoongArch::XVEXTRINS_H;
9234 unsigned Idx =
MI.getOperand(3).getImm();
9236 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
9238 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
9239 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
9242 .
addReg(XSrc, {}, LoongArch::sub_128);
9244 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
9245 : LoongArch::VINSGR2VR_B),
9253 .
addImm(LoongArch::sub_128);
9255 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9256 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9260 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
9263 .
addImm(Idx >= HalfSize ? 48 : 18);
9268 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
9271 MI.eraseFromParent();
9286 unsigned BroadcastOp, CTOp, PickOp;
9287 switch (
MI.getOpcode()) {
9290 case LoongArch::PseudoCTPOP_B:
9291 BroadcastOp = LoongArch::VREPLGR2VR_B;
9292 CTOp = LoongArch::VPCNT_B;
9293 PickOp = LoongArch::VPICKVE2GR_B;
9295 case LoongArch::PseudoCTPOP_H:
9296 case LoongArch::PseudoCTPOP_H_LA32:
9297 BroadcastOp = LoongArch::VREPLGR2VR_H;
9298 CTOp = LoongArch::VPCNT_H;
9299 PickOp = LoongArch::VPICKVE2GR_H;
9301 case LoongArch::PseudoCTPOP_W:
9302 case LoongArch::PseudoCTPOP_W_LA32:
9303 BroadcastOp = LoongArch::VREPLGR2VR_W;
9304 CTOp = LoongArch::VPCNT_W;
9305 PickOp = LoongArch::VPICKVE2GR_W;
9307 case LoongArch::PseudoCTPOP_D:
9308 BroadcastOp = LoongArch::VREPLGR2VR_D;
9309 CTOp = LoongArch::VPCNT_D;
9310 PickOp = LoongArch::VPICKVE2GR_D;
9314 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9315 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9320 MI.eraseFromParent();
9334 unsigned EleBits = 8;
9335 unsigned NotOpc = 0;
9338 switch (
MI.getOpcode()) {
9341 case LoongArch::PseudoVMSKLTZ_B:
9342 MskOpc = LoongArch::VMSKLTZ_B;
9344 case LoongArch::PseudoVMSKLTZ_H:
9345 MskOpc = LoongArch::VMSKLTZ_H;
9348 case LoongArch::PseudoVMSKLTZ_W:
9349 MskOpc = LoongArch::VMSKLTZ_W;
9352 case LoongArch::PseudoVMSKLTZ_D:
9353 MskOpc = LoongArch::VMSKLTZ_D;
9356 case LoongArch::PseudoVMSKGEZ_B:
9357 MskOpc = LoongArch::VMSKGEZ_B;
9359 case LoongArch::PseudoVMSKEQZ_B:
9360 MskOpc = LoongArch::VMSKNZ_B;
9361 NotOpc = LoongArch::VNOR_V;
9363 case LoongArch::PseudoVMSKNEZ_B:
9364 MskOpc = LoongArch::VMSKNZ_B;
9366 case LoongArch::PseudoXVMSKLTZ_B:
9367 MskOpc = LoongArch::XVMSKLTZ_B;
9368 RC = &LoongArch::LASX256RegClass;
9370 case LoongArch::PseudoXVMSKLTZ_H:
9371 MskOpc = LoongArch::XVMSKLTZ_H;
9372 RC = &LoongArch::LASX256RegClass;
9375 case LoongArch::PseudoXVMSKLTZ_W:
9376 MskOpc = LoongArch::XVMSKLTZ_W;
9377 RC = &LoongArch::LASX256RegClass;
9380 case LoongArch::PseudoXVMSKLTZ_D:
9381 MskOpc = LoongArch::XVMSKLTZ_D;
9382 RC = &LoongArch::LASX256RegClass;
9385 case LoongArch::PseudoXVMSKGEZ_B:
9386 MskOpc = LoongArch::XVMSKGEZ_B;
9387 RC = &LoongArch::LASX256RegClass;
9389 case LoongArch::PseudoXVMSKEQZ_B:
9390 MskOpc = LoongArch::XVMSKNZ_B;
9391 NotOpc = LoongArch::XVNOR_V;
9392 RC = &LoongArch::LASX256RegClass;
9394 case LoongArch::PseudoXVMSKNEZ_B:
9395 MskOpc = LoongArch::XVMSKNZ_B;
9396 RC = &LoongArch::LASX256RegClass;
9411 if (
TRI->getRegSizeInBits(*RC) > 128) {
9412 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9413 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9422 : LoongArch::BSTRINS_W),
9426 .
addImm(256 / EleBits - 1)
9434 MI.eraseFromParent();
9441 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9442 "Unexpected instruction");
9454 MI.eraseFromParent();
9461 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9462 "Unexpected instruction");
9468 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
9478 MI.eraseFromParent();
9483 switch (
MI.getOpcode()) {
9486 case LoongArch::Select_GPR_Using_CC_GPR:
9522 if (
MI.getOperand(2).isReg())
9523 RHS =
MI.getOperand(2).getReg();
9524 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9528 SelectDests.
insert(
MI.getOperand(0).getReg());
9532 SequenceMBBI !=
E; ++SequenceMBBI) {
9533 if (SequenceMBBI->isDebugInstr())
9536 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9537 !SequenceMBBI->getOperand(2).isReg() ||
9538 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9539 SequenceMBBI->getOperand(3).getImm() !=
CC ||
9540 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9541 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9543 LastSelectPseudo = &*SequenceMBBI;
9545 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9548 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9549 SequenceMBBI->mayLoadOrStore() ||
9550 SequenceMBBI->usesCustomInsertionHook())
9553 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9568 F->insert(
I, IfFalseMBB);
9569 F->insert(
I, TailMBB);
9572 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9578 TailMBB->
push_back(DebugInstr->removeFromParent());
9582 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9592 if (
MI.getOperand(2).isImm())
9604 auto SelectMBBI =
MI.getIterator();
9605 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9607 while (SelectMBBI != SelectEnd) {
9608 auto Next = std::next(SelectMBBI);
9612 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9613 .
addReg(SelectMBBI->getOperand(4).getReg())
9615 .
addReg(SelectMBBI->getOperand(5).getReg())
9622 F->getProperties().resetNoPHIs();
9628 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9631 switch (
MI.getOpcode()) {
9634 case LoongArch::DIV_W:
9635 case LoongArch::DIV_WU:
9636 case LoongArch::MOD_W:
9637 case LoongArch::MOD_WU:
9638 case LoongArch::DIV_D:
9639 case LoongArch::DIV_DU:
9640 case LoongArch::MOD_D:
9641 case LoongArch::MOD_DU:
9644 case LoongArch::WRFCSR: {
9646 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9647 .
addReg(
MI.getOperand(1).getReg());
9648 MI.eraseFromParent();
9651 case LoongArch::RDFCSR: {
9652 MachineInstr *ReadFCSR =
9654 MI.getOperand(0).getReg())
9655 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9657 MI.eraseFromParent();
9660 case LoongArch::Select_GPR_Using_CC_GPR:
9662 case LoongArch::BuildPairF64Pseudo:
9664 case LoongArch::SplitPairF64Pseudo:
9666 case LoongArch::PseudoXVINSGR2VR_B:
9667 case LoongArch::PseudoXVINSGR2VR_H:
9669 case LoongArch::PseudoCTPOP_B:
9670 case LoongArch::PseudoCTPOP_H:
9671 case LoongArch::PseudoCTPOP_W:
9672 case LoongArch::PseudoCTPOP_D:
9673 case LoongArch::PseudoCTPOP_H_LA32:
9674 case LoongArch::PseudoCTPOP_W_LA32:
9676 case LoongArch::PseudoVMSKLTZ_B:
9677 case LoongArch::PseudoVMSKLTZ_H:
9678 case LoongArch::PseudoVMSKLTZ_W:
9679 case LoongArch::PseudoVMSKLTZ_D:
9680 case LoongArch::PseudoVMSKGEZ_B:
9681 case LoongArch::PseudoVMSKEQZ_B:
9682 case LoongArch::PseudoVMSKNEZ_B:
9683 case LoongArch::PseudoXVMSKLTZ_B:
9684 case LoongArch::PseudoXVMSKLTZ_H:
9685 case LoongArch::PseudoXVMSKLTZ_W:
9686 case LoongArch::PseudoXVMSKLTZ_D:
9687 case LoongArch::PseudoXVMSKGEZ_B:
9688 case LoongArch::PseudoXVMSKEQZ_B:
9689 case LoongArch::PseudoXVMSKNEZ_B:
9691 case TargetOpcode::STATEPOINT:
9697 MI.addOperand(*
MI.getMF(),
9699 LoongArch::R1,
true,
9702 if (!Subtarget.is64Bit())
9705 case LoongArch::PROBED_STACKALLOC_DYN:
9712 unsigned *
Fast)
const {
9713 if (!Subtarget.hasUAL())
9731 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9732 LoongArch::R10, LoongArch::R11};
9747 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9748 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9749 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9750 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9751 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9752 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9758 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9759 LoongArch::F6, LoongArch::F7};
9762 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9763 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9766 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9767 LoongArch::VR6, LoongArch::VR7};
9770 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9771 LoongArch::XR6, LoongArch::XR7};
9774 switch (State.getCallingConv()) {
9776 if (!State.isVarArg())
9780 return State.AllocateReg(
ArgGPRs);
9788 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9790 unsigned GRLenInBytes = GRLen / 8;
9801 State.AllocateStack(GRLenInBytes, StackAlign),
9804 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9815 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9823 unsigned ValNo,
MVT ValVT,
9826 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9827 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9828 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9833 if (IsRet && ValNo > 1)
9837 bool UseGPRForFloat =
true;
9847 UseGPRForFloat = ArgFlags.
isVarArg();
9860 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9863 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9864 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9866 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9872 State.getPendingArgFlags();
9875 "PendingLocs and PendingArgFlags out of sync");
9879 UseGPRForFloat =
true;
9881 if (UseGPRForFloat && ValVT == MVT::f32) {
9884 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9887 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9890 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9932 PendingLocs.
size() <= 2) {
9933 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9938 PendingLocs.
clear();
9939 PendingArgFlags.
clear();
9946 unsigned StoreSizeBytes = GRLen / 8;
9949 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9951 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9955 UseGPRForFloat =
false;
9956 StoreSizeBytes = 16;
9957 StackAlign =
Align(16);
9960 UseGPRForFloat =
false;
9961 StoreSizeBytes = 32;
9962 StackAlign =
Align(32);
9968 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9972 if (!PendingLocs.
empty()) {
9974 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9975 for (
auto &It : PendingLocs) {
9977 It.convertToReg(
Reg);
9982 PendingLocs.clear();
9983 PendingArgFlags.
clear();
9986 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9987 "Expected an GRLenVT at this stage");
10004void LoongArchTargetLowering::analyzeInputArgs(
10007 LoongArchCCAssignFn Fn)
const {
10009 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
10010 MVT ArgVT = Ins[i].VT;
10011 Type *ArgTy =
nullptr;
10013 ArgTy = FType->getReturnType();
10014 else if (Ins[i].isOrigArg())
10015 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
10019 CCInfo, IsRet, ArgTy)) {
10020 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
10027void LoongArchTargetLowering::analyzeOutputArgs(
10030 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
10031 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10032 MVT ArgVT = Outs[i].VT;
10033 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
10037 CCInfo, IsRet, OrigTy)) {
10038 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
10057 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
10079 if (In.isOrigArg()) {
10084 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
10085 (
BitWidth < 32 && In.Flags.isZExt())) {
10135 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10148 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10152 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
10166 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
10178 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
10182 LoongArch::R23, LoongArch::R24, LoongArch::R25,
10183 LoongArch::R26, LoongArch::R27, LoongArch::R28,
10184 LoongArch::R29, LoongArch::R30, LoongArch::R31};
10191 if (LocVT == MVT::f32) {
10194 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
10195 LoongArch::F26, LoongArch::F27};
10202 if (LocVT == MVT::f64) {
10205 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
10206 LoongArch::F30_64, LoongArch::F31_64};
10225 switch (CallConv) {
10237 "GHC calling convention requires the F and D extensions");
10242 MVT GRLenVT = Subtarget.getGRLenVT();
10243 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
10252 return CI->isMustTailCall();
10257 std::vector<SDValue> OutChains;
10266 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
10268 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10285 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10294 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10295 assert(ArgPartOffset == 0);
10296 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10298 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10322 int VaArgOffset, VarArgsSaveSize;
10326 if (ArgRegs.
size() == Idx) {
10328 VarArgsSaveSize = 0;
10330 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10331 VaArgOffset = -VarArgsSaveSize;
10337 LoongArchFI->setVarArgsFrameIndex(FI);
10345 VarArgsSaveSize += GRLenInBytes;
10350 for (
unsigned I = Idx;
I < ArgRegs.
size();
10351 ++
I, VaArgOffset += GRLenInBytes) {
10352 const Register Reg = RegInfo.createVirtualRegister(RC);
10353 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10361 ->setValue((
Value *)
nullptr);
10362 OutChains.push_back(
Store);
10364 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10369 if (!OutChains.empty()) {
10370 OutChains.push_back(Chain);
10385 if (
N->getNumValues() != 1)
10387 if (!
N->hasNUsesOfValue(1, 0))
10390 SDNode *Copy = *
N->user_begin();
10396 if (Copy->getGluedNode())
10400 bool HasRet =
false;
10402 if (
Node->getOpcode() != LoongArchISD::RET)
10410 Chain = Copy->getOperand(0);
10415bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10419 auto CalleeCC = CLI.CallConv;
10420 auto &Outs = CLI.Outs;
10422 auto CallerCC = Caller.getCallingConv();
10424 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10433 for (
auto &Arg : Outs)
10434 if (Arg.Flags.isByVal())
10450 for (
auto &VA : ArgLocs)
10456 auto IsCallerStructRet = Caller.hasStructRetAttr();
10457 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10458 if (IsCallerStructRet || IsCalleeStructRet)
10463 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10464 if (CalleeCC != CallerCC) {
10465 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10466 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10492 MVT GRLenVT = Subtarget.getGRLenVT();
10504 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10508 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10514 "site marked musttail");
10521 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10523 if (!Flags.isByVal())
10527 unsigned Size = Flags.getByValSize();
10528 Align Alignment = Flags.getNonZeroByValAlign();
10535 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10537 false,
nullptr, std::nullopt,
10549 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10552 SDValue ArgValue = OutVals[OutIdx];
10560 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10561 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10573 if (!StackPtr.getNode())
10585 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10599 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10619 const Argument *FormalArg =
nullptr;
10620 unsigned FilteredIdx = 0;
10621 for (
const auto &CallArg : CLI.
CB->
args()) {
10622 if (CallArg->getType()->isEmptyTy())
10624 if (FilteredIdx == CallArgIdx) {
10633 unsigned FormalArgIdx = CallArgIdx;
10635 FormalArgIdx = FormalArg->
getArgNo();
10639 if (Arg.getType()->isEmptyTy())
10641 if (FilteredIdx == CallArgIdx) {
10642 FormalArgIdx = Arg.getArgNo();
10655 SDValue IncomingPtr = CopyOp;
10672 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10673 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10674 SDValue PartValue = OutVals[OutIdx + 1];
10675 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10686 ArgValue = IncomingPtr;
10690 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10702 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10703 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10704 assert(ArgPartOffset == 0);
10709 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10710 SDValue PartValue = OutVals[OutIdx + 1];
10711 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10723 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10725 for (
const auto &Part : Parts) {
10726 SDValue PartValue = Part.first;
10727 SDValue PartOffset = Part.second;
10734 ArgValue = SpillSlot;
10741 if (Flags.isByVal())
10742 ArgValue = ByValArgs[j++];
10750 "Tail call not allowed if stack is used for passing parameters");
10753 if (!StackPtr.getNode())
10766 if (!MemOpChains.
empty())
10772 for (
auto &Reg : RegsToPass) {
10773 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10795 Ops.push_back(Chain);
10796 Ops.push_back(Callee);
10800 for (
auto &Reg : RegsToPass)
10801 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10806 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10807 assert(Mask &&
"Missing call preserved mask for calling convention");
10813 Ops.push_back(Glue);
10822 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10825 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10828 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10829 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10851 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10854 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10855 auto &VA = RVLocs[i];
10863 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10864 assert(VA.needsCustom());
10869 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10870 RetValue, RetValue2);
10883 const Type *RetTy)
const {
10885 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10887 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10891 Outs[i].Flags, CCInfo,
true,
nullptr))
10917 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10918 SDValue Val = OutVals[OutIdx];
10927 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10931 Register RegHi = RVLocs[++i].getLocReg();
10956 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10964 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10965 uint64_t RequiredImm = 0;
10967 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10969 RequiredImm = (0b10101 << 8) | (V >> 8);
10970 return {
true, RequiredImm};
10971 }
else if (SplatBitSize == 32) {
10973 if (!(V & 0xFFFF00FF)) {
10974 RequiredImm = (0b10001 << 8) | (V >> 8);
10975 return {
true, RequiredImm};
10978 if (!(V & 0xFF00FFFF)) {
10979 RequiredImm = (0b10010 << 8) | (V >> 16);
10980 return {
true, RequiredImm};
10983 if (!(V & 0x00FFFFFF)) {
10984 RequiredImm = (0b10011 << 8) | (V >> 24);
10985 return {
true, RequiredImm};
10988 if ((V & 0xFFFF00FF) == 0xFF) {
10989 RequiredImm = (0b10110 << 8) | (V >> 8);
10990 return {
true, RequiredImm};
10993 if ((V & 0xFF00FFFF) == 0xFFFF) {
10994 RequiredImm = (0b10111 << 8) | (V >> 16);
10995 return {
true, RequiredImm};
10998 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
11000 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11001 return {
true, RequiredImm};
11003 }
else if (SplatBitSize == 64) {
11005 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
11006 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
11008 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11009 return {
true, RequiredImm};
11012 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
11013 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
11015 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
11016 return {
true, RequiredImm};
11019 auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {
11021 for (
int i = 0; i < 8; ++i) {
11023 if (
byte == 0 ||
byte == 0xFF)
11024 res |= ((
byte & 1) << i);
11029 return {
true, res};
11031 auto [IsSame, Suffix] = sameBitsPreByte(V);
11033 RequiredImm = (0b11001 << 8) | Suffix;
11034 return {
true, RequiredImm};
11037 return {
false, RequiredImm};
11042 if (!Subtarget.hasExtLSX())
11045 if (VT == MVT::f32) {
11046 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
11047 return (masked == 0x3e000000 || masked == 0x40000000);
11050 if (VT == MVT::f64) {
11051 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
11052 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
11061bool LoongArchTargetLowering::shouldConvertFpToSat(
unsigned Op,
EVT FPVT,
11067 if (FPVT == MVT::f32)
11069 return FPVT == MVT::f64 &&
Subtarget.hasBasicD();
11073LoongArchTargetLowering::getFPImmAction(
const APFloat &
Imm,
EVT VT,
11074 bool ForCodeSize)
const {
11076 if (VT == MVT::f32 && !
Subtarget.hasBasicF())
11078 if (VT == MVT::f64 && !
Subtarget.hasBasicD())
11096 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
11108bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
11118 Type *Ty =
I->getOperand(0)->getType();
11120 unsigned Size = Ty->getIntegerBitWidth();
11140 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
11145 if (Subtarget.hasExtLASX())
11147 else if (Subtarget.hasExtLSX())
11154 EVT VT =
Y.getValueType();
11157 return Subtarget.hasExtLSX() && VT.
isInteger();
11168 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
11169 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
11170 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
11171 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
11174 Info.memVT = MVT::i32;
11175 Info.ptrVal =
I.getArgOperand(0);
11177 Info.align =
Align(4);
11196 "Unable to expand");
11197 unsigned MinWordSize = 4;
11209 Value *AlignedAddr = Builder.CreateIntrinsic(
11210 Intrinsic::ptrmask, {PtrTy, IntTy},
11211 {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))},
nullptr,
11214 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
11215 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
11216 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
11217 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
11218 Value *Mask = Builder.CreateShl(
11219 ConstantInt::get(WordType,
11220 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
11222 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
11223 Value *ValOperand_Shifted =
11224 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
11225 ShiftAmt,
"ValOperand_Shifted");
11228 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
11230 NewOperand = ValOperand_Shifted;
11233 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
11236 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
11237 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
11238 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
11257 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
11265 if (Subtarget.hasLAMCAS()) {
11287 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
11289 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
11291 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
11293 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
11295 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
11297 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
11299 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
11301 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11311 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11313 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11315 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11317 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11319 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11321 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11323 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11325 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11337 if (Subtarget.hasLAMCAS())
11349 unsigned GRLen = Subtarget.getGRLen();
11351 Value *FailureOrdering =
11352 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t
>(FailOrd));
11353 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11355 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11356 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11357 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11358 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11361 Value *Result = Builder.CreateIntrinsic(
11362 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11364 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11380 Builder.CreateNot(Mask,
"Inv_Mask"),
11387 unsigned GRLen = Subtarget.getGRLen();
11389 Builder.getIntN(GRLen,
static_cast<uint64_t
>(AI->
getOrdering()));
11396 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11397 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11398 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11411 unsigned ValWidth =
11414 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11415 Result = Builder.CreateCall(LlwOpScwLoop,
11416 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11419 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11423 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11447 return LoongArch::R4;
11452 return LoongArch::R5;
11463 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11464 return RefinementSteps;
11470 "Reciprocal estimate queried on unsupported target");
11498 int &RefinementSteps,
11499 bool &UseOneConstNR,
11500 bool Reciprocal)
const {
11502 "Enabled should never be Disabled here");
11504 if (!Subtarget.hasFrecipe())
11519 UseOneConstNR =
false;
11525 if (Reciprocal || RefinementSteps > 0)
11535 int &RefinementSteps)
const {
11537 "Enabled should never be Disabled here");
11539 if (!Subtarget.hasFrecipe())
11553 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11561LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11581 if (Constraint.
size() == 1) {
11582 switch (Constraint[0]) {
11598 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11607 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11614std::pair<unsigned, const TargetRegisterClass *>
11615LoongArchTargetLowering::getRegForInlineAsmConstraint(
11619 if (Constraint.
size() == 1) {
11620 switch (Constraint[0]) {
11625 return std::make_pair(0U, &LoongArch::GPRRegClass);
11627 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11629 if (Subtarget.hasBasicF() && VT == MVT::f32)
11630 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11631 if (Subtarget.hasBasicD() && VT == MVT::f64)
11632 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11633 if (Subtarget.hasExtLSX() &&
11634 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11635 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11636 if (Subtarget.hasExtLSX() && VT == MVT::i128)
11637 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11638 if (Subtarget.hasExtLASX() &&
11639 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11640 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11660 bool IsFP = Constraint[2] ==
'f';
11661 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11662 std::pair<unsigned, const TargetRegisterClass *>
R;
11667 unsigned RegNo =
R.first;
11668 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11669 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11670 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11671 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11681void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11685 if (Constraint.
size() == 1) {
11686 switch (Constraint[0]) {
11693 Subtarget.getGRLenVT()));
11702 Subtarget.getGRLenVT()));
11708 if (
C->getZExtValue() == 0)
11728#define GET_REGISTER_MATCHER
11729#include "LoongArchGenAsmMatcher.inc"
11735 std::string NewRegName = Name.second.str();
11741 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11742 if (!ReservedRegs.
test(Reg))
11759 const APInt &
Imm = ConstNode->getAPIntValue();
11761 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2() ||
11762 (1 -
Imm).isPowerOf2() || (-1 -
Imm).isPowerOf2())
11765 if (ConstNode->hasOneUse() &&
11766 ((
Imm - 2).isPowerOf2() || (
Imm - 4).isPowerOf2() ||
11767 (
Imm - 8).isPowerOf2() || (
Imm - 16).isPowerOf2()))
11773 if (ConstNode->hasOneUse() && !(
Imm.sge(-2048) &&
Imm.sle(4095))) {
11774 unsigned Shifts =
Imm.countr_zero();
11781 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11785 APInt ImmSmall =
APInt(
Imm.getBitWidth(), 1ULL << Shifts,
true);
11786 if ((
Imm - ImmSmall).isPowerOf2() || (
Imm + ImmSmall).isPowerOf2() ||
11787 (ImmSmall -
Imm).isPowerOf2())
11797 Type *Ty,
unsigned AS,
11816 switch (AM.
Scale) {
11852 EVT MemVT = LD->getMemoryVT();
11853 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11864 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11873 if (
Y.getValueType().isVector())
11885 Type *Ty,
bool IsSigned)
const {
11886 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11895 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11896 Type.getSizeInBits() < Subtarget.getGRLen()))
11906 Align &PrefAlign)
const {
11910 if (Subtarget.is64Bit()) {
11912 PrefAlign =
Align(8);
11915 PrefAlign =
Align(4);
11930bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11932 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
11933 bool IsABIRegCopy =
CC.has_value();
11936 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11937 PartVT == MVT::f32) {
11952SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11954 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
11955 bool IsABIRegCopy =
CC.has_value();
11957 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11958 PartVT == MVT::f32) {
11975 if (VT == MVT::f16 && Subtarget.hasBasicF())
11981unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11984 if (VT == MVT::f16 && Subtarget.hasBasicF())
11993 unsigned Opc =
Op.getOpcode();
11998 case LoongArchISD::VANYNONZERO:
11999 case LoongArchISD::VALLZERO:
12000 case LoongArchISD::VALL_ZERO:
12001 case LoongArchISD::VANY_ZERO:
12002 case LoongArchISD::VALL_NONZERO:
12003 case LoongArchISD::VANY_NONZERO: {
12005 Known.Zero.setBitsFrom(1);
12008 case LoongArchISD::VPICK_ZEXT_ELT: {
12012 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
12013 Known.Zero.setBitsFrom(VTBits);
12016 case LoongArchISD::BSTRINS: {
12018 unsigned Msb =
Op.getConstantOperandVal(2);
12019 unsigned Lsb =
Op.getConstantOperandVal(3);
12022 Known.insertBits(Known2.
trunc(Msb - Lsb + 1), Lsb);
12025 case LoongArchISD::BSTRPICK: {
12028 unsigned Msb =
Op.getConstantOperandVal(1);
12029 unsigned Lsb =
Op.getConstantOperandVal(2);
12039 unsigned Depth)
const {
12040 switch (
Op.getOpcode()) {
12043 case LoongArchISD::BSTRINS: {
12044 unsigned BitWidth =
Op.getScalarValueSizeInBits();
12045 unsigned Msb =
Op.getConstantOperandVal(2);
12046 unsigned Lsb =
Op.getConstantOperandVal(3);
12050 return std::min(Tmp,
BitWidth - 1 - Msb);
12054 return Tmp > Lsb ? Tmp - Lsb : 1;
12063 unsigned Depth)
const {
12064 EVT VT =
Op.getValueType();
12066 unsigned Opc =
Op.getOpcode();
12070 case LoongArchISD::CRC_W_B_W:
12071 case LoongArchISD::CRC_W_H_W:
12072 case LoongArchISD::CRCC_W_B_W:
12073 case LoongArchISD::CRCC_W_H_W: {
12075 APInt DemandedSrcBits =
12077 Opc == LoongArchISD::CRCC_W_B_W)
12081 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
12083 case LoongArchISD::VMSKLTZ:
12084 case LoongArchISD::XVMSKLTZ: {
12086 MVT SrcVT = Src.getSimpleValueType();
12091 if (OriginalDemandedBits.
countr_zero() >= NumElts)
12095 APInt KnownUndef, KnownZero;
12111 if (KnownSrc.
One[SrcBits - 1])
12112 Known.One.setLowBits(NumElts);
12113 else if (KnownSrc.
Zero[SrcBits - 1])
12114 Known.Zero.setLowBits(NumElts);
12118 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
12125 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
12149 unsigned Index)
const {
12160 unsigned Index)
const {
12164 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
12179 Align StackAlign)
const {
12183 unsigned StackProbeSize =
12187 return StackProbeSize ? StackProbeSize : StackAlign.
value();
12191LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
12205 const EVT VT =
Op.getValueType();
12216 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
12226 const Register TargetReg =
MI.getOperand(0).getReg();
12229 const bool IsLA64 = Subtarget.is64Bit();
12230 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
12232 const uint64_t ProbeSize =
TLI->getStackProbeSize(MF, StackAlign);
12237 MF.
insert(MBBInsertPoint, LoopTestMBB);
12240 MF.
insert(MBBInsertPoint, ExitMBB);
12251 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
12257 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
12263 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
12278 MBB->addSuccessor(LoopTestMBB);
12280 MI.eraseFromParent();
12282 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)
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
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)
bpf unwind BPF Unwind Lower
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue performUINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performHorizWideningCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static std::pair< SDValue, EVT > stripSignExtendInReg(SDValue V)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static SDValue ExtendSrcToDst(SDNode *N, SelectionDAG &DAG, unsigned ExtendOp)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static SDValue performDemandedBitsCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static std::tuple< unsigned, SDValue, EVT > matchBinOpWithSharedOperand(SDValue BinV, SDValue X)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVPERMIQ(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI_Q (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldVMskZeroTest(SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue matchDeinterleaveBuildVector(SDValue N, unsigned &StartIndex)
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVE0 (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue MergeBlocksConvert(SDNode *N, SelectionDAG &DAG, unsigned Opcode, unsigned BlockBits)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue convertRMEncoding(SelectionDAG &DAG, const SDLoc &DL, MVT GRLenVT, SDValue RMValue)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
MachineBasicBlock * Folded
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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,...
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.
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
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
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.
bool isFPImmCheapInGPR(const APFloat &Imm, EVT VT) const
Returns true if building Imm in a GPR and moving it to a float register is cheaper than loading it fr...
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
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 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
ISD::CondCode getOperandCondCode(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl, SDNodeFlags Flags={})
Constant fold a setcc to true or false.
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of 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 getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isZeroEltSplatMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses all elements with the same value as the first element of exa...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
FPImmAction
How the legalizer should materialize a floating-point immediate.
@ ConstantPool
Load the immediate from the constant pool.
@ Legal
The target can instruction select the immediate natively.
@ Bitcast
Build the immediate as a bitcast of an integer constant with the same bits.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ 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 - Same semantics as the llvm.minnum/maxnum intrinsics.
@ 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 ...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
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)