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()) {
531 if (Subtarget.has32S())
536 if (Subtarget.hasExtLSX()) {
552 if (Subtarget.hasExtLASX()) {
577 if (Subtarget.hasLAMCAS())
580 if (Subtarget.hasSCQ()) {
600 switch (
Op.getOpcode()) {
602 return lowerATOMIC_FENCE(
Op, DAG);
604 return lowerEH_DWARF_CFA(
Op, DAG);
606 return lowerGlobalAddress(
Op, DAG);
608 return lowerGlobalTLSAddress(
Op, DAG);
610 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
612 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
614 return lowerINTRINSIC_VOID(
Op, DAG);
616 return lowerBlockAddress(
Op, DAG);
618 return lowerJumpTable(
Op, DAG);
620 return lowerShiftLeftParts(
Op, DAG);
622 return lowerShiftRightParts(
Op, DAG,
true);
624 return lowerShiftRightParts(
Op, DAG,
false);
626 return lowerConstantPool(
Op, DAG);
628 return lowerFP_TO_SINT(
Op, DAG);
630 return lowerFP_TO_UINT(
Op, DAG);
632 return lowerFP_TO_SINT_SAT(
Op, DAG);
634 return lowerBITCAST(
Op, DAG);
636 return lowerUINT_TO_FP(
Op, DAG);
638 return lowerSINT_TO_FP(
Op, DAG);
640 return lowerVASTART(
Op, DAG);
642 return lowerFRAMEADDR(
Op, DAG);
644 return lowerRETURNADDR(
Op, DAG);
646 return lowerSET_ROUNDING(
Op, DAG);
648 return lowerGET_ROUNDING(
Op, DAG);
650 return lowerWRITE_REGISTER(
Op, DAG);
652 return lowerINSERT_VECTOR_ELT(
Op, DAG);
654 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
656 return lowerBUILD_VECTOR(
Op, DAG);
658 return lowerCONCAT_VECTORS(
Op, DAG);
660 return lowerVECTOR_SHUFFLE(
Op, DAG);
662 return lowerBITREVERSE(
Op, DAG);
664 return lowerSCALAR_TO_VECTOR(
Op, DAG);
666 return lowerPREFETCH(
Op, DAG);
668 return lowerSELECT(
Op, DAG);
670 return lowerBRCOND(
Op, DAG);
672 return lowerFP_TO_FP16(
Op, DAG);
674 return lowerFP16_TO_FP(
Op, DAG);
676 return lowerFP_TO_BF16(
Op, DAG);
678 return lowerBF16_TO_FP(
Op, DAG);
680 return lowerVECREDUCE_ADD(
Op, DAG);
683 return lowerRotate(
Op, DAG);
691 return lowerVECREDUCE(
Op, DAG);
693 return lowerConstantFP(
Op, DAG);
695 return lowerSETCC(
Op, DAG);
697 return lowerFP_ROUND(
Op, DAG);
699 return lowerFP_EXTEND(
Op, DAG);
701 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
703 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
705 return lowerANY_EXTEND(
Op, DAG);
707 return lowerVSELECT(
Op, DAG);
716 EVT VT =
V.getValueType();
722 return V.getOperand(0);
728 Not = DAG.
getBitcast(
V.getOperand(0).getValueType(), Not);
738 if (!
V->isOnlyUserOf(SplatValue.getNode()))
742 Not = DAG.
getBitcast(
V.getOperand(0).getValueType(), Not);
750 V.getOperand(0).hasOneUse() &&
V.getOperand(1).hasOneUse()) {
778 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
779 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
786 if (Opcode0 != Opcode1)
789 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
796 EVT VT =
N.getValueType();
811 SSVT0 == MVT::v4f64) {
830 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
831 N->getOpcode() == LoongArchISD::VPERMI) &&
832 Opcode0 == LoongArchISD::VFCVT) {
837 if (!
Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
840 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
841 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
847 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
863 MVT VT =
Op.getSimpleValueType();
864 MVT SVT =
In.getSimpleValueType();
866 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
879 EVT VT =
Op.getValueType();
881 EVT SVT = Src.getValueType();
884 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
886 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
887 if (!V2F32ToV2F64 && !V4F32ToV4F64)
914 if (
SDValue V = CheckVecHighPart(Src)) {
916 "Unexpected wide vector");
917 Opcode = LoongArchISD::VFCVTH;
920 Opcode = LoongArchISD::VFCVTL;
922 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
927 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
933 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
948 MVT VT =
Op.getSimpleValueType();
957 APInt SplatValue, SplatUndef;
958 unsigned SplatBitSize;
963 if (BVN->
isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
965 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
970 EVT CondVT =
Cond.getValueType();
972 Mask.resize(NumElts, -1);
973 for (
int i = 0; i < NumElts; ++i) {
978 if (CondElt->getZExtValue() == 0)
979 Mask[i] = i + NumElts;
993 EVT VT =
Op.getValueType();
998 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
999 (VT == MVT::f64 && Subtarget.hasBasicD()));
1017 if (VT == MVT::f32) {
1018 assert(Subtarget.is64Bit());
1021 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, VT, NewVal);
1024 assert(VT == MVT::f64 && !Subtarget.is64Bit());
1027 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
1035 EVT ResultVT =
Op.getValueType();
1036 EVT OperandVT =
Op.getOperand(0).getValueType();
1041 if (ResultVT == SetCCResultVT)
1044 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
1045 "SETCC operands must have the same type!");
1049 Op.getOperand(1),
Op.getOperand(2));
1051 if (ResultVT.
bitsGT(SetCCResultVT))
1053 else if (ResultVT.
bitsLT(SetCCResultVT))
1082SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1086 MVT SrcVT = Src.getSimpleValueType();
1087 MVT DstVT =
Op.getSimpleValueType();
1093 unsigned Ratio = DstEltBits / SrcEltBits;
1102 if (Ratio == 2 && !IsSignSplat)
1103 return DAG.
getNode(LoongArchISD::VSLLWIL,
DL, DstVT, Src,
1107 for (
unsigned EltBits = SrcEltBits; EltBits < DstEltBits; EltBits *= 2) {
1110 Res = DAG.
getNode(LoongArchISD::VILVL,
DL, VT, Res, Res);
1122 assert(Subtarget.hasExtLASX());
1141 MVT OpVT =
Op.getSimpleValueType();
1148 unsigned LegalVecSize = 128;
1149 bool isLASX256Vector =
1159 if (isLASX256Vector) {
1165 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1166 EleBits = std::min(EleBits, 64u);
1169 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1172 if (isLASX256Vector) {
1198 MVT OpVT =
Op.getSimpleValueType();
1211 MVT GRLenVT = Subtarget.getGRLenVT();
1213 for (
int i = NumEles; i > 1; i /= 2) {
1216 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1225 unsigned IsData =
Op.getConstantOperandVal(4);
1230 return Op.getOperand(0);
1237 MVT VT =
Op.getSimpleValueType();
1243 unsigned Opcode =
Op.getOpcode();
1246 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1252 CstSplatValue =
C->getAPIntValue();
1260 APInt CstSplatValue;
1261 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1265 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1281 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1297 if (
LHS == LHS2 &&
RHS == RHS2) {
1302 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1310 return std::nullopt;
1318 MVT VT =
N->getSimpleValueType(0);
1349 if (~TrueVal == FalseVal) {
1389 unsigned SelOpNo = 0;
1399 unsigned ConstSelOpNo = 1;
1400 unsigned OtherSelOpNo = 2;
1407 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1412 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1418 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1420 std::swap(NewConstOps[0], NewConstOps[1]);
1432 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1434 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1437 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1438 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1458 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1472 int64_t
C = RHSC->getSExtValue();
1515 MVT VT =
Op.getSimpleValueType();
1516 MVT GRLenVT = Subtarget.getGRLenVT();
1521 if (
Op.hasOneUse()) {
1522 unsigned UseOpc =
Op->user_begin()->getOpcode();
1524 SDNode *BinOp = *
Op->user_begin();
1531 return lowerSELECT(NewSel, DAG);
1548 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1571 if (TrueVal - 1 == FalseVal)
1573 if (TrueVal + 1 == FalseVal)
1580 RHS == TrueV &&
LHS == FalseV) {
1605 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1612 MVT GRLenVT = Subtarget.getGRLenVT();
1623 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1624 Op.getOperand(0),
LHS,
RHS, TargetCC,
1627 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1628 Op.getOperand(0), CondV,
Op.getOperand(2));
1632 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1638LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1641 MVT OpVT =
Op.getSimpleValueType();
1652 EVT ResTy =
Op->getValueType(0);
1657 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1667 for (
unsigned int i = 0; i < NewEltNum; i++) {
1670 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1671 ? (
unsigned)LoongArchISD::BITREV_8B
1689 for (
unsigned int i = 0; i < NewEltNum; i++)
1690 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1691 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1709 if (EltBits > 32 || EltBits == 1)
1737 int MaskOffset,
const APInt &Zeroable) {
1738 int Size = Mask.size();
1739 unsigned SizeInBits =
Size * ScalarSizeInBits;
1741 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1742 for (
int i = 0; i <
Size; i += Scale)
1743 for (
int j = 0; j < Shift; ++j)
1744 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1752 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1753 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1758 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1759 for (
int i = 0; i !=
Size; i += Scale) {
1760 unsigned Pos =
Left ? i + Shift : i;
1761 unsigned Low =
Left ? i : i + Shift;
1762 unsigned Len = Scale - Shift;
1767 int ShiftEltBits = ScalarSizeInBits * Scale;
1768 bool ByteShift = ShiftEltBits > 64;
1769 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1770 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1771 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1775 Scale = ByteShift ? Scale / 2 : Scale;
1781 return (
int)ShiftAmt;
1784 unsigned MaxWidth = 128;
1785 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1786 for (
int Shift = 1; Shift != Scale; ++Shift)
1787 for (
bool Left : {
true,
false})
1788 if (CheckZeros(Shift, Scale,
Left)) {
1789 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1814 const APInt &Zeroable) {
1815 int Size = Mask.size();
1829 Mask,
Size, Zeroable);
1837 "Illegal integer vector type");
1846template <
typename ValType>
1849 unsigned CheckStride,
1851 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1855 if (*
I != -1 && *
I != ExpectedIndex)
1857 ExpectedIndex += ExpectedIndexStride;
1861 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1873 int Size = Mask.size();
1882 int VectorSizeInBits =
V1.getValueSizeInBits();
1883 int ScalarSizeInBits = VectorSizeInBits /
Size;
1884 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1885 (void)ScalarSizeInBits;
1887 for (
int i = 0; i <
Size; ++i) {
1893 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1910 RepeatedMask.
assign(LaneSize, -1);
1911 int Size = Mask.size();
1912 for (
int i = 0; i <
Size; ++i) {
1913 assert(Mask[i] == -1 || Mask[i] >= 0);
1916 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1923 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1924 if (RepeatedMask[i % LaneSize] < 0)
1926 RepeatedMask[i % LaneSize] = LocalM;
1927 else if (RepeatedMask[i % LaneSize] != LocalM)
1944 int NumElts = RepeatedMask.
size();
1946 int Scale = 16 / NumElts;
1948 for (
int i = 0; i < NumElts; ++i) {
1949 int M = RepeatedMask[i];
1950 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1951 "Unexpected mask index.");
1956 int StartIdx = i - (M % NumElts);
1963 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1966 Rotation = CandidateRotation;
1967 else if (Rotation != CandidateRotation)
1982 else if (TargetV != MaskV)
1987 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1988 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1997 return Rotation * Scale;
2016 if (ByteRotation <= 0)
2023 int LoByteShift = 16 - ByteRotation;
2024 int HiByteShift = ByteRotation;
2047 const APInt &Zeroable) {
2061 for (
int i = 0; i < NumElements; i++) {
2065 if (i % Scale != 0) {
2077 M = M % NumElements;
2080 Offset = M - (i / Scale);
2083 if (
Offset % (NumElements / Scale))
2085 }
else if (InputV !=
V)
2088 if (M != (
Offset + (i / Scale)))
2098 unsigned VilVLoHi = LoongArchISD::VILVL;
2099 if (
Offset >= (NumElements / 2)) {
2100 VilVLoHi = LoongArchISD::VILVH;
2101 Offset -= (NumElements / 2);
2109 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2113 }
while (Scale > 1);
2119 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2120 NumExtElements *= 2) {
2140 int SplatIndex = -1;
2141 for (
const auto &M : Mask) {
2148 if (SplatIndex == -1)
2151 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2153 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2183 unsigned SubVecSize = 4;
2184 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2187 int SubMask[4] = {-1, -1, -1, -1};
2188 for (
unsigned i = 0; i < SubVecSize; ++i) {
2189 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2195 M -= 4 * (j / SubVecSize);
2196 if (M < 0 || M >= 4)
2202 if (SubMask[i] == -1)
2206 else if (M != -1 && M != SubMask[i])
2213 for (
int i = SubVecSize - 1; i >= 0; --i) {
2226 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2227 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2230 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2248 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2257 for (
int i = 0; i < WidenNumElts; ++i)
2258 WidenMask[i] = WidenNumElts - 1 - i;
2266 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2290 const auto &Begin = Mask.begin();
2291 const auto &
End = Mask.end();
2308 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2330 const auto &Begin = Mask.begin();
2331 const auto &
End = Mask.end();
2348 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2371 const auto &Begin = Mask.begin();
2372 const auto &
End = Mask.end();
2373 unsigned HalfSize = Mask.size() / 2;
2391 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2414 const auto &Begin = Mask.begin();
2415 const auto &
End = Mask.end();
2432 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2454 const auto &Begin = Mask.begin();
2455 const auto &Mid = Mask.begin() + Mask.size() / 2;
2456 const auto &
End = Mask.end();
2474 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2496 const auto &Begin = Mask.begin();
2497 const auto &Mid = Mask.begin() + Mask.size() / 2;
2498 const auto &
End = Mask.end();
2515 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2541 if (Mask.size() != NumElts)
2544 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2547 for (
unsigned i = 0; i < NumElts; ++i) {
2550 if (Mask[i] !=
int(
Base + i)) {
2563 int DiffMask = Mask[DiffPos];
2564 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2570 if (
unsigned(DiffMask) < NumElts) {
2575 SrcIdx =
unsigned(DiffMask) - NumElts;
2591 if (
SDValue Result = tryLowerToExtrAndIns(0))
2593 return tryLowerToExtrAndIns(NumElts);
2601 unsigned &MaskImm) {
2602 unsigned MaskSize = Mask.size();
2605 return (M == -1) || (M >=
Off && M <
Off + 4);
2608 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2609 auto immPart = [&](
int M,
unsigned Off) {
2610 return (M == -1 ? 0 : (M -
Off)) & 0x3;
2612 MaskImm |= immPart(MLo,
Off) << (
I * 2);
2613 MaskImm |= immPart(MHi,
Off) << ((
I + 1) * 2);
2616 for (
unsigned i = 0; i < 4; i += 2) {
2618 int MHi = Mask[i + 1];
2620 if (MaskSize == 8) {
2621 auto isValid2 = [&](
int &M,
int M2) {
2628 if ((M2 % MaskSize) < 4)
2636 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2642 buildImm(MLo, MHi, 0, i);
2645 buildImm(MLo, MHi, MaskSize, i);
2675 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2680 unsigned MaskImm = 0;
2684 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2711 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2724 "Vector type is unsupported for lsx!");
2726 "Two operands have different types!");
2728 "Unexpected mask size for shuffle!");
2729 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2731 APInt KnownUndef, KnownZero;
2733 APInt Zeroable = KnownUndef | KnownZero;
2806 int SplatIndex = -1;
2807 for (
const auto &M : Mask) {
2814 if (SplatIndex == -1)
2817 const auto &Begin = Mask.begin();
2818 const auto &
End = Mask.end();
2819 int HalfSize = Mask.size() / 2;
2821 if (SplatIndex >= HalfSize)
2824 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2828 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2842 if (Mask.size() == 4) {
2843 unsigned MaskImm = 0;
2844 for (
int i = 1; i >= 0; --i) {
2846 int MHi = Mask[i + 2];
2847 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2848 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2850 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2855 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2857 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2860 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2881 return DAG.
getNode(LoongArchISD::XVREPLVE0,
DL, VT,
V1);
2890 unsigned MaskSize = Mask.size();
2895 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2897 unsigned MaskImm = 0;
2901 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2906 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2907 unsigned MaskImm = 0;
2908 for (
unsigned i = 0; i < MaskSize; ++i) {
2911 if (Mask[i] >= (
int)MaskSize)
2913 MaskImm |= Mask[i] << (i * 2);
2916 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2928 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2932 unsigned HalfSize = NumElts / 2;
2933 bool FrontLo =
true, FrontHi =
true;
2934 bool BackLo =
true, BackHi =
true;
2936 auto inRange = [](
int val,
int low,
int high) {
2937 return (val == -1) || (val >= low && val < high);
2940 for (
unsigned i = 0; i < HalfSize; ++i) {
2941 int Fronti = Mask[i];
2942 int Backi = Mask[i + HalfSize];
2944 FrontLo &=
inRange(Fronti, 0, HalfSize);
2945 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2946 BackLo &=
inRange(Backi, 0, HalfSize);
2947 BackHi &=
inRange(Backi, HalfSize, NumElts);
2953 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2958 for (
unsigned i = 0; i < NumElts; ++i)
2963 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2985 const auto &Begin = Mask.begin();
2986 const auto &
End = Mask.end();
2987 unsigned HalfSize = Mask.size() / 2;
2988 unsigned LeftSize = HalfSize / 2;
2996 Mask.size() + HalfSize - LeftSize, 1) &&
2998 Mask.size() + HalfSize + LeftSize, 1))
3009 Mask.size() + HalfSize - LeftSize, 1) &&
3011 Mask.size() + HalfSize + LeftSize, 1))
3016 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
3024 const auto &Begin = Mask.begin();
3025 const auto &
End = Mask.end();
3026 unsigned HalfSize = Mask.size() / 2;
3034 Mask.size() + HalfSize, 1))
3045 Mask.size() + HalfSize, 1))
3050 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
3058 const auto &Begin = Mask.begin();
3059 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3060 const auto &Mid = Mask.begin() + Mask.size() / 2;
3061 const auto &RightMid = Mask.end() - Mask.size() / 4;
3062 const auto &
End = Mask.end();
3063 unsigned HalfSize = Mask.size() / 2;
3085 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
3093 const auto &Begin = Mask.begin();
3094 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3095 const auto &Mid = Mask.begin() + Mask.size() / 2;
3096 const auto &RightMid = Mask.end() - Mask.size() / 4;
3097 const auto &
End = Mask.end();
3098 unsigned HalfSize = Mask.size() / 2;
3121 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3130 int HalfSize = NumElts / 2;
3134 if ((
int)Mask.size() != NumElts)
3137 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3139 for (
int i = 0; i < NumElts; ++i) {
3142 if (Mask[i] !=
Base + i) {
3144 if (DiffPos.
size() > 2)
3152 if (DiffPos.
size() == 1) {
3153 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3154 DiffPos.
push_back(DiffPos[0] + HalfSize);
3155 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3156 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3160 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3164 int DiffMaskLo = Mask[DiffPos[0]];
3165 int DiffMaskHi = Mask[DiffPos[1]];
3166 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3167 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3168 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3169 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3171 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3172 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3174 if (DiffMaskHi != DiffMaskLo + HalfSize)
3178 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3180 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3201 if (
SDValue Result = tryLowerToExtrAndIns(0))
3203 return tryLowerToExtrAndIns(NumElts);
3212 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3217 int MaskSize = Mask.size();
3223 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3225 for (
int i = 0; i < MaskSize; ++i) {
3226 if (Mask[i] ==
Base + i || Mask[i] == -1)
3228 if (Mask[i] != Replaced)
3239 int Idx = checkReplaceOne(0, MaskSize);
3241 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3245 Idx = checkReplaceOne(MaskSize, 0);
3247 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3258 int MaskSize = Mask.size();
3259 int HalfSize = Mask.size() / 2;
3260 const auto &Begin = Mask.begin();
3261 const auto &Mid = Mask.begin() + HalfSize;
3262 const auto &
End = Mask.end();
3274 for (
auto it = Begin; it < Mid; it++) {
3277 else if ((*it >= 0 && *it < HalfSize) ||
3278 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3279 int M = *it < HalfSize ? *it : *it - HalfSize;
3284 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3286 for (
auto it = Mid; it <
End; it++) {
3289 else if ((*it >= HalfSize && *it < MaskSize) ||
3290 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3291 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3296 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3300 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3328 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3330 int MaskSize = Mask.size();
3331 int HalfSize = Mask.size() / 2;
3334 HalfMaskType preMask =
None, postMask =
None;
3336 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3337 return M < 0 || (M >= 0 && M < HalfSize) ||
3338 (M >= MaskSize && M < MaskSize + HalfSize);
3340 preMask = HighLaneTy;
3341 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3342 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3343 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3345 preMask = LowLaneTy;
3347 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3348 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3349 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3351 postMask = LowLaneTy;
3352 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3353 return M < 0 || (M >= 0 && M < HalfSize) ||
3354 (M >= MaskSize && M < MaskSize + HalfSize);
3356 postMask = HighLaneTy;
3364 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3367 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3375 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3380 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3381 *it = *it < 0 ? *it : *it - HalfSize;
3383 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3384 *it = *it < 0 ? *it : *it + HalfSize;
3386 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3394 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3399 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3400 *it = *it < 0 ? *it : *it - HalfSize;
3402 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3410 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3415 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3416 *it = *it < 0 ? *it : *it + HalfSize;
3443 int Lo = LaneMask[0] < 0 ? 0 : LaneMask[0];
3444 int Hi = LaneMask[1] < 0 ? 1 : LaneMask[1];
3446 LoongArchISD::XVPERMIQ,
DL, VT, V2,
V1,
3479 int Size = Mask.size();
3480 int LaneSize =
Size / 2;
3484 int LaneSrcs[2][2] = {{-1, -1}, {-1, -1}};
3486 bool LaneCrossing =
false;
3487 for (
int i = 0; i <
Size; ++i) {
3491 int Lane = i / LaneSize;
3492 int SrcLane = M / LaneSize;
3496 int Op = (SrcLane % 2) != Lane;
3498 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3500 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3502 LaneSrcs[Lane][
Op] = SrcLane;
3503 InLaneMask[i] =
Op *
Size + Lane * LaneSize + M % LaneSize;
3514 for (
int i = LaneSize; i <
Size; ++i)
3515 if (SwappedMask[i] >= 0)
3516 SwappedMask[i] = (SwappedMask[i] +
Size) % (2 *
Size);
3518 std::swap(LaneSrcs[1][0], LaneSrcs[1][1]);
3519 InLaneMask = SwappedMask;
3525 for (
int Op = 0;
Op < 2; ++
Op) {
3527 for (
int Lane = 0; Lane < 2; ++Lane)
3528 if (LaneSrcs[Lane][
Op] >= 0)
3529 for (
int i = 0; i < LaneSize; ++i)
3530 LaneMask[Lane * LaneSize + i] = LaneSrcs[Lane][
Op] * LaneSize + i;
3536 if (SVN->getMask() == Mask)
3552 "Vector type is unsupported for lasx!");
3554 "Two operands have different types!");
3556 "Unexpected mask size for shuffle!");
3557 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3558 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3560 APInt KnownUndef, KnownZero;
3562 APInt Zeroable = KnownUndef | KnownZero;
3653 ArrayRef<int> OrigMask = SVOp->
getMask();
3656 MVT VT =
Op.getSimpleValueType();
3660 bool V1IsUndef =
V1.isUndef();
3661 bool V2IsUndef = V2.
isUndef();
3662 if (V1IsUndef && V2IsUndef)
3675 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3676 SmallVector<int, 8> NewMask(OrigMask);
3677 for (
int &M : NewMask)
3678 if (M >= NumElements)
3684 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3685 (void)MaskUpperLimit;
3687 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3688 "Out of bounds shuffle index");
3710 std::tie(Res, Chain) =
3711 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3712 if (Subtarget.is64Bit())
3713 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3725 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3729 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3730 CallOptions,
DL, Chain);
3736 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3742 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3743 if (Subtarget.is64Bit())
3744 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3750 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3751 MVT VT =
Op.getSimpleValueType();
3756 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3777 "Unsupported vector type for broadcast.");
3780 bool IsIdeneity =
true;
3782 for (
int i = 0; i !=
NumOps; i++) {
3784 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3796 auto ExtType = LN->getExtensionType();
3801 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3806 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3824 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3838 EVT ResTy,
unsigned first) {
3841 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3844 Node->op_begin() + first + NumElts);
3853 MVT VT =
Node->getSimpleValueType(0);
3854 EVT ResTy =
Op->getValueType(0);
3857 APInt SplatValue, SplatUndef;
3858 unsigned SplatBitSize;
3861 bool UseSameConstant =
true;
3866 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3867 (!Subtarget.hasExtLASX() || !Is256Vec))
3873 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3875 SplatBitSize <= 64) {
3877 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3881 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3888 if ((Is128Vec && ResTy == MVT::v4i32) ||
3889 (Is256Vec && ResTy == MVT::v8i32))
3895 switch (SplatBitSize) {
3899 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3902 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3905 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3908 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3916 if (ViaVecTy != ResTy)
3925 for (
unsigned i = 0; i < NumElts; ++i) {
3930 ConstantValue = Opi;
3931 else if (ConstantValue != Opi)
3932 UseSameConstant =
false;
3937 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3939 for (
unsigned i = 0; i < NumElts; ++i) {
3957 BitVector UndefElements;
3958 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3959 UndefElements.
count() == 0) {
3963 EVT FillTy = Is256Vec
3969 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3972 unsigned SplatLen = NumElts / SeqLen;
3978 if (SplatEltTy == MVT::i128)
3979 SplatTy = MVT::v4i64;
3987 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3988 : LoongArchISD::XVREPLVE0,
3989 DL, SplatTy, SrcVec);
3991 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
4004 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
4005 ResTy == MVT::v4f64) {
4006 unsigned NonUndefCount = 0;
4007 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
4008 if (!
Node->getOperand(i).isUndef()) {
4010 if (NonUndefCount > 1)
4014 if (NonUndefCount == 1)
4027 VecTy, NumElts / 2);
4038 MVT ResVT =
Op.getSimpleValueType();
4046 unsigned NumFreezeUndef = 0;
4047 unsigned NumZero = 0;
4048 unsigned NumNonZero = 0;
4049 unsigned NonZeros = 0;
4050 SmallSet<SDValue, 4> Undefs;
4051 for (
unsigned i = 0; i != NumOperands; ++i) {
4066 assert(i <
sizeof(NonZeros) * CHAR_BIT);
4073 if (NumNonZero > 2) {
4077 Ops.slice(0, NumOperands / 2));
4079 Ops.slice(NumOperands / 2));
4092 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
4094 for (
unsigned i = 0; i != NumOperands; ++i) {
4095 if ((NonZeros & (1 << i)) == 0)
4106LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
4108 MVT EltVT =
Op.getSimpleValueType();
4113 MVT GRLenVT = Subtarget.getGRLenVT();
4141 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
4145 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
4147 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
4156 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
4165LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
4167 MVT VT =
Op.getSimpleValueType();
4189 auto ExtType = LN->getExtensionType();
4190 if (LN->isSimple() &&
4192 LN->getMemoryVT().getSizeInBits() == EltSizeInBits) {
4194 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
4196 if (EltSizeInBits >= 32) {
4201 FltVT,
DL, LN->getChain(), LN->getBasePtr(), LN->getPointerInfo(),
4202 LN->getAlign(), LN->getMemOperand()->getFlags(), LN->getAAInfo());
4208 SDVTList Tys = DAG.
getVTList(VT, MVT::Other);
4209 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
4211 LN->getMemoryVT(), LN->getMemOperand());
4232 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4234 for (
unsigned i = 0; i < NumElts; ++i) {
4242 for (
unsigned i = 0; i < NumElts; ++i) {
4251 for (
unsigned i = 0; i < NumElts; ++i)
4304 MVT GRLenVT = Subtarget.getGRLenVT();
4316 "rounding mode is not supported by LoongArch hardware",
4317 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4334 FCSRNo, RMValue, Chain);
4340 MVT GRLenVT = Subtarget.getGRLenVT();
4347 MVT::Other, FCSRNo, Chain);
4363 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4365 "On LA64, only 64-bit registers can be written.");
4366 return Op.getOperand(0);
4369 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4371 "On LA32, only 32-bit registers can be written.");
4372 return Op.getOperand(0);
4382 "be a constant integer");
4388 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4389 EVT VT =
Op.getValueType();
4392 unsigned Depth =
Op.getConstantOperandVal(0);
4393 int GRLenInBytes = Subtarget.getGRLen() / 8;
4396 int Offset = -(GRLenInBytes * 2);
4408 if (
Op.getConstantOperandVal(0) != 0) {
4410 "return address can only be determined for the current frame");
4416 MVT GRLenVT = Subtarget.getGRLenVT();
4428 auto Size = Subtarget.getGRLen() / 8;
4436 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4446 MachinePointerInfo(SV));
4464 EVT SrcVT = Src.getValueType();
4465 EVT DstVT =
Op.getValueType();
4496 EVT VT =
Op.getValueType();
4506 if (Subtarget.hasExtLASX() && Op0VT.
getScalarType() == MVT::i64 &&
4510 return lowerUINT_TO_FPToF32(
Op, DAG);
4522 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4530 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4533 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4534 !Subtarget.hasBasicD() &&
"unexpected target features");
4538 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4542 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4552 EVT RetVT =
Op.getValueType();
4558 std::tie(Result, Chain) =
4565 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4566 !Subtarget.hasBasicD() &&
"unexpected target features");
4577 EVT RetVT =
Op.getValueType();
4583 std::tie(Result, Chain) =
4592 EVT VT =
Op.getValueType();
4596 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4597 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4599 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4601 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4604 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4618 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4619 !Subtarget.hasBasicD()) {
4621 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4636 EVT VT =
Op.getValueType();
4637 EVT SrcVT = Src.getValueType();
4638 unsigned SatWidth =
cast<VTSDNode>(
Op.getOperand(1))->getVT().getSizeInBits();
4648 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4651 if (SatWidth == 32) {
4653 if (Subtarget.is64Bit())
4654 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, VT, Ftint);
4658 if (SatWidth == 64 && Subtarget.is64Bit() && Subtarget.hasBasicD()) {
4668 if (!Subtarget.hasExtLSX())
4673 EVT VT =
Op.getValueType();
4674 EVT SrcVT = Src.getValueType();
4679 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4682 if (SrcVT == MVT::f32)
4704 N->getOffset(), Flags);
4712template <
class NodeTy>
4715 bool IsLocal)
const {
4726 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4807 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4809 const GlobalValue *GV =
N->getGlobal();
4821 unsigned Opc,
bool UseGOT,
4825 MVT GRLenVT = Subtarget.getGRLenVT();
4839 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4880 TargetLowering::CallLoweringInfo CLI(DAG);
4895 const GlobalValue *GV =
N->getGlobal();
4909LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4916 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4919 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4932 return getDynamicTLSAddr(
N, DAG,
4933 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4934 : LoongArch::PseudoLA_TLS_GD,
4941 return getDynamicTLSAddr(
N, DAG,
4942 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4943 : LoongArch::PseudoLA_TLS_LD,
4948 return getStaticTLSAddr(
N, DAG,
4949 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4950 : LoongArch::PseudoLA_TLS_IE,
4957 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4961 return getTLSDescAddr(
N, DAG,
4962 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4963 : LoongArch::PseudoLA_TLS_DESC,
4967template <
unsigned N>
4972 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4973 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4975 ": argument out of range.");
4982LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4984 switch (
Op.getConstantOperandVal(0)) {
4987 case Intrinsic::thread_pointer: {
4991 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4992 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4993 case Intrinsic::loongarch_lsx_vreplvei_d:
4994 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4996 case Intrinsic::loongarch_lsx_vreplvei_w:
4997 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4998 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4999 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
5000 case Intrinsic::loongarch_lasx_xvpickve_d:
5001 case Intrinsic::loongarch_lasx_xvpickve_d_f:
5003 case Intrinsic::loongarch_lasx_xvinsve0_d:
5005 case Intrinsic::loongarch_lsx_vsat_b:
5006 case Intrinsic::loongarch_lsx_vsat_bu:
5007 case Intrinsic::loongarch_lsx_vrotri_b:
5008 case Intrinsic::loongarch_lsx_vsllwil_h_b:
5009 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
5010 case Intrinsic::loongarch_lsx_vsrlri_b:
5011 case Intrinsic::loongarch_lsx_vsrari_b:
5012 case Intrinsic::loongarch_lsx_vreplvei_h:
5013 case Intrinsic::loongarch_lasx_xvsat_b:
5014 case Intrinsic::loongarch_lasx_xvsat_bu:
5015 case Intrinsic::loongarch_lasx_xvrotri_b:
5016 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
5017 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
5018 case Intrinsic::loongarch_lasx_xvsrlri_b:
5019 case Intrinsic::loongarch_lasx_xvsrari_b:
5020 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
5021 case Intrinsic::loongarch_lasx_xvpickve_w:
5022 case Intrinsic::loongarch_lasx_xvpickve_w_f:
5024 case Intrinsic::loongarch_lasx_xvinsve0_w:
5026 case Intrinsic::loongarch_lsx_vsat_h:
5027 case Intrinsic::loongarch_lsx_vsat_hu:
5028 case Intrinsic::loongarch_lsx_vrotri_h:
5029 case Intrinsic::loongarch_lsx_vsllwil_w_h:
5030 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
5031 case Intrinsic::loongarch_lsx_vsrlri_h:
5032 case Intrinsic::loongarch_lsx_vsrari_h:
5033 case Intrinsic::loongarch_lsx_vreplvei_b:
5034 case Intrinsic::loongarch_lasx_xvsat_h:
5035 case Intrinsic::loongarch_lasx_xvsat_hu:
5036 case Intrinsic::loongarch_lasx_xvrotri_h:
5037 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
5038 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
5039 case Intrinsic::loongarch_lasx_xvsrlri_h:
5040 case Intrinsic::loongarch_lasx_xvsrari_h:
5041 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
5043 case Intrinsic::loongarch_lsx_vsrlni_b_h:
5044 case Intrinsic::loongarch_lsx_vsrani_b_h:
5045 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
5046 case Intrinsic::loongarch_lsx_vsrarni_b_h:
5047 case Intrinsic::loongarch_lsx_vssrlni_b_h:
5048 case Intrinsic::loongarch_lsx_vssrani_b_h:
5049 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
5050 case Intrinsic::loongarch_lsx_vssrani_bu_h:
5051 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
5052 case Intrinsic::loongarch_lsx_vssrarni_b_h:
5053 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
5054 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
5055 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
5056 case Intrinsic::loongarch_lasx_xvsrani_b_h:
5057 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
5058 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
5059 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
5060 case Intrinsic::loongarch_lasx_xvssrani_b_h:
5061 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
5062 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
5063 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
5064 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
5065 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
5066 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
5068 case Intrinsic::loongarch_lsx_vsat_w:
5069 case Intrinsic::loongarch_lsx_vsat_wu:
5070 case Intrinsic::loongarch_lsx_vrotri_w:
5071 case Intrinsic::loongarch_lsx_vsllwil_d_w:
5072 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
5073 case Intrinsic::loongarch_lsx_vsrlri_w:
5074 case Intrinsic::loongarch_lsx_vsrari_w:
5075 case Intrinsic::loongarch_lsx_vslei_bu:
5076 case Intrinsic::loongarch_lsx_vslei_hu:
5077 case Intrinsic::loongarch_lsx_vslei_wu:
5078 case Intrinsic::loongarch_lsx_vslei_du:
5079 case Intrinsic::loongarch_lsx_vslti_bu:
5080 case Intrinsic::loongarch_lsx_vslti_hu:
5081 case Intrinsic::loongarch_lsx_vslti_wu:
5082 case Intrinsic::loongarch_lsx_vslti_du:
5083 case Intrinsic::loongarch_lsx_vbsll_v:
5084 case Intrinsic::loongarch_lsx_vbsrl_v:
5085 case Intrinsic::loongarch_lasx_xvsat_w:
5086 case Intrinsic::loongarch_lasx_xvsat_wu:
5087 case Intrinsic::loongarch_lasx_xvrotri_w:
5088 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
5089 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
5090 case Intrinsic::loongarch_lasx_xvsrlri_w:
5091 case Intrinsic::loongarch_lasx_xvsrari_w:
5092 case Intrinsic::loongarch_lasx_xvslei_bu:
5093 case Intrinsic::loongarch_lasx_xvslei_hu:
5094 case Intrinsic::loongarch_lasx_xvslei_wu:
5095 case Intrinsic::loongarch_lasx_xvslei_du:
5096 case Intrinsic::loongarch_lasx_xvslti_bu:
5097 case Intrinsic::loongarch_lasx_xvslti_hu:
5098 case Intrinsic::loongarch_lasx_xvslti_wu:
5099 case Intrinsic::loongarch_lasx_xvslti_du:
5100 case Intrinsic::loongarch_lasx_xvbsll_v:
5101 case Intrinsic::loongarch_lasx_xvbsrl_v:
5103 case Intrinsic::loongarch_lsx_vseqi_b:
5104 case Intrinsic::loongarch_lsx_vseqi_h:
5105 case Intrinsic::loongarch_lsx_vseqi_w:
5106 case Intrinsic::loongarch_lsx_vseqi_d:
5107 case Intrinsic::loongarch_lsx_vslei_b:
5108 case Intrinsic::loongarch_lsx_vslei_h:
5109 case Intrinsic::loongarch_lsx_vslei_w:
5110 case Intrinsic::loongarch_lsx_vslei_d:
5111 case Intrinsic::loongarch_lsx_vslti_b:
5112 case Intrinsic::loongarch_lsx_vslti_h:
5113 case Intrinsic::loongarch_lsx_vslti_w:
5114 case Intrinsic::loongarch_lsx_vslti_d:
5115 case Intrinsic::loongarch_lasx_xvseqi_b:
5116 case Intrinsic::loongarch_lasx_xvseqi_h:
5117 case Intrinsic::loongarch_lasx_xvseqi_w:
5118 case Intrinsic::loongarch_lasx_xvseqi_d:
5119 case Intrinsic::loongarch_lasx_xvslei_b:
5120 case Intrinsic::loongarch_lasx_xvslei_h:
5121 case Intrinsic::loongarch_lasx_xvslei_w:
5122 case Intrinsic::loongarch_lasx_xvslei_d:
5123 case Intrinsic::loongarch_lasx_xvslti_b:
5124 case Intrinsic::loongarch_lasx_xvslti_h:
5125 case Intrinsic::loongarch_lasx_xvslti_w:
5126 case Intrinsic::loongarch_lasx_xvslti_d:
5128 case Intrinsic::loongarch_lsx_vsrlni_h_w:
5129 case Intrinsic::loongarch_lsx_vsrani_h_w:
5130 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
5131 case Intrinsic::loongarch_lsx_vsrarni_h_w:
5132 case Intrinsic::loongarch_lsx_vssrlni_h_w:
5133 case Intrinsic::loongarch_lsx_vssrani_h_w:
5134 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
5135 case Intrinsic::loongarch_lsx_vssrani_hu_w:
5136 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
5137 case Intrinsic::loongarch_lsx_vssrarni_h_w:
5138 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
5139 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
5140 case Intrinsic::loongarch_lsx_vfrstpi_b:
5141 case Intrinsic::loongarch_lsx_vfrstpi_h:
5142 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
5143 case Intrinsic::loongarch_lasx_xvsrani_h_w:
5144 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
5145 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
5146 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
5147 case Intrinsic::loongarch_lasx_xvssrani_h_w:
5148 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
5149 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
5150 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
5151 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
5152 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
5153 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
5154 case Intrinsic::loongarch_lasx_xvfrstpi_b:
5155 case Intrinsic::loongarch_lasx_xvfrstpi_h:
5157 case Intrinsic::loongarch_lsx_vsat_d:
5158 case Intrinsic::loongarch_lsx_vsat_du:
5159 case Intrinsic::loongarch_lsx_vrotri_d:
5160 case Intrinsic::loongarch_lsx_vsrlri_d:
5161 case Intrinsic::loongarch_lsx_vsrari_d:
5162 case Intrinsic::loongarch_lasx_xvsat_d:
5163 case Intrinsic::loongarch_lasx_xvsat_du:
5164 case Intrinsic::loongarch_lasx_xvrotri_d:
5165 case Intrinsic::loongarch_lasx_xvsrlri_d:
5166 case Intrinsic::loongarch_lasx_xvsrari_d:
5168 case Intrinsic::loongarch_lsx_vsrlni_w_d:
5169 case Intrinsic::loongarch_lsx_vsrani_w_d:
5170 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
5171 case Intrinsic::loongarch_lsx_vsrarni_w_d:
5172 case Intrinsic::loongarch_lsx_vssrlni_w_d:
5173 case Intrinsic::loongarch_lsx_vssrani_w_d:
5174 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
5175 case Intrinsic::loongarch_lsx_vssrani_wu_d:
5176 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
5177 case Intrinsic::loongarch_lsx_vssrarni_w_d:
5178 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
5179 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
5180 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
5181 case Intrinsic::loongarch_lasx_xvsrani_w_d:
5182 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
5183 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
5184 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
5185 case Intrinsic::loongarch_lasx_xvssrani_w_d:
5186 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
5187 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
5188 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
5189 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
5190 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
5191 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
5193 case Intrinsic::loongarch_lsx_vsrlni_d_q:
5194 case Intrinsic::loongarch_lsx_vsrani_d_q:
5195 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
5196 case Intrinsic::loongarch_lsx_vsrarni_d_q:
5197 case Intrinsic::loongarch_lsx_vssrlni_d_q:
5198 case Intrinsic::loongarch_lsx_vssrani_d_q:
5199 case Intrinsic::loongarch_lsx_vssrlni_du_q:
5200 case Intrinsic::loongarch_lsx_vssrani_du_q:
5201 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
5202 case Intrinsic::loongarch_lsx_vssrarni_d_q:
5203 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
5204 case Intrinsic::loongarch_lsx_vssrarni_du_q:
5205 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
5206 case Intrinsic::loongarch_lasx_xvsrani_d_q:
5207 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
5208 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
5209 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
5210 case Intrinsic::loongarch_lasx_xvssrani_d_q:
5211 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
5212 case Intrinsic::loongarch_lasx_xvssrani_du_q:
5213 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
5214 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
5215 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
5216 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
5218 case Intrinsic::loongarch_lsx_vnori_b:
5219 case Intrinsic::loongarch_lsx_vshuf4i_b:
5220 case Intrinsic::loongarch_lsx_vshuf4i_h:
5221 case Intrinsic::loongarch_lsx_vshuf4i_w:
5222 case Intrinsic::loongarch_lasx_xvnori_b:
5223 case Intrinsic::loongarch_lasx_xvshuf4i_b:
5224 case Intrinsic::loongarch_lasx_xvshuf4i_h:
5225 case Intrinsic::loongarch_lasx_xvshuf4i_w:
5226 case Intrinsic::loongarch_lasx_xvpermi_d:
5228 case Intrinsic::loongarch_lsx_vshuf4i_d:
5229 case Intrinsic::loongarch_lsx_vpermi_w:
5230 case Intrinsic::loongarch_lsx_vbitseli_b:
5231 case Intrinsic::loongarch_lsx_vextrins_b:
5232 case Intrinsic::loongarch_lsx_vextrins_h:
5233 case Intrinsic::loongarch_lsx_vextrins_w:
5234 case Intrinsic::loongarch_lsx_vextrins_d:
5235 case Intrinsic::loongarch_lasx_xvshuf4i_d:
5236 case Intrinsic::loongarch_lasx_xvpermi_w:
5237 case Intrinsic::loongarch_lasx_xvpermi_q:
5238 case Intrinsic::loongarch_lasx_xvbitseli_b:
5239 case Intrinsic::loongarch_lasx_xvextrins_b:
5240 case Intrinsic::loongarch_lasx_xvextrins_h:
5241 case Intrinsic::loongarch_lasx_xvextrins_w:
5242 case Intrinsic::loongarch_lasx_xvextrins_d:
5244 case Intrinsic::loongarch_lsx_vrepli_b:
5245 case Intrinsic::loongarch_lsx_vrepli_h:
5246 case Intrinsic::loongarch_lsx_vrepli_w:
5247 case Intrinsic::loongarch_lsx_vrepli_d:
5248 case Intrinsic::loongarch_lasx_xvrepli_b:
5249 case Intrinsic::loongarch_lasx_xvrepli_h:
5250 case Intrinsic::loongarch_lasx_xvrepli_w:
5251 case Intrinsic::loongarch_lasx_xvrepli_d:
5253 case Intrinsic::loongarch_lsx_vldi:
5254 case Intrinsic::loongarch_lasx_xvldi:
5270LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
5273 MVT GRLenVT = Subtarget.getGRLenVT();
5274 EVT VT =
Op.getValueType();
5276 const StringRef ErrorMsgOOR =
"argument out of range";
5277 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5278 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5280 switch (
Op.getConstantOperandVal(1)) {
5283 case Intrinsic::loongarch_crc_w_b_w:
5284 case Intrinsic::loongarch_crc_w_h_w:
5285 case Intrinsic::loongarch_crc_w_w_w:
5286 case Intrinsic::loongarch_crc_w_d_w:
5287 case Intrinsic::loongarch_crcc_w_b_w:
5288 case Intrinsic::loongarch_crcc_w_h_w:
5289 case Intrinsic::loongarch_crcc_w_w_w:
5290 case Intrinsic::loongarch_crcc_w_d_w:
5292 case Intrinsic::loongarch_csrrd_w:
5293 case Intrinsic::loongarch_csrrd_d: {
5294 unsigned Imm =
Op.getConstantOperandVal(2);
5297 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5300 case Intrinsic::loongarch_csrwr_w:
5301 case Intrinsic::loongarch_csrwr_d: {
5302 unsigned Imm =
Op.getConstantOperandVal(3);
5305 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5306 {Chain,
Op.getOperand(2),
5309 case Intrinsic::loongarch_csrxchg_w:
5310 case Intrinsic::loongarch_csrxchg_d: {
5311 unsigned Imm =
Op.getConstantOperandVal(4);
5314 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5315 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5318 case Intrinsic::loongarch_iocsrrd_d: {
5320 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5323#define IOCSRRD_CASE(NAME, NODE) \
5324 case Intrinsic::loongarch_##NAME: { \
5325 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5326 {Chain, Op.getOperand(2)}); \
5332 case Intrinsic::loongarch_cpucfg: {
5333 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5334 {Chain,
Op.getOperand(2)});
5336 case Intrinsic::loongarch_lddir_d: {
5337 unsigned Imm =
Op.getConstantOperandVal(3);
5342 case Intrinsic::loongarch_movfcsr2gr: {
5343 if (!Subtarget.hasBasicF())
5345 unsigned Imm =
Op.getConstantOperandVal(2);
5348 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5351 case Intrinsic::loongarch_lsx_vld:
5352 case Intrinsic::loongarch_lsx_vldrepl_b:
5353 case Intrinsic::loongarch_lasx_xvld:
5354 case Intrinsic::loongarch_lasx_xvldrepl_b:
5358 case Intrinsic::loongarch_lsx_vldrepl_h:
5359 case Intrinsic::loongarch_lasx_xvldrepl_h:
5363 Op,
"argument out of range or not a multiple of 2", DAG)
5365 case Intrinsic::loongarch_lsx_vldrepl_w:
5366 case Intrinsic::loongarch_lasx_xvldrepl_w:
5370 Op,
"argument out of range or not a multiple of 4", DAG)
5372 case Intrinsic::loongarch_lsx_vldrepl_d:
5373 case Intrinsic::loongarch_lasx_xvldrepl_d:
5377 Op,
"argument out of range or not a multiple of 8", DAG)
5388 return Op.getOperand(0);
5394 MVT GRLenVT = Subtarget.getGRLenVT();
5396 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5398 const StringRef ErrorMsgOOR =
"argument out of range";
5399 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5400 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5401 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5403 switch (IntrinsicEnum) {
5407 case Intrinsic::loongarch_cacop_d:
5408 case Intrinsic::loongarch_cacop_w: {
5409 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5411 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5420 case Intrinsic::loongarch_dbar: {
5427 case Intrinsic::loongarch_ibar: {
5434 case Intrinsic::loongarch_break: {
5441 case Intrinsic::loongarch_movgr2fcsr: {
5442 if (!Subtarget.hasBasicF())
5452 case Intrinsic::loongarch_syscall: {
5459#define IOCSRWR_CASE(NAME, NODE) \
5460 case Intrinsic::loongarch_##NAME: { \
5461 SDValue Op3 = Op.getOperand(3); \
5462 return Subtarget.is64Bit() \
5463 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5464 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5465 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5466 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5473 case Intrinsic::loongarch_iocsrwr_d: {
5474 return !Subtarget.is64Bit()
5481#define ASRT_LE_GT_CASE(NAME) \
5482 case Intrinsic::loongarch_##NAME: { \
5483 return !Subtarget.is64Bit() \
5484 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5489#undef ASRT_LE_GT_CASE
5490 case Intrinsic::loongarch_ldpte_d: {
5491 unsigned Imm =
Op.getConstantOperandVal(3);
5492 return !Subtarget.is64Bit()
5497 case Intrinsic::loongarch_lsx_vst:
5498 case Intrinsic::loongarch_lasx_xvst:
5502 case Intrinsic::loongarch_lasx_xvstelm_b:
5507 case Intrinsic::loongarch_lsx_vstelm_b:
5512 case Intrinsic::loongarch_lasx_xvstelm_h:
5517 Op,
"argument out of range or not a multiple of 2", DAG)
5519 case Intrinsic::loongarch_lsx_vstelm_h:
5524 Op,
"argument out of range or not a multiple of 2", DAG)
5526 case Intrinsic::loongarch_lasx_xvstelm_w:
5531 Op,
"argument out of range or not a multiple of 4", DAG)
5533 case Intrinsic::loongarch_lsx_vstelm_w:
5538 Op,
"argument out of range or not a multiple of 4", DAG)
5540 case Intrinsic::loongarch_lasx_xvstelm_d:
5545 Op,
"argument out of range or not a multiple of 8", DAG)
5547 case Intrinsic::loongarch_lsx_vstelm_d:
5552 Op,
"argument out of range or not a multiple of 8", DAG)
5563 EVT VT =
Lo.getValueType();
5604 EVT VT =
Lo.getValueType();
5658 return LoongArchISD::DIV_W;
5660 return LoongArchISD::DIV_WU;
5662 return LoongArchISD::MOD_W;
5664 return LoongArchISD::MOD_WU;
5666 return LoongArchISD::SLL_W;
5668 return LoongArchISD::SRA_W;
5670 return LoongArchISD::SRL_W;
5673 return LoongArchISD::ROTR_W;
5675 return LoongArchISD::CTZ_W;
5677 return LoongArchISD::CLZ_W;
5696 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5697 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5701 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5707 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5734 StringRef ErrorMsg,
bool WithChain =
true) {
5739 Results.push_back(
N->getOperand(0));
5742template <
unsigned N>
5747 const StringRef ErrorMsgOOR =
"argument out of range";
5748 unsigned Imm =
Node->getConstantOperandVal(2);
5782 switch (
N->getConstantOperandVal(0)) {
5785 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5787 LoongArchISD::VPICK_SEXT_ELT);
5789 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5790 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5792 LoongArchISD::VPICK_SEXT_ELT);
5794 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5796 LoongArchISD::VPICK_SEXT_ELT);
5798 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5800 LoongArchISD::VPICK_ZEXT_ELT);
5802 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5803 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5805 LoongArchISD::VPICK_ZEXT_ELT);
5807 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5809 LoongArchISD::VPICK_ZEXT_ELT);
5811 case Intrinsic::loongarch_lsx_bz_b:
5812 case Intrinsic::loongarch_lsx_bz_h:
5813 case Intrinsic::loongarch_lsx_bz_w:
5814 case Intrinsic::loongarch_lsx_bz_d:
5815 case Intrinsic::loongarch_lasx_xbz_b:
5816 case Intrinsic::loongarch_lasx_xbz_h:
5817 case Intrinsic::loongarch_lasx_xbz_w:
5818 case Intrinsic::loongarch_lasx_xbz_d:
5820 LoongArchISD::VALL_ZERO);
5822 case Intrinsic::loongarch_lsx_bz_v:
5823 case Intrinsic::loongarch_lasx_xbz_v:
5825 LoongArchISD::VANY_ZERO);
5827 case Intrinsic::loongarch_lsx_bnz_b:
5828 case Intrinsic::loongarch_lsx_bnz_h:
5829 case Intrinsic::loongarch_lsx_bnz_w:
5830 case Intrinsic::loongarch_lsx_bnz_d:
5831 case Intrinsic::loongarch_lasx_xbnz_b:
5832 case Intrinsic::loongarch_lasx_xbnz_h:
5833 case Intrinsic::loongarch_lasx_xbnz_w:
5834 case Intrinsic::loongarch_lasx_xbnz_d:
5836 LoongArchISD::VALL_NONZERO);
5838 case Intrinsic::loongarch_lsx_bnz_v:
5839 case Intrinsic::loongarch_lasx_xbnz_v:
5841 LoongArchISD::VANY_NONZERO);
5849 assert(
N->getValueType(0) == MVT::i128 &&
5850 "AtomicCmpSwap on types less than 128 should be legal");
5854 switch (
MemOp->getMergedOrdering()) {
5858 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5862 Opcode = LoongArch::PseudoCmpXchg128;
5869 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5870 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5871 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5872 NewVal.first, NewVal.second,
N->getOperand(0)};
5875 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5886 EVT VT =
N->getValueType(0);
5887 switch (
N->getOpcode()) {
5892 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5893 "Unexpected custom legalisation");
5900 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5901 "Unexpected custom legalisation");
5903 Subtarget.hasDiv32() && VT == MVT::i32
5910 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5911 "Unexpected custom legalisation");
5919 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5920 "Unexpected custom legalisation");
5927 MVT VT =
N->getSimpleValueType(0);
5928 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5929 "Unexpected custom legalisation");
5931 "Unexpected type action!");
5936 Ld->getPointerInfo(), Ld->getBaseAlign(),
5937 Ld->getMemOperand()->getFlags());
5948 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5949 "Unexpected custom legalisation");
5956 if (Src.getValueType() == MVT::f16)
5967 EVT OpVT = Src.getValueType();
5971 std::tie(Result, Chain) =
5978 EVT SrcVT = Src.getValueType();
5979 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5980 Subtarget.hasBasicF()) {
5982 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5984 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5986 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5994 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5995 "Unexpected custom legalisation");
5998 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
6003 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
6004 "Unexpected custom legalisation");
6010 if (OpVT == MVT::v2f64) {
6020 assert((VT == MVT::i16 || VT == MVT::i32) &&
6021 "Unexpected custom legalization");
6022 MVT GRLenVT = Subtarget.getGRLenVT();
6029 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
6034 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
6042 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
6043 "Unexpected custom legalization");
6044 MVT GRLenVT = Subtarget.getGRLenVT();
6051 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
6054 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
6062 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
6063 "Unexpected custom legalisation");
6070 MVT GRLenVT = Subtarget.getGRLenVT();
6071 const StringRef ErrorMsgOOR =
"argument out of range";
6072 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
6073 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
6075 switch (
N->getConstantOperandVal(1)) {
6078 case Intrinsic::loongarch_movfcsr2gr: {
6079 if (!Subtarget.hasBasicF()) {
6089 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
6096#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
6097 case Intrinsic::loongarch_##NAME: { \
6098 SDValue NODE = DAG.getNode( \
6099 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6100 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
6101 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
6102 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
6103 Results.push_back(NODE.getValue(1)); \
6112#undef CRC_CASE_EXT_BINARYOP
6114#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
6115 case Intrinsic::loongarch_##NAME: { \
6116 SDValue NODE = DAG.getNode( \
6117 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6119 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
6120 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
6121 Results.push_back(NODE.getValue(1)); \
6126#undef CRC_CASE_EXT_UNARYOP
6127#define CSR_CASE(ID) \
6128 case Intrinsic::loongarch_##ID: { \
6129 if (!Subtarget.is64Bit()) \
6130 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
6138 case Intrinsic::loongarch_csrrd_w: {
6145 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
6152 case Intrinsic::loongarch_csrwr_w: {
6153 unsigned Imm =
N->getConstantOperandVal(3);
6159 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
6167 case Intrinsic::loongarch_csrxchg_w: {
6168 unsigned Imm =
N->getConstantOperandVal(4);
6174 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
6183#define IOCSRRD_CASE(NAME, NODE) \
6184 case Intrinsic::loongarch_##NAME: { \
6185 SDValue IOCSRRDResults = \
6186 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6187 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
6188 Results.push_back( \
6189 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
6190 Results.push_back(IOCSRRDResults.getValue(1)); \
6197 case Intrinsic::loongarch_cpucfg: {
6199 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
6206 case Intrinsic::loongarch_lddir_d: {
6207 if (!Subtarget.is64Bit()) {
6217 if (Subtarget.is64Bit())
6219 "On LA64, only 64-bit registers can be read.");
6222 "On LA32, only 32-bit registers can be read.");
6224 Results.push_back(
N->getOperand(0));
6235 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
6248 MVT VT =
N->getSimpleValueType(0);
6254 EVT InVT = In.getValueType();
6264 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6269 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
6272 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6281 for (
unsigned I = 0;
I < MinElts; ++
I)
6282 TruncMask[
I] = Scale *
I;
6284 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
6285 MVT SVT = In.getSimpleValueType().getScalarType();
6291 "Illegal vector type in truncation");
6303 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
6306 EVT DstVT =
N->getValueType(0);
6308 MVT SrcVT = Src.getSimpleValueType();
6326 unsigned WidenSrcElts = 128 / SrcEltBits;
6333 unsigned FirstStageEltBits = 128 / NumElts;
6337 SrcVT = FirstStageVT;
6338 SrcEltBits = FirstStageEltBits;
6346 while (SrcEltBits < DstEltBits) {
6347 unsigned NextEltBits = SrcEltBits * 2;
6350 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6369 Blocks = std::move(NextBlocks);
6370 SrcVT = NextBlockVT;
6371 SrcEltBits = NextEltBits;
6388 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6390 MVT VT =
N->getSimpleValueType(0);
6409 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6413 unsigned MinSizeInBits) {
6421 unsigned SplatBitSize;
6424 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6425 HasAnyUndefs, MinSizeInBits,
6437 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6448 unsigned EltIdx = IdxC->getZExtValue();
6450 Start = (int)EltIdx - (
int)(i * 2);
6451 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6457 else if (Src != CurSrc)
6461 if (!Src || Start < 0)
6474 unsigned Opc =
N->getOpcode();
6477 EVT VT =
N->getValueType(0);
6484 unsigned ExtOpc =
LHS.getOpcode();
6492 if (ExtOpc !=
RHS.getOpcode())
6495 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6498 unsigned OddIdx, EvenIdx;
6502 if (!LHSVec || !RHSVec)
6504 if (OddIdx != 1 || EvenIdx != 0)
6514 if (!
TLI.isTypeLegal(VT) || !
TLI.isTypeLegal(SrcVT))
6527 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6529 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6531 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6543 EVT VT =
N->getValueType(0);
6609 if (
And.getOperand(0) ==
X) {
6638 if (ShiftVal != (SplatVal + 1))
6647 : LoongArchISD::VSRAR,
6657 SDValue FirstOperand =
N->getOperand(0);
6658 SDValue SecondOperand =
N->getOperand(1);
6659 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6660 EVT ValTy =
N->getValueType(0);
6663 unsigned SMIdx, SMLen;
6728 NewOperand = FirstOperand;
6731 msb = lsb + SMLen - 1;
6735 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6749 EVT DstVT =
N.getValueType();
6758 EVT SrcVT = Src.getValueType();
6766 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6777 if (NumElts % 2 != 0)
6783 for (
unsigned I = 0;
I != NumElts; ++
I) {
6798 SrcVT = Src.getValueType();
6808 }
else if (ThisSrc != Src) {
6812 unsigned Half = NumElts / 2;
6813 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6814 ExpectedIdx += isLow ? 0 : Half;
6816 if (CI->getZExtValue() != ExpectedIdx)
6828 EVT VT =
N->getValueType(0);
6835 unsigned ExtOpc =
LHS.getOpcode();
6843 if (!
LHS.hasOneUse())
6847 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6863 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6884 SDValue FirstOperand =
N->getOperand(0);
6886 EVT ValTy =
N->getValueType(0);
6889 unsigned MaskIdx, MaskLen;
6904 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6905 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6920 EVT VT =
N->getValueType(0);
6931 if (N0C->isZero() && !
N->hasOneUse())
6937 if (
N->hasOneUse()) {
6938 unsigned UserOpc =
N->use_begin()->getUser()->getOpcode();
6946 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
6979 if (
N->getValueType(0) !=
Subtarget.getGRLenVT())
6984 EVT VT =
N->getValueType(0);
7012 switch (Src.getOpcode()) {
7015 return Src.getOperand(0).getValueSizeInBits() ==
Size;
7025 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
7038 switch (Src.getOpcode()) {
7048 Src.getOpcode(),
DL, SExtVT,
7054 DL, SExtVT, Src.getOperand(0),
7066 EVT VT =
N->getValueType(0);
7068 EVT SrcVT = Src.getValueType();
7070 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
7075 EVT CmpVT = Src.getOperand(0).getValueType();
7087 switch (Src.getOperandCondCode(2)) {
7093 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
7098 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
7103 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
7108 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
7110 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
7115 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
7117 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
7122 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
7139 EVT VT =
N->getValueType(0);
7141 EVT SrcVT = Src.getValueType();
7158 bool UseLASX =
false;
7159 bool PropagateSExt =
false;
7161 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
7162 EVT CmpVT = Src.getOperand(0).getValueType();
7171 SExtVT = MVT::v2i64;
7174 SExtVT = MVT::v4i32;
7176 SExtVT = MVT::v4i64;
7178 PropagateSExt =
true;
7182 SExtVT = MVT::v8i16;
7184 SExtVT = MVT::v8i32;
7186 PropagateSExt =
true;
7190 SExtVT = MVT::v16i8;
7192 SExtVT = MVT::v16i16;
7194 PropagateSExt =
true;
7198 SExtVT = MVT::v32i8;
7207 if (Src.getSimpleValueType() == MVT::v32i8) {
7215 }
else if (UseLASX) {
7221 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
7234 EVT ValTy =
N->getValueType(0);
7235 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
7239 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
7241 bool SwapAndRetried =
false;
7250 if (ValBits != 32 && ValBits != 64)
7265 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
7268 (MaskIdx0 + MaskLen0 <= ValBits)) {
7289 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
7290 (MaskIdx0 + MaskLen0 <= ValBits)) {
7307 (MaskIdx0 + MaskLen0 <= 64) &&
7315 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7316 : (MaskIdx0 + MaskLen0 - 1),
7332 (MaskIdx0 + MaskLen0 <= ValBits)) {
7355 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7356 : (MaskIdx0 + MaskLen0 - 1),
7371 unsigned MaskIdx, MaskLen;
7372 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
7381 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7399 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7405 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7413 if (!SwapAndRetried) {
7415 SwapAndRetried =
true;
7419 SwapAndRetried =
false;
7436 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7445 if (!SwapAndRetried) {
7447 SwapAndRetried =
true;
7456 EVT VT =
N->getValueType(0);
7463 SDValue XorOps[] = {
N->getOperand(0),
N->getOperand(1)};
7464 for (
unsigned AndIdx = 0; AndIdx != 2; ++AndIdx) {
7466 SDValue Mask = XorOps[1 - AndIdx];
7470 for (
unsigned MaskIdx = 0; MaskIdx != 2; ++MaskIdx) {
7475 if (
And.getOperand(MaskIdx) != Mask)
7488 switch (
V.getNode()->getOpcode()) {
7500 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7508 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7538 unsigned MskOpc =
LHS.getOpcode();
7539 if (MskOpc != LoongArchISD::VMSKLTZ && MskOpc != LoongArchISD::XVMSKLTZ)
7542 if (!
LHS.hasOneUse())
7546 EVT SrcVT = Src.getValueType();
7553 : LoongArchISD::VALLZERO,
7621 if (
N->getValueType(0) ==
Subtarget.getGRLenVT())
7626 SDNode *AndNode =
N->getOperand(0).getNode();
7634 SDValue CmpInputValue =
N->getOperand(1);
7643 if (!CN || !CN->
isZero())
7645 AndInputValue1 = AndInputValue1.
getOperand(0);
7649 if (AndInputValue2 != CmpInputValue)
7682 TruncInputValue1, TruncInputValue2);
7724static std::tuple<unsigned, SDValue, EVT>
7728 unsigned Opc = Inner.getOpcode();
7733 if (Inner.getOperand(0) ==
X)
7734 return {
Opc, Inner.getOperand(1), ExtVT};
7735 if (Inner.getOperand(1) ==
X)
7736 return {
Opc, Inner.getOperand(0), ExtVT};
7740 if (Inner.getOperand(0) ==
X)
7741 return {
Opc, Inner.getOperand(1), ExtVT};
7763 EVT VT =
N->getValueType(0);
7775 bool BinIsTrueArm) ->
SDValue {
7783 if (Delta.getNode() ==
N)
7805 if (
SDValue R = TryFold(TrueV, FalseV,
true))
7807 if (
SDValue R = TryFold(FalseV, TrueV,
false))
7821 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7824 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7849 LHS.getOperand(0).getValueType() ==
Subtarget.getGRLenVT()) {
7853 CCVal =
LHS.getOperandCondCode(2);
7877 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7904 unsigned Sht =
LHS.getConstantOperandVal(1);
7908 if ((EleBits + Sht) ==
Subtarget.getGRLen()) {
7918 EVT VT =
LHS.getValueType();
7943 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7944 N->getOperand(0),
V,
7949 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7950 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
7966 EVT VT =
N->getValueType(0);
7969 if (TrueV == FalseV)
8000 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
8001 {LHS, RHS, CC, TrueV, FalseV});
8006template <
unsigned N>
8010 bool IsSigned =
false) {
8014 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
8015 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
8017 ": argument out of range.");
8023template <
unsigned N>
8027 EVT ResTy =
Node->getValueType(0);
8031 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
8032 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
8034 ": argument out of range.");
8039 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
8045 EVT ResTy =
Node->getValueType(0);
8053 EVT ResTy =
Node->getValueType(0);
8062template <
unsigned N>
8065 EVT ResTy =
Node->getValueType(0);
8070 ": argument out of range.");
8080template <
unsigned N>
8083 EVT ResTy =
Node->getValueType(0);
8088 ": argument out of range.");
8097template <
unsigned N>
8100 EVT ResTy =
Node->getValueType(0);
8105 ": argument out of range.");
8114template <
unsigned W>
8117 unsigned Imm =
N->getConstantOperandVal(2);
8119 const StringRef ErrorMsg =
"argument out of range";
8121 return DAG.
getUNDEF(
N->getValueType(0));
8127 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
8135 switch (
N->getConstantOperandVal(0)) {
8138 case Intrinsic::loongarch_lsx_vadd_b:
8139 case Intrinsic::loongarch_lsx_vadd_h:
8140 case Intrinsic::loongarch_lsx_vadd_w:
8141 case Intrinsic::loongarch_lsx_vadd_d:
8142 case Intrinsic::loongarch_lasx_xvadd_b:
8143 case Intrinsic::loongarch_lasx_xvadd_h:
8144 case Intrinsic::loongarch_lasx_xvadd_w:
8145 case Intrinsic::loongarch_lasx_xvadd_d:
8148 case Intrinsic::loongarch_lsx_vaddi_bu:
8149 case Intrinsic::loongarch_lsx_vaddi_hu:
8150 case Intrinsic::loongarch_lsx_vaddi_wu:
8151 case Intrinsic::loongarch_lsx_vaddi_du:
8152 case Intrinsic::loongarch_lasx_xvaddi_bu:
8153 case Intrinsic::loongarch_lasx_xvaddi_hu:
8154 case Intrinsic::loongarch_lasx_xvaddi_wu:
8155 case Intrinsic::loongarch_lasx_xvaddi_du:
8158 case Intrinsic::loongarch_lsx_vsub_b:
8159 case Intrinsic::loongarch_lsx_vsub_h:
8160 case Intrinsic::loongarch_lsx_vsub_w:
8161 case Intrinsic::loongarch_lsx_vsub_d:
8162 case Intrinsic::loongarch_lasx_xvsub_b:
8163 case Intrinsic::loongarch_lasx_xvsub_h:
8164 case Intrinsic::loongarch_lasx_xvsub_w:
8165 case Intrinsic::loongarch_lasx_xvsub_d:
8168 case Intrinsic::loongarch_lsx_vsubi_bu:
8169 case Intrinsic::loongarch_lsx_vsubi_hu:
8170 case Intrinsic::loongarch_lsx_vsubi_wu:
8171 case Intrinsic::loongarch_lsx_vsubi_du:
8172 case Intrinsic::loongarch_lasx_xvsubi_bu:
8173 case Intrinsic::loongarch_lasx_xvsubi_hu:
8174 case Intrinsic::loongarch_lasx_xvsubi_wu:
8175 case Intrinsic::loongarch_lasx_xvsubi_du:
8178 case Intrinsic::loongarch_lsx_vneg_b:
8179 case Intrinsic::loongarch_lsx_vneg_h:
8180 case Intrinsic::loongarch_lsx_vneg_w:
8181 case Intrinsic::loongarch_lsx_vneg_d:
8182 case Intrinsic::loongarch_lasx_xvneg_b:
8183 case Intrinsic::loongarch_lasx_xvneg_h:
8184 case Intrinsic::loongarch_lasx_xvneg_w:
8185 case Intrinsic::loongarch_lasx_xvneg_d:
8189 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
8191 SDLoc(
N),
N->getValueType(0)),
8193 case Intrinsic::loongarch_lsx_vmax_b:
8194 case Intrinsic::loongarch_lsx_vmax_h:
8195 case Intrinsic::loongarch_lsx_vmax_w:
8196 case Intrinsic::loongarch_lsx_vmax_d:
8197 case Intrinsic::loongarch_lasx_xvmax_b:
8198 case Intrinsic::loongarch_lasx_xvmax_h:
8199 case Intrinsic::loongarch_lasx_xvmax_w:
8200 case Intrinsic::loongarch_lasx_xvmax_d:
8203 case Intrinsic::loongarch_lsx_vmax_bu:
8204 case Intrinsic::loongarch_lsx_vmax_hu:
8205 case Intrinsic::loongarch_lsx_vmax_wu:
8206 case Intrinsic::loongarch_lsx_vmax_du:
8207 case Intrinsic::loongarch_lasx_xvmax_bu:
8208 case Intrinsic::loongarch_lasx_xvmax_hu:
8209 case Intrinsic::loongarch_lasx_xvmax_wu:
8210 case Intrinsic::loongarch_lasx_xvmax_du:
8213 case Intrinsic::loongarch_lsx_vmaxi_b:
8214 case Intrinsic::loongarch_lsx_vmaxi_h:
8215 case Intrinsic::loongarch_lsx_vmaxi_w:
8216 case Intrinsic::loongarch_lsx_vmaxi_d:
8217 case Intrinsic::loongarch_lasx_xvmaxi_b:
8218 case Intrinsic::loongarch_lasx_xvmaxi_h:
8219 case Intrinsic::loongarch_lasx_xvmaxi_w:
8220 case Intrinsic::loongarch_lasx_xvmaxi_d:
8223 case Intrinsic::loongarch_lsx_vmaxi_bu:
8224 case Intrinsic::loongarch_lsx_vmaxi_hu:
8225 case Intrinsic::loongarch_lsx_vmaxi_wu:
8226 case Intrinsic::loongarch_lsx_vmaxi_du:
8227 case Intrinsic::loongarch_lasx_xvmaxi_bu:
8228 case Intrinsic::loongarch_lasx_xvmaxi_hu:
8229 case Intrinsic::loongarch_lasx_xvmaxi_wu:
8230 case Intrinsic::loongarch_lasx_xvmaxi_du:
8233 case Intrinsic::loongarch_lsx_vmin_b:
8234 case Intrinsic::loongarch_lsx_vmin_h:
8235 case Intrinsic::loongarch_lsx_vmin_w:
8236 case Intrinsic::loongarch_lsx_vmin_d:
8237 case Intrinsic::loongarch_lasx_xvmin_b:
8238 case Intrinsic::loongarch_lasx_xvmin_h:
8239 case Intrinsic::loongarch_lasx_xvmin_w:
8240 case Intrinsic::loongarch_lasx_xvmin_d:
8243 case Intrinsic::loongarch_lsx_vmin_bu:
8244 case Intrinsic::loongarch_lsx_vmin_hu:
8245 case Intrinsic::loongarch_lsx_vmin_wu:
8246 case Intrinsic::loongarch_lsx_vmin_du:
8247 case Intrinsic::loongarch_lasx_xvmin_bu:
8248 case Intrinsic::loongarch_lasx_xvmin_hu:
8249 case Intrinsic::loongarch_lasx_xvmin_wu:
8250 case Intrinsic::loongarch_lasx_xvmin_du:
8253 case Intrinsic::loongarch_lsx_vmini_b:
8254 case Intrinsic::loongarch_lsx_vmini_h:
8255 case Intrinsic::loongarch_lsx_vmini_w:
8256 case Intrinsic::loongarch_lsx_vmini_d:
8257 case Intrinsic::loongarch_lasx_xvmini_b:
8258 case Intrinsic::loongarch_lasx_xvmini_h:
8259 case Intrinsic::loongarch_lasx_xvmini_w:
8260 case Intrinsic::loongarch_lasx_xvmini_d:
8263 case Intrinsic::loongarch_lsx_vmini_bu:
8264 case Intrinsic::loongarch_lsx_vmini_hu:
8265 case Intrinsic::loongarch_lsx_vmini_wu:
8266 case Intrinsic::loongarch_lsx_vmini_du:
8267 case Intrinsic::loongarch_lasx_xvmini_bu:
8268 case Intrinsic::loongarch_lasx_xvmini_hu:
8269 case Intrinsic::loongarch_lasx_xvmini_wu:
8270 case Intrinsic::loongarch_lasx_xvmini_du:
8273 case Intrinsic::loongarch_lsx_vmul_b:
8274 case Intrinsic::loongarch_lsx_vmul_h:
8275 case Intrinsic::loongarch_lsx_vmul_w:
8276 case Intrinsic::loongarch_lsx_vmul_d:
8277 case Intrinsic::loongarch_lasx_xvmul_b:
8278 case Intrinsic::loongarch_lasx_xvmul_h:
8279 case Intrinsic::loongarch_lasx_xvmul_w:
8280 case Intrinsic::loongarch_lasx_xvmul_d:
8283 case Intrinsic::loongarch_lsx_vmadd_b:
8284 case Intrinsic::loongarch_lsx_vmadd_h:
8285 case Intrinsic::loongarch_lsx_vmadd_w:
8286 case Intrinsic::loongarch_lsx_vmadd_d:
8287 case Intrinsic::loongarch_lasx_xvmadd_b:
8288 case Intrinsic::loongarch_lasx_xvmadd_h:
8289 case Intrinsic::loongarch_lasx_xvmadd_w:
8290 case Intrinsic::loongarch_lasx_xvmadd_d: {
8291 EVT ResTy =
N->getValueType(0);
8296 case Intrinsic::loongarch_lsx_vmsub_b:
8297 case Intrinsic::loongarch_lsx_vmsub_h:
8298 case Intrinsic::loongarch_lsx_vmsub_w:
8299 case Intrinsic::loongarch_lsx_vmsub_d:
8300 case Intrinsic::loongarch_lasx_xvmsub_b:
8301 case Intrinsic::loongarch_lasx_xvmsub_h:
8302 case Intrinsic::loongarch_lasx_xvmsub_w:
8303 case Intrinsic::loongarch_lasx_xvmsub_d: {
8304 EVT ResTy =
N->getValueType(0);
8309 case Intrinsic::loongarch_lsx_vdiv_b:
8310 case Intrinsic::loongarch_lsx_vdiv_h:
8311 case Intrinsic::loongarch_lsx_vdiv_w:
8312 case Intrinsic::loongarch_lsx_vdiv_d:
8313 case Intrinsic::loongarch_lasx_xvdiv_b:
8314 case Intrinsic::loongarch_lasx_xvdiv_h:
8315 case Intrinsic::loongarch_lasx_xvdiv_w:
8316 case Intrinsic::loongarch_lasx_xvdiv_d:
8319 case Intrinsic::loongarch_lsx_vdiv_bu:
8320 case Intrinsic::loongarch_lsx_vdiv_hu:
8321 case Intrinsic::loongarch_lsx_vdiv_wu:
8322 case Intrinsic::loongarch_lsx_vdiv_du:
8323 case Intrinsic::loongarch_lasx_xvdiv_bu:
8324 case Intrinsic::loongarch_lasx_xvdiv_hu:
8325 case Intrinsic::loongarch_lasx_xvdiv_wu:
8326 case Intrinsic::loongarch_lasx_xvdiv_du:
8329 case Intrinsic::loongarch_lsx_vmod_b:
8330 case Intrinsic::loongarch_lsx_vmod_h:
8331 case Intrinsic::loongarch_lsx_vmod_w:
8332 case Intrinsic::loongarch_lsx_vmod_d:
8333 case Intrinsic::loongarch_lasx_xvmod_b:
8334 case Intrinsic::loongarch_lasx_xvmod_h:
8335 case Intrinsic::loongarch_lasx_xvmod_w:
8336 case Intrinsic::loongarch_lasx_xvmod_d:
8339 case Intrinsic::loongarch_lsx_vmod_bu:
8340 case Intrinsic::loongarch_lsx_vmod_hu:
8341 case Intrinsic::loongarch_lsx_vmod_wu:
8342 case Intrinsic::loongarch_lsx_vmod_du:
8343 case Intrinsic::loongarch_lasx_xvmod_bu:
8344 case Intrinsic::loongarch_lasx_xvmod_hu:
8345 case Intrinsic::loongarch_lasx_xvmod_wu:
8346 case Intrinsic::loongarch_lasx_xvmod_du:
8349 case Intrinsic::loongarch_lsx_vand_v:
8350 case Intrinsic::loongarch_lasx_xvand_v:
8353 case Intrinsic::loongarch_lsx_vor_v:
8354 case Intrinsic::loongarch_lasx_xvor_v:
8357 case Intrinsic::loongarch_lsx_vxor_v:
8358 case Intrinsic::loongarch_lasx_xvxor_v:
8361 case Intrinsic::loongarch_lsx_vnor_v:
8362 case Intrinsic::loongarch_lasx_xvnor_v: {
8367 case Intrinsic::loongarch_lsx_vandi_b:
8368 case Intrinsic::loongarch_lasx_xvandi_b:
8371 case Intrinsic::loongarch_lsx_vori_b:
8372 case Intrinsic::loongarch_lasx_xvori_b:
8375 case Intrinsic::loongarch_lsx_vxori_b:
8376 case Intrinsic::loongarch_lasx_xvxori_b:
8379 case Intrinsic::loongarch_lsx_vsll_b:
8380 case Intrinsic::loongarch_lsx_vsll_h:
8381 case Intrinsic::loongarch_lsx_vsll_w:
8382 case Intrinsic::loongarch_lsx_vsll_d:
8383 case Intrinsic::loongarch_lasx_xvsll_b:
8384 case Intrinsic::loongarch_lasx_xvsll_h:
8385 case Intrinsic::loongarch_lasx_xvsll_w:
8386 case Intrinsic::loongarch_lasx_xvsll_d:
8389 case Intrinsic::loongarch_lsx_vslli_b:
8390 case Intrinsic::loongarch_lasx_xvslli_b:
8393 case Intrinsic::loongarch_lsx_vslli_h:
8394 case Intrinsic::loongarch_lasx_xvslli_h:
8397 case Intrinsic::loongarch_lsx_vslli_w:
8398 case Intrinsic::loongarch_lasx_xvslli_w:
8401 case Intrinsic::loongarch_lsx_vslli_d:
8402 case Intrinsic::loongarch_lasx_xvslli_d:
8405 case Intrinsic::loongarch_lsx_vsrl_b:
8406 case Intrinsic::loongarch_lsx_vsrl_h:
8407 case Intrinsic::loongarch_lsx_vsrl_w:
8408 case Intrinsic::loongarch_lsx_vsrl_d:
8409 case Intrinsic::loongarch_lasx_xvsrl_b:
8410 case Intrinsic::loongarch_lasx_xvsrl_h:
8411 case Intrinsic::loongarch_lasx_xvsrl_w:
8412 case Intrinsic::loongarch_lasx_xvsrl_d:
8415 case Intrinsic::loongarch_lsx_vsrli_b:
8416 case Intrinsic::loongarch_lasx_xvsrli_b:
8419 case Intrinsic::loongarch_lsx_vsrli_h:
8420 case Intrinsic::loongarch_lasx_xvsrli_h:
8423 case Intrinsic::loongarch_lsx_vsrli_w:
8424 case Intrinsic::loongarch_lasx_xvsrli_w:
8427 case Intrinsic::loongarch_lsx_vsrli_d:
8428 case Intrinsic::loongarch_lasx_xvsrli_d:
8431 case Intrinsic::loongarch_lsx_vsra_b:
8432 case Intrinsic::loongarch_lsx_vsra_h:
8433 case Intrinsic::loongarch_lsx_vsra_w:
8434 case Intrinsic::loongarch_lsx_vsra_d:
8435 case Intrinsic::loongarch_lasx_xvsra_b:
8436 case Intrinsic::loongarch_lasx_xvsra_h:
8437 case Intrinsic::loongarch_lasx_xvsra_w:
8438 case Intrinsic::loongarch_lasx_xvsra_d:
8441 case Intrinsic::loongarch_lsx_vsrai_b:
8442 case Intrinsic::loongarch_lasx_xvsrai_b:
8445 case Intrinsic::loongarch_lsx_vsrai_h:
8446 case Intrinsic::loongarch_lasx_xvsrai_h:
8449 case Intrinsic::loongarch_lsx_vsrai_w:
8450 case Intrinsic::loongarch_lasx_xvsrai_w:
8453 case Intrinsic::loongarch_lsx_vsrai_d:
8454 case Intrinsic::loongarch_lasx_xvsrai_d:
8457 case Intrinsic::loongarch_lsx_vclz_b:
8458 case Intrinsic::loongarch_lsx_vclz_h:
8459 case Intrinsic::loongarch_lsx_vclz_w:
8460 case Intrinsic::loongarch_lsx_vclz_d:
8461 case Intrinsic::loongarch_lasx_xvclz_b:
8462 case Intrinsic::loongarch_lasx_xvclz_h:
8463 case Intrinsic::loongarch_lasx_xvclz_w:
8464 case Intrinsic::loongarch_lasx_xvclz_d:
8466 case Intrinsic::loongarch_lsx_vpcnt_b:
8467 case Intrinsic::loongarch_lsx_vpcnt_h:
8468 case Intrinsic::loongarch_lsx_vpcnt_w:
8469 case Intrinsic::loongarch_lsx_vpcnt_d:
8470 case Intrinsic::loongarch_lasx_xvpcnt_b:
8471 case Intrinsic::loongarch_lasx_xvpcnt_h:
8472 case Intrinsic::loongarch_lasx_xvpcnt_w:
8473 case Intrinsic::loongarch_lasx_xvpcnt_d:
8475 case Intrinsic::loongarch_lsx_vbitclr_b:
8476 case Intrinsic::loongarch_lsx_vbitclr_h:
8477 case Intrinsic::loongarch_lsx_vbitclr_w:
8478 case Intrinsic::loongarch_lsx_vbitclr_d:
8479 case Intrinsic::loongarch_lasx_xvbitclr_b:
8480 case Intrinsic::loongarch_lasx_xvbitclr_h:
8481 case Intrinsic::loongarch_lasx_xvbitclr_w:
8482 case Intrinsic::loongarch_lasx_xvbitclr_d:
8484 case Intrinsic::loongarch_lsx_vbitclri_b:
8485 case Intrinsic::loongarch_lasx_xvbitclri_b:
8487 case Intrinsic::loongarch_lsx_vbitclri_h:
8488 case Intrinsic::loongarch_lasx_xvbitclri_h:
8490 case Intrinsic::loongarch_lsx_vbitclri_w:
8491 case Intrinsic::loongarch_lasx_xvbitclri_w:
8493 case Intrinsic::loongarch_lsx_vbitclri_d:
8494 case Intrinsic::loongarch_lasx_xvbitclri_d:
8496 case Intrinsic::loongarch_lsx_vbitset_b:
8497 case Intrinsic::loongarch_lsx_vbitset_h:
8498 case Intrinsic::loongarch_lsx_vbitset_w:
8499 case Intrinsic::loongarch_lsx_vbitset_d:
8500 case Intrinsic::loongarch_lasx_xvbitset_b:
8501 case Intrinsic::loongarch_lasx_xvbitset_h:
8502 case Intrinsic::loongarch_lasx_xvbitset_w:
8503 case Intrinsic::loongarch_lasx_xvbitset_d: {
8504 EVT VecTy =
N->getValueType(0);
8510 case Intrinsic::loongarch_lsx_vbitseti_b:
8511 case Intrinsic::loongarch_lasx_xvbitseti_b:
8513 case Intrinsic::loongarch_lsx_vbitseti_h:
8514 case Intrinsic::loongarch_lasx_xvbitseti_h:
8516 case Intrinsic::loongarch_lsx_vbitseti_w:
8517 case Intrinsic::loongarch_lasx_xvbitseti_w:
8519 case Intrinsic::loongarch_lsx_vbitseti_d:
8520 case Intrinsic::loongarch_lasx_xvbitseti_d:
8522 case Intrinsic::loongarch_lsx_vbitrev_b:
8523 case Intrinsic::loongarch_lsx_vbitrev_h:
8524 case Intrinsic::loongarch_lsx_vbitrev_w:
8525 case Intrinsic::loongarch_lsx_vbitrev_d:
8526 case Intrinsic::loongarch_lasx_xvbitrev_b:
8527 case Intrinsic::loongarch_lasx_xvbitrev_h:
8528 case Intrinsic::loongarch_lasx_xvbitrev_w:
8529 case Intrinsic::loongarch_lasx_xvbitrev_d: {
8530 EVT VecTy =
N->getValueType(0);
8536 case Intrinsic::loongarch_lsx_vbitrevi_b:
8537 case Intrinsic::loongarch_lasx_xvbitrevi_b:
8539 case Intrinsic::loongarch_lsx_vbitrevi_h:
8540 case Intrinsic::loongarch_lasx_xvbitrevi_h:
8542 case Intrinsic::loongarch_lsx_vbitrevi_w:
8543 case Intrinsic::loongarch_lasx_xvbitrevi_w:
8545 case Intrinsic::loongarch_lsx_vbitrevi_d:
8546 case Intrinsic::loongarch_lasx_xvbitrevi_d:
8548 case Intrinsic::loongarch_lsx_vfadd_s:
8549 case Intrinsic::loongarch_lsx_vfadd_d:
8550 case Intrinsic::loongarch_lasx_xvfadd_s:
8551 case Intrinsic::loongarch_lasx_xvfadd_d:
8554 case Intrinsic::loongarch_lsx_vfsub_s:
8555 case Intrinsic::loongarch_lsx_vfsub_d:
8556 case Intrinsic::loongarch_lasx_xvfsub_s:
8557 case Intrinsic::loongarch_lasx_xvfsub_d:
8560 case Intrinsic::loongarch_lsx_vfmul_s:
8561 case Intrinsic::loongarch_lsx_vfmul_d:
8562 case Intrinsic::loongarch_lasx_xvfmul_s:
8563 case Intrinsic::loongarch_lasx_xvfmul_d:
8566 case Intrinsic::loongarch_lsx_vfdiv_s:
8567 case Intrinsic::loongarch_lsx_vfdiv_d:
8568 case Intrinsic::loongarch_lasx_xvfdiv_s:
8569 case Intrinsic::loongarch_lasx_xvfdiv_d:
8572 case Intrinsic::loongarch_lsx_vfmadd_s:
8573 case Intrinsic::loongarch_lsx_vfmadd_d:
8574 case Intrinsic::loongarch_lasx_xvfmadd_s:
8575 case Intrinsic::loongarch_lasx_xvfmadd_d:
8577 N->getOperand(2),
N->getOperand(3));
8578 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
8580 N->getOperand(1),
N->getOperand(2),
8582 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
8583 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
8585 N->getOperand(1),
N->getOperand(2),
8587 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
8588 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
8590 N->getOperand(1),
N->getOperand(2),
8592 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
8594 N->getOperand(1),
N->getOperand(2),
8596 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
8597 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
8598 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
8599 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
8600 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
8601 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
8602 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
8603 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
8604 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
8607 case Intrinsic::loongarch_lsx_vreplve_b:
8608 case Intrinsic::loongarch_lsx_vreplve_h:
8609 case Intrinsic::loongarch_lsx_vreplve_w:
8610 case Intrinsic::loongarch_lsx_vreplve_d:
8611 case Intrinsic::loongarch_lasx_xvreplve_b:
8612 case Intrinsic::loongarch_lasx_xvreplve_h:
8613 case Intrinsic::loongarch_lasx_xvreplve_w:
8614 case Intrinsic::loongarch_lasx_xvreplve_d:
8615 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
8619 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8623 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8624 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8628 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8632 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8636 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8637 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8641 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8645 case Intrinsic::loongarch_lsx_bz_b:
8646 case Intrinsic::loongarch_lsx_bz_h:
8647 case Intrinsic::loongarch_lsx_bz_w:
8648 case Intrinsic::loongarch_lsx_bz_d:
8649 case Intrinsic::loongarch_lasx_xbz_b:
8650 case Intrinsic::loongarch_lasx_xbz_h:
8651 case Intrinsic::loongarch_lasx_xbz_w:
8652 case Intrinsic::loongarch_lasx_xbz_d:
8654 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8657 case Intrinsic::loongarch_lsx_bz_v:
8658 case Intrinsic::loongarch_lasx_xbz_v:
8660 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8663 case Intrinsic::loongarch_lsx_bnz_b:
8664 case Intrinsic::loongarch_lsx_bnz_h:
8665 case Intrinsic::loongarch_lsx_bnz_w:
8666 case Intrinsic::loongarch_lsx_bnz_d:
8667 case Intrinsic::loongarch_lasx_xbnz_b:
8668 case Intrinsic::loongarch_lasx_xbnz_h:
8669 case Intrinsic::loongarch_lasx_xbnz_w:
8670 case Intrinsic::loongarch_lasx_xbnz_d:
8672 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8675 case Intrinsic::loongarch_lsx_bnz_v:
8676 case Intrinsic::loongarch_lasx_xbnz_v:
8678 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8681 case Intrinsic::loongarch_lasx_concat_128_s:
8682 case Intrinsic::loongarch_lasx_concat_128_d:
8683 case Intrinsic::loongarch_lasx_concat_128:
8685 N->getOperand(1),
N->getOperand(2));
8697 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8709 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8711 "Unexpected value type!");
8720 MVT VT =
N->getSimpleValueType(0);
8726 if (
TLI.SimplifyDemandedBits(
SDValue(
N, 0), DemandedMask, DCI))
8741 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8754 APInt V =
C->getValueAPF().bitcastToAPInt();
8769 MVT VT =
N->getSimpleValueType(0);
8847 EVT VT =
N->getValueType(0);
8849 EVT SrcVT = Src.getValueType();
8855 if (SrcEltBits >= DstEltBits)
8862 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8874 unsigned BlockBits) {
8876 MVT DstVT =
N->getSimpleValueType(0);
8878 MVT SrcVT = Src.getSimpleValueType();
8885 Src.getOperand(0).getValueType() == BlockVT) {
8886 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8888 }
else if (SrcBits > BlockBits) {
8890 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8895 BlockBits = SrcBits;
8902 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8907 if (BlockBits == 256) {
8917 if (Blocks.
size() == 1)
8927 EVT VT =
N->getValueType(0);
8929 EVT SrcVT = Src.getValueType();
8935 unsigned BlockBits =
Subtarget.hasExtLASX() ? 256 : 128;
8938 if (SrcEltBits <= DstEltBits)
8941 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8955 if (VT != MVT::f32 && VT != MVT::f64)
8957 if (VT == MVT::f32 && !
Subtarget.hasBasicF())
8959 if (VT == MVT::f64 && !
Subtarget.hasBasicD())
8991 EVT VT =
N->getValueType(0);
9012 EVT DstVT =
N->getValueType(0);
9014 EVT SrcVT = Src.getValueType();
9024 unsigned BlockBits =
Subtarget.hasExtLASX() ? 256 : 128;
9029 if (SrcBits % BlockBits != 0 && SrcBits != 128)
9032 if (DstEltBits < 32) {
9038 if (SrcEltBits != 64 || DstEltBits != 32)
9077 if (!
TLI.isOperationLegalOrPromote(
N.getOpcode(), VT))
9116 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
9126 EVT VT =
N.getValueType();
9143 switch (
N.getOpcode()) {
9159 EVT VT =
N->getValueType(0);
9167 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
9172 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
9174 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
9186 EVT VT =
N->getValueType(0);
9188 if (VT.
isVector() &&
N->getNumOperands() == 2)
9201 EVT VT =
N->getValueType(0);
9213 SDValue TrueVal =
N->getOperand(1);
9214 SDValue FalseVal =
N->getOperand(2);
9247 if (FalseVal.getOpcode() !=
ISD::ADD)
9250 SDValue Add0 = FalseVal.getOperand(0);
9251 SDValue Add1 = FalseVal.getOperand(1);
9321 : LoongArchISD::VSRAR,
9332 EVT ResTy =
N->getValueType(0);
9337 if (ResTy != MVT::v8i16 && ResTy != MVT::v4i32 && ResTy != MVT::v2i64 &&
9338 ResTy != MVT::i128 && ResTy != MVT::v16i16 && ResTy != MVT::v8i32 &&
9339 ResTy != MVT::v4i64 && ResTy != MVT::v2i128)
9341 if (HasLSXOnly && (ResTy.
is256BitVector() || ResTy == MVT::v2i128))
9354 auto getExtType = [](
unsigned Op0,
unsigned Op1) ->
int {
9372 bool IsScalar = (ResTy == MVT::i128);
9373 if (IsScalar && ExtType < 2 &&
Subtarget.is64Bit())
9386 unsigned Src0Bits = Src0.getValueType().getScalarSizeInBits();
9387 unsigned Src1Bits = Src1.getValueType().getScalarSizeInBits();
9388 if (Src0Bits != Src1Bits || ResBits != Src0Bits * 2)
9396 for (
unsigned i = 0; i < Src0.getNumOperands(); ++i)
9397 Elems.
emplace_back(Src0.getOperand(i), Src1.getOperand(i));
9403 for (
auto &[Op0, Op1] : Elems) {
9417 unsigned CurIdx = IdxC->getZExtValue();
9419 if (CurIdx != 0 && CurIdx != 1)
9421 OrigN0 = Op0.getOperand(0);
9425 if (CurIdx != Index + 2 || Op0.getOperand(0) != OrigN0 ||
9440 bool IsEven = (Index % 2 == 0);
9442 static const unsigned OpcTable[3][2] = {
9443 {LoongArchISD::VMULWOD, LoongArchISD::VMULWEV},
9444 {LoongArchISD::VMULWODU, LoongArchISD::VMULWEVU},
9445 {LoongArchISD::VMULWODUS, LoongArchISD::VMULWEVUS}};
9448 Result = DAG.
getNode(OpcTable[2][IsEven],
DL, OrigTy, OrigN1, OrigN0);
9450 Result = DAG.
getNode(OpcTable[ExtType][IsEven],
DL, OrigTy, OrigN0, OrigN1);
9460 EVT VT =
N->getValueType(0);
9462 unsigned Opc = Src.getOpcode();
9468 if (
N->hasOneUse()) {
9495 return DAG.
getNode(LoongArchISD::SLL_W,
DL, VT, Src.getOperand(0),
9502 if (!
N->hasOneUse())
9522 if (Src.hasOneUse() && Src.getOperand(0).getValueType().isInteger()) {
9532 SDLoc(
N), Src.getValueType(), Src.getOperand(0),
9584 if (
N->hasOneUse() &&
N->use_begin()->getUser()->getOpcode() ==
ISD::SUB)
9608 switch (
N->getOpcode()) {
9644 case LoongArchISD::BITREV_W:
9646 case LoongArchISD::BR_CC:
9648 case LoongArchISD::SELECT_CC:
9652 case LoongArchISD::MOVGR2FR_W_LA64:
9654 case LoongArchISD::MOVFR2GR_S_LA64:
9656 case LoongArchISD::CRC_W_B_W:
9657 case LoongArchISD::CRC_W_H_W:
9658 case LoongArchISD::CRCC_W_B_W:
9659 case LoongArchISD::CRCC_W_H_W:
9660 case LoongArchISD::VMSKLTZ:
9661 case LoongArchISD::XVMSKLTZ:
9663 case LoongArchISD::SPLIT_PAIR_F64:
9665 case LoongArchISD::VANDN:
9671 case LoongArchISD::VPACKEV:
9672 case LoongArchISD::VPERMI:
9701 MF->
insert(It, BreakMBB);
9705 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
9706 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
9718 MBB->addSuccessor(BreakMBB);
9719 MBB->addSuccessor(SinkMBB);
9725 BreakMBB->addSuccessor(SinkMBB);
9737 unsigned BroadcastOp;
9739 switch (
MI.getOpcode()) {
9742 case LoongArch::PseudoXVINSGR2VR_B:
9744 BroadcastOp = LoongArch::XVREPLGR2VR_B;
9745 InsOp = LoongArch::XVEXTRINS_B;
9747 case LoongArch::PseudoXVINSGR2VR_H:
9749 BroadcastOp = LoongArch::XVREPLGR2VR_H;
9750 InsOp = LoongArch::XVEXTRINS_H;
9762 unsigned Idx =
MI.getOperand(3).getImm();
9764 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
9766 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
9767 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
9770 .
addReg(XSrc, {}, LoongArch::sub_128);
9772 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
9773 : LoongArch::VINSGR2VR_B),
9781 .
addImm(LoongArch::sub_128);
9783 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9784 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9788 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
9791 .
addImm(Idx >= HalfSize ? 48 : 18);
9796 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
9799 MI.eraseFromParent();
9814 unsigned BroadcastOp, CTOp, PickOp;
9815 switch (
MI.getOpcode()) {
9818 case LoongArch::PseudoCTPOP_B:
9819 BroadcastOp = LoongArch::VREPLGR2VR_B;
9820 CTOp = LoongArch::VPCNT_B;
9821 PickOp = LoongArch::VPICKVE2GR_B;
9823 case LoongArch::PseudoCTPOP_H:
9824 case LoongArch::PseudoCTPOP_H_LA32:
9825 BroadcastOp = LoongArch::VREPLGR2VR_H;
9826 CTOp = LoongArch::VPCNT_H;
9827 PickOp = LoongArch::VPICKVE2GR_H;
9829 case LoongArch::PseudoCTPOP_W:
9830 case LoongArch::PseudoCTPOP_W_LA32:
9831 BroadcastOp = LoongArch::VREPLGR2VR_W;
9832 CTOp = LoongArch::VPCNT_W;
9833 PickOp = LoongArch::VPICKVE2GR_W;
9835 case LoongArch::PseudoCTPOP_D:
9836 BroadcastOp = LoongArch::VREPLGR2VR_D;
9837 CTOp = LoongArch::VPCNT_D;
9838 PickOp = LoongArch::VPICKVE2GR_D;
9842 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9843 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9848 MI.eraseFromParent();
9862 unsigned EleBits = 8;
9863 unsigned NotOpc = 0;
9866 switch (
MI.getOpcode()) {
9869 case LoongArch::PseudoVMSKLTZ_B:
9870 MskOpc = LoongArch::VMSKLTZ_B;
9872 case LoongArch::PseudoVMSKLTZ_H:
9873 MskOpc = LoongArch::VMSKLTZ_H;
9876 case LoongArch::PseudoVMSKLTZ_W:
9877 MskOpc = LoongArch::VMSKLTZ_W;
9880 case LoongArch::PseudoVMSKLTZ_D:
9881 MskOpc = LoongArch::VMSKLTZ_D;
9884 case LoongArch::PseudoVMSKGEZ_B:
9885 MskOpc = LoongArch::VMSKGEZ_B;
9887 case LoongArch::PseudoVMSKEQZ_B:
9888 MskOpc = LoongArch::VMSKNZ_B;
9889 NotOpc = LoongArch::VNOR_V;
9891 case LoongArch::PseudoVMSKNEZ_B:
9892 MskOpc = LoongArch::VMSKNZ_B;
9894 case LoongArch::PseudoXVMSKLTZ_B:
9895 MskOpc = LoongArch::XVMSKLTZ_B;
9896 RC = &LoongArch::LASX256RegClass;
9898 case LoongArch::PseudoXVMSKLTZ_H:
9899 MskOpc = LoongArch::XVMSKLTZ_H;
9900 RC = &LoongArch::LASX256RegClass;
9903 case LoongArch::PseudoXVMSKLTZ_W:
9904 MskOpc = LoongArch::XVMSKLTZ_W;
9905 RC = &LoongArch::LASX256RegClass;
9908 case LoongArch::PseudoXVMSKLTZ_D:
9909 MskOpc = LoongArch::XVMSKLTZ_D;
9910 RC = &LoongArch::LASX256RegClass;
9913 case LoongArch::PseudoXVMSKGEZ_B:
9914 MskOpc = LoongArch::XVMSKGEZ_B;
9915 RC = &LoongArch::LASX256RegClass;
9917 case LoongArch::PseudoXVMSKEQZ_B:
9918 MskOpc = LoongArch::XVMSKNZ_B;
9919 NotOpc = LoongArch::XVNOR_V;
9920 RC = &LoongArch::LASX256RegClass;
9922 case LoongArch::PseudoXVMSKNEZ_B:
9923 MskOpc = LoongArch::XVMSKNZ_B;
9924 RC = &LoongArch::LASX256RegClass;
9937 if (
TRI->getRegSizeInBits(*RC) > 128) {
9938 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9939 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9948 : LoongArch::BSTRINS_W),
9952 .
addImm(256 / EleBits - 1)
9960 MI.eraseFromParent();
9967 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9968 "Unexpected instruction");
9980 MI.eraseFromParent();
9987 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9988 "Unexpected instruction");
9994 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
10004 MI.eraseFromParent();
10009 switch (
MI.getOpcode()) {
10012 case LoongArch::Select_GPR_Using_CC_GPR:
10048 if (
MI.getOperand(2).isReg())
10049 RHS =
MI.getOperand(2).getReg();
10050 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
10054 SelectDests.
insert(
MI.getOperand(0).getReg());
10058 SequenceMBBI !=
E; ++SequenceMBBI) {
10059 if (SequenceMBBI->isDebugInstr())
10062 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
10063 !SequenceMBBI->getOperand(2).isReg() ||
10064 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
10065 SequenceMBBI->getOperand(3).getImm() !=
CC ||
10066 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
10067 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
10069 LastSelectPseudo = &*SequenceMBBI;
10071 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
10074 if (SequenceMBBI->hasUnmodeledSideEffects() ||
10075 SequenceMBBI->mayLoadOrStore() ||
10076 SequenceMBBI->usesCustomInsertionHook())
10079 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
10094 F->insert(
I, IfFalseMBB);
10095 F->insert(
I, TailMBB);
10098 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
10104 TailMBB->
push_back(DebugInstr->removeFromParent());
10108 TailMBB->
splice(TailMBB->
end(), HeadMBB,
10118 if (
MI.getOperand(2).isImm())
10121 .
addImm(
MI.getOperand(2).getImm())
10130 auto SelectMBBI =
MI.getIterator();
10131 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
10133 while (SelectMBBI != SelectEnd) {
10134 auto Next = std::next(SelectMBBI);
10138 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
10139 .
addReg(SelectMBBI->getOperand(4).getReg())
10141 .
addReg(SelectMBBI->getOperand(5).getReg())
10148 F->getProperties().resetNoPHIs();
10154 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
10157 switch (
MI.getOpcode()) {
10160 case LoongArch::DIV_W:
10161 case LoongArch::DIV_WU:
10162 case LoongArch::MOD_W:
10163 case LoongArch::MOD_WU:
10164 case LoongArch::DIV_D:
10165 case LoongArch::DIV_DU:
10166 case LoongArch::MOD_D:
10167 case LoongArch::MOD_DU:
10170 case LoongArch::WRFCSR: {
10172 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
10173 .
addReg(
MI.getOperand(1).getReg());
10174 MI.eraseFromParent();
10177 case LoongArch::RDFCSR: {
10178 MachineInstr *ReadFCSR =
10180 MI.getOperand(0).getReg())
10181 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
10183 MI.eraseFromParent();
10186 case LoongArch::Select_GPR_Using_CC_GPR:
10188 case LoongArch::BuildPairF64Pseudo:
10190 case LoongArch::SplitPairF64Pseudo:
10192 case LoongArch::PseudoXVINSGR2VR_B:
10193 case LoongArch::PseudoXVINSGR2VR_H:
10195 case LoongArch::PseudoCTPOP_B:
10196 case LoongArch::PseudoCTPOP_H:
10197 case LoongArch::PseudoCTPOP_W:
10198 case LoongArch::PseudoCTPOP_D:
10199 case LoongArch::PseudoCTPOP_H_LA32:
10200 case LoongArch::PseudoCTPOP_W_LA32:
10202 case LoongArch::PseudoVMSKLTZ_B:
10203 case LoongArch::PseudoVMSKLTZ_H:
10204 case LoongArch::PseudoVMSKLTZ_W:
10205 case LoongArch::PseudoVMSKLTZ_D:
10206 case LoongArch::PseudoVMSKGEZ_B:
10207 case LoongArch::PseudoVMSKEQZ_B:
10208 case LoongArch::PseudoVMSKNEZ_B:
10209 case LoongArch::PseudoXVMSKLTZ_B:
10210 case LoongArch::PseudoXVMSKLTZ_H:
10211 case LoongArch::PseudoXVMSKLTZ_W:
10212 case LoongArch::PseudoXVMSKLTZ_D:
10213 case LoongArch::PseudoXVMSKGEZ_B:
10214 case LoongArch::PseudoXVMSKEQZ_B:
10215 case LoongArch::PseudoXVMSKNEZ_B:
10217 case TargetOpcode::STATEPOINT:
10223 MI.addOperand(*
MI.getMF(),
10225 LoongArch::R1,
true,
10228 if (!Subtarget.is64Bit())
10231 case LoongArch::PROBED_STACKALLOC_DYN:
10238 unsigned *
Fast)
const {
10239 if (!Subtarget.hasUAL())
10257 LoongArch::R7, LoongArch::R8, LoongArch::R9,
10258 LoongArch::R10, LoongArch::R11};
10273 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
10274 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
10275 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
10276 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
10277 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
10278 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
10284 LoongArch::F3, LoongArch::F4, LoongArch::F5,
10285 LoongArch::F6, LoongArch::F7};
10288 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
10289 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
10292 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
10293 LoongArch::VR6, LoongArch::VR7};
10296 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
10297 LoongArch::XR6, LoongArch::XR7};
10300 switch (State.getCallingConv()) {
10302 if (!State.isVarArg())
10306 return State.AllocateReg(
ArgGPRs);
10314 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
10316 unsigned GRLenInBytes = GRLen / 8;
10327 State.AllocateStack(GRLenInBytes, StackAlign),
10330 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
10341 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
10349 unsigned ValNo,
MVT ValVT,
10352 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
10353 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
10354 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
10359 if (IsRet && ValNo > 1)
10363 bool UseGPRForFloat =
true;
10373 UseGPRForFloat = ArgFlags.
isVarArg();
10386 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
10389 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
10390 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
10392 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
10398 State.getPendingArgFlags();
10401 "PendingLocs and PendingArgFlags out of sync");
10405 UseGPRForFloat =
true;
10407 if (UseGPRForFloat && ValVT == MVT::f32) {
10410 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
10413 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
10416 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
10458 PendingLocs.
size() <= 2) {
10459 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
10464 PendingLocs.
clear();
10465 PendingArgFlags.
clear();
10472 unsigned StoreSizeBytes = GRLen / 8;
10475 if (ValVT == MVT::f32 && !UseGPRForFloat) {
10477 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
10481 UseGPRForFloat =
false;
10482 StoreSizeBytes = 16;
10483 StackAlign =
Align(16);
10486 UseGPRForFloat =
false;
10487 StoreSizeBytes = 32;
10488 StackAlign =
Align(32);
10494 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
10498 if (!PendingLocs.
empty()) {
10500 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
10501 for (
auto &It : PendingLocs) {
10503 It.convertToReg(
Reg);
10508 PendingLocs.clear();
10509 PendingArgFlags.
clear();
10512 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
10513 "Expected an GRLenVT at this stage");
10530void LoongArchTargetLowering::analyzeInputArgs(
10533 LoongArchCCAssignFn Fn)
const {
10535 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
10536 MVT ArgVT = Ins[i].VT;
10537 Type *ArgTy =
nullptr;
10539 ArgTy = FType->getReturnType();
10540 else if (Ins[i].isOrigArg())
10541 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
10545 CCInfo, IsRet, ArgTy)) {
10546 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
10553void LoongArchTargetLowering::analyzeOutputArgs(
10556 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
10557 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10558 MVT ArgVT = Outs[i].VT;
10559 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
10563 CCInfo, IsRet, OrigTy)) {
10564 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
10583 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
10605 if (In.isOrigArg()) {
10610 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
10611 (
BitWidth < 32 && In.Flags.isZExt())) {
10661 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10674 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10678 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
10692 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
10704 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
10708 LoongArch::R23, LoongArch::R24, LoongArch::R25,
10709 LoongArch::R26, LoongArch::R27, LoongArch::R28,
10710 LoongArch::R29, LoongArch::R30, LoongArch::R31};
10717 if (LocVT == MVT::f32) {
10720 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
10721 LoongArch::F26, LoongArch::F27};
10728 if (LocVT == MVT::f64) {
10731 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
10732 LoongArch::F30_64, LoongArch::F31_64};
10751 switch (CallConv) {
10763 "GHC calling convention requires the F and D extensions");
10768 MVT GRLenVT = Subtarget.getGRLenVT();
10769 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
10778 return CI->isMustTailCall();
10783 std::vector<SDValue> OutChains;
10792 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
10794 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10811 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10820 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10821 assert(ArgPartOffset == 0);
10822 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10824 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10848 int VaArgOffset, VarArgsSaveSize;
10852 if (ArgRegs.
size() == Idx) {
10854 VarArgsSaveSize = 0;
10856 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10857 VaArgOffset = -VarArgsSaveSize;
10863 LoongArchFI->setVarArgsFrameIndex(FI);
10871 VarArgsSaveSize += GRLenInBytes;
10876 for (
unsigned I = Idx;
I < ArgRegs.
size();
10877 ++
I, VaArgOffset += GRLenInBytes) {
10878 const Register Reg = RegInfo.createVirtualRegister(RC);
10879 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10887 ->setValue((
Value *)
nullptr);
10888 OutChains.push_back(
Store);
10890 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10895 if (!OutChains.empty()) {
10896 OutChains.push_back(Chain);
10911 if (
N->getNumValues() != 1)
10913 if (!
N->hasNUsesOfValue(1, 0))
10916 SDNode *Copy = *
N->user_begin();
10922 if (Copy->getGluedNode())
10926 bool HasRet =
false;
10928 if (
Node->getOpcode() != LoongArchISD::RET)
10936 Chain = Copy->getOperand(0);
10941bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10945 auto CalleeCC = CLI.CallConv;
10946 auto &Outs = CLI.Outs;
10948 auto CallerCC = Caller.getCallingConv();
10950 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10959 for (
auto &Arg : Outs)
10960 if (Arg.Flags.isByVal())
10976 for (
auto &VA : ArgLocs)
10982 auto IsCallerStructRet = Caller.hasStructRetAttr();
10983 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10984 if (IsCallerStructRet || IsCalleeStructRet)
10989 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10990 if (CalleeCC != CallerCC) {
10991 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10992 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
11018 MVT GRLenVT = Subtarget.getGRLenVT();
11030 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
11034 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
11040 "site marked musttail");
11047 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
11049 if (!Flags.isByVal())
11053 unsigned Size = Flags.getByValSize();
11054 Align Alignment = Flags.getNonZeroByValAlign();
11061 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
11063 false,
nullptr, std::nullopt,
11075 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
11078 SDValue ArgValue = OutVals[OutIdx];
11086 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
11087 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
11099 if (!StackPtr.getNode())
11111 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
11125 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
11145 const Argument *FormalArg =
nullptr;
11146 unsigned FilteredIdx = 0;
11147 for (
const auto &CallArg : CLI.
CB->
args()) {
11148 if (CallArg->getType()->isEmptyTy())
11150 if (FilteredIdx == CallArgIdx) {
11159 unsigned FormalArgIdx = CallArgIdx;
11161 FormalArgIdx = FormalArg->
getArgNo();
11165 if (Arg.getType()->isEmptyTy())
11167 if (FilteredIdx == CallArgIdx) {
11168 FormalArgIdx = Arg.getArgNo();
11181 SDValue IncomingPtr = CopyOp;
11198 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
11199 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
11200 SDValue PartValue = OutVals[OutIdx + 1];
11201 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
11212 ArgValue = IncomingPtr;
11216 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
11228 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
11229 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
11230 assert(ArgPartOffset == 0);
11235 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
11236 SDValue PartValue = OutVals[OutIdx + 1];
11237 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
11249 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
11251 for (
const auto &Part : Parts) {
11252 SDValue PartValue = Part.first;
11253 SDValue PartOffset = Part.second;
11260 ArgValue = SpillSlot;
11267 if (Flags.isByVal())
11268 ArgValue = ByValArgs[j++];
11276 "Tail call not allowed if stack is used for passing parameters");
11279 if (!StackPtr.getNode())
11292 if (!MemOpChains.
empty())
11298 for (
auto &Reg : RegsToPass) {
11299 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
11321 Ops.push_back(Chain);
11322 Ops.push_back(Callee);
11326 for (
auto &Reg : RegsToPass)
11327 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
11332 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
11333 assert(Mask &&
"Missing call preserved mask for calling convention");
11339 Ops.push_back(Glue);
11348 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
11351 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
11354 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
11355 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
11377 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
11380 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
11381 auto &VA = RVLocs[i];
11389 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
11390 assert(VA.needsCustom());
11395 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
11396 RetValue, RetValue2);
11409 const Type *RetTy)
const {
11411 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
11413 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
11417 Outs[i].Flags, CCInfo,
true,
nullptr))
11443 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
11444 SDValue Val = OutVals[OutIdx];
11453 DAG.
getVTList(MVT::i32, MVT::i32), Val);
11457 Register RegHi = RVLocs[++i].getLocReg();
11482 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
11490 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
11491 uint64_t RequiredImm = 0;
11493 if (SplatBitSize == 16 && !(V & 0x00FF)) {
11495 RequiredImm = (0b10101 << 8) | (V >> 8);
11496 return {
true, RequiredImm};
11497 }
else if (SplatBitSize == 32) {
11499 if (!(V & 0xFFFF00FF)) {
11500 RequiredImm = (0b10001 << 8) | (V >> 8);
11501 return {
true, RequiredImm};
11504 if (!(V & 0xFF00FFFF)) {
11505 RequiredImm = (0b10010 << 8) | (V >> 16);
11506 return {
true, RequiredImm};
11509 if (!(V & 0x00FFFFFF)) {
11510 RequiredImm = (0b10011 << 8) | (V >> 24);
11511 return {
true, RequiredImm};
11514 if ((V & 0xFFFF00FF) == 0xFF) {
11515 RequiredImm = (0b10110 << 8) | (V >> 8);
11516 return {
true, RequiredImm};
11519 if ((V & 0xFF00FFFF) == 0xFFFF) {
11520 RequiredImm = (0b10111 << 8) | (V >> 16);
11521 return {
true, RequiredImm};
11524 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
11526 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11527 return {
true, RequiredImm};
11529 }
else if (SplatBitSize == 64) {
11531 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
11532 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
11534 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11535 return {
true, RequiredImm};
11538 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
11539 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
11541 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
11542 return {
true, RequiredImm};
11545 auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {
11547 for (
int i = 0; i < 8; ++i) {
11549 if (
byte == 0 ||
byte == 0xFF)
11550 res |= ((
byte & 1) << i);
11555 return {
true, res};
11557 auto [IsSame, Suffix] = sameBitsPreByte(V);
11559 RequiredImm = (0b11001 << 8) | Suffix;
11560 return {
true, RequiredImm};
11563 return {
false, RequiredImm};
11568 if (!Subtarget.hasExtLSX())
11571 if (VT == MVT::f32) {
11572 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
11573 return (masked == 0x3e000000 || masked == 0x40000000);
11576 if (VT == MVT::f64) {
11577 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
11578 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
11587bool LoongArchTargetLowering::shouldConvertFpToSat(
unsigned Op,
EVT FPVT,
11593 if (FPVT == MVT::f32)
11595 return FPVT == MVT::f64 &&
Subtarget.hasBasicD();
11599LoongArchTargetLowering::getFPImmAction(
const APFloat &
Imm,
EVT VT,
11600 bool ForCodeSize)
const {
11602 if (VT == MVT::f32 && !
Subtarget.hasBasicF())
11604 if (VT == MVT::f64 && !
Subtarget.hasBasicD())
11622 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
11634bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
11644 Type *Ty =
I->getOperand(0)->getType();
11646 unsigned Size = Ty->getIntegerBitWidth();
11666 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
11671 if (Subtarget.hasExtLASX())
11673 else if (Subtarget.hasExtLSX())
11680 EVT VT =
Y.getValueType();
11683 return Subtarget.hasExtLSX() && VT.
isInteger();
11694 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
11695 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
11696 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
11697 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
11700 Info.memVT = MVT::i32;
11701 Info.ptrVal =
I.getArgOperand(0);
11703 Info.align =
Align(4);
11722 "Unable to expand");
11723 unsigned MinWordSize = 4;
11735 Value *AlignedAddr = Builder.CreateIntrinsic(
11736 Intrinsic::ptrmask, {PtrTy, IntTy},
11737 {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))},
nullptr,
11740 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
11741 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
11742 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
11743 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
11744 Value *Mask = Builder.CreateShl(
11745 ConstantInt::get(WordType,
11746 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
11748 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
11749 Value *ValOperand_Shifted =
11750 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
11751 ShiftAmt,
"ValOperand_Shifted");
11754 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
11756 NewOperand = ValOperand_Shifted;
11759 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
11762 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
11763 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
11764 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
11783 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
11791 if (Subtarget.hasLAMCAS()) {
11813 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
11815 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
11817 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
11819 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
11821 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
11823 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
11825 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
11827 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11837 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11839 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11841 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11843 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11845 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11847 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11849 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11851 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11863 if (Subtarget.hasLAMCAS())
11875 unsigned GRLen = Subtarget.getGRLen();
11877 Value *FailureOrdering =
11878 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t
>(FailOrd));
11879 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11881 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11882 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11883 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11884 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11887 Value *Result = Builder.CreateIntrinsic(
11888 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11890 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11906 Builder.CreateNot(Mask,
"Inv_Mask"),
11913 unsigned GRLen = Subtarget.getGRLen();
11915 Builder.getIntN(GRLen,
static_cast<uint64_t
>(AI->
getOrdering()));
11922 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11923 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11924 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11937 unsigned ValWidth =
11940 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11941 Result = Builder.CreateCall(LlwOpScwLoop,
11942 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11945 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11949 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11973 return LoongArch::R4;
11978 return LoongArch::R5;
11989 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11990 return RefinementSteps;
11996 "Reciprocal estimate queried on unsupported target");
12024 int &RefinementSteps,
12025 bool &UseOneConstNR,
12026 bool Reciprocal)
const {
12028 "Enabled should never be Disabled here");
12030 if (!Subtarget.hasFrecipe())
12045 UseOneConstNR =
false;
12051 if (Reciprocal || RefinementSteps > 0)
12061 int &RefinementSteps)
const {
12063 "Enabled should never be Disabled here");
12065 if (!Subtarget.hasFrecipe())
12079 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
12087LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
12107 if (Constraint.
size() == 1) {
12108 switch (Constraint[0]) {
12124 if (Constraint ==
"ZC" || Constraint ==
"ZB")
12133 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
12140std::pair<unsigned, const TargetRegisterClass *>
12141LoongArchTargetLowering::getRegForInlineAsmConstraint(
12145 if (Constraint.
size() == 1) {
12146 switch (Constraint[0]) {
12151 return std::make_pair(0U, &LoongArch::GPRRegClass);
12153 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
12155 if (Subtarget.hasBasicF() && VT == MVT::f32)
12156 return std::make_pair(0U, &LoongArch::FPR32RegClass);
12157 if (Subtarget.hasBasicD() && VT == MVT::f64)
12158 return std::make_pair(0U, &LoongArch::FPR64RegClass);
12159 if (Subtarget.hasExtLSX() &&
12160 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
12161 return std::make_pair(0U, &LoongArch::LSX128RegClass);
12162 if (Subtarget.hasExtLSX() && VT == MVT::i128)
12163 return std::make_pair(0U, &LoongArch::LSX128RegClass);
12164 if (Subtarget.hasExtLASX() &&
12165 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
12166 return std::make_pair(0U, &LoongArch::LASX256RegClass);
12186 bool IsFP = Constraint[2] ==
'f';
12187 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
12188 std::pair<unsigned, const TargetRegisterClass *>
R;
12193 unsigned RegNo =
R.first;
12194 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
12195 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
12196 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
12197 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
12207void LoongArchTargetLowering::LowerAsmOperandForConstraint(
12211 if (Constraint.
size() == 1) {
12212 switch (Constraint[0]) {
12219 Subtarget.getGRLenVT()));
12228 Subtarget.getGRLenVT()));
12234 if (
C->getZExtValue() == 0)
12254#define GET_REGISTER_MATCHER
12255#include "LoongArchGenAsmMatcher.inc"
12261 std::string NewRegName = Name.second.str();
12267 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
12268 if (!ReservedRegs.
test(Reg))
12285 const APInt &
Imm = ConstNode->getAPIntValue();
12287 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2() ||
12288 (1 -
Imm).isPowerOf2() || (-1 -
Imm).isPowerOf2())
12291 if (ConstNode->hasOneUse() &&
12292 ((
Imm - 2).isPowerOf2() || (
Imm - 4).isPowerOf2() ||
12293 (
Imm - 8).isPowerOf2() || (
Imm - 16).isPowerOf2()))
12299 if (ConstNode->hasOneUse() && !(
Imm.sge(-2048) &&
Imm.sle(4095))) {
12300 unsigned Shifts =
Imm.countr_zero();
12307 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
12311 APInt ImmSmall =
APInt(
Imm.getBitWidth(), 1ULL << Shifts,
true);
12312 if ((
Imm - ImmSmall).isPowerOf2() || (
Imm + ImmSmall).isPowerOf2() ||
12313 (ImmSmall -
Imm).isPowerOf2())
12323 Type *Ty,
unsigned AS,
12342 switch (AM.
Scale) {
12378 EVT MemVT = LD->getMemoryVT();
12379 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
12390 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
12399 if (
Y.getValueType().isVector())
12411 Type *Ty,
bool IsSigned)
const {
12412 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
12421 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
12422 Type.getSizeInBits() < Subtarget.getGRLen()))
12432 Align &PrefAlign)
const {
12436 if (Subtarget.is64Bit()) {
12438 PrefAlign =
Align(8);
12441 PrefAlign =
Align(4);
12456bool LoongArchTargetLowering::splitValueIntoRegisterParts(
12458 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
12459 bool IsABIRegCopy =
CC.has_value();
12462 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
12463 PartVT == MVT::f32) {
12478SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
12480 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
12481 bool IsABIRegCopy =
CC.has_value();
12483 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
12484 PartVT == MVT::f32) {
12501 if (VT == MVT::f16 && Subtarget.hasBasicF())
12507unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
12510 if (VT == MVT::f16 && Subtarget.hasBasicF())
12519 unsigned Opc =
Op.getOpcode();
12524 case LoongArchISD::VANYNONZERO:
12525 case LoongArchISD::VALLZERO:
12526 case LoongArchISD::VALL_ZERO:
12527 case LoongArchISD::VANY_ZERO:
12528 case LoongArchISD::VALL_NONZERO:
12529 case LoongArchISD::VANY_NONZERO: {
12531 Known.Zero.setBitsFrom(1);
12534 case LoongArchISD::VPICK_ZEXT_ELT: {
12538 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
12539 Known.Zero.setBitsFrom(VTBits);
12542 case LoongArchISD::BSTRINS: {
12544 unsigned Msb =
Op.getConstantOperandVal(2);
12545 unsigned Lsb =
Op.getConstantOperandVal(3);
12548 Known.insertBits(Known2.
trunc(Msb - Lsb + 1), Lsb);
12551 case LoongArchISD::BSTRPICK: {
12554 unsigned Msb =
Op.getConstantOperandVal(1);
12555 unsigned Lsb =
Op.getConstantOperandVal(2);
12565 unsigned Depth)
const {
12566 switch (
Op.getOpcode()) {
12569 case LoongArchISD::BSTRINS: {
12570 unsigned BitWidth =
Op.getScalarValueSizeInBits();
12571 unsigned Msb =
Op.getConstantOperandVal(2);
12572 unsigned Lsb =
Op.getConstantOperandVal(3);
12576 return std::min(Tmp,
BitWidth - 1 - Msb);
12580 return Tmp > Lsb ? Tmp - Lsb : 1;
12589 unsigned Depth)
const {
12590 EVT VT =
Op.getValueType();
12592 unsigned Opc =
Op.getOpcode();
12596 case LoongArchISD::CRC_W_B_W:
12597 case LoongArchISD::CRC_W_H_W:
12598 case LoongArchISD::CRCC_W_B_W:
12599 case LoongArchISD::CRCC_W_H_W: {
12601 APInt DemandedSrcBits =
12603 Opc == LoongArchISD::CRCC_W_B_W)
12607 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
12609 case LoongArchISD::VMSKLTZ:
12610 case LoongArchISD::XVMSKLTZ: {
12612 MVT SrcVT = Src.getSimpleValueType();
12617 if (OriginalDemandedBits.
countr_zero() >= NumElts)
12621 APInt KnownUndef, KnownZero;
12637 if (KnownSrc.
One[SrcBits - 1])
12638 Known.One.setLowBits(NumElts);
12639 else if (KnownSrc.
Zero[SrcBits - 1])
12640 Known.Zero.setLowBits(NumElts);
12644 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
12651 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
12675 unsigned Index)
const {
12686 unsigned Index)
const {
12690 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
12705 Align StackAlign)
const {
12709 unsigned StackProbeSize =
12713 return StackProbeSize ? StackProbeSize : StackAlign.
value();
12717LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
12731 const EVT VT =
Op.getValueType();
12742 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
12752 const Register TargetReg =
MI.getOperand(0).getReg();
12755 const bool IsLA64 = Subtarget.is64Bit();
12756 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
12758 const uint64_t ProbeSize =
TLI->getStackProbeSize(MF, StackAlign);
12763 MF.
insert(MBBInsertPoint, LoopTestMBB);
12766 MF.
insert(MBBInsertPoint, ExitMBB);
12777 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
12783 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
12789 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
12804 MBB->addSuccessor(LoopTestMBB);
12806 MI.eraseFromParent();
12808 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 performXORCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
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 performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
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 combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
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 performMULCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
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.
bool isOne() const
Determine if this is a value of 1.
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.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
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)
reference emplace_back(ArgTypes &&... Args)
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)
Value * getOperand(unsigned i) const
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 isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
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.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
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.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
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.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
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
bool isAfterLegalizeDAG() const
bool isBeforeLegalize() 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)