32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
248 if (Subtarget.is64Bit())
251 if (!Subtarget.hasBasicD()) {
253 if (Subtarget.is64Bit()) {
262 if (Subtarget.hasBasicD()) {
295 if (Subtarget.is64Bit())
301 if (Subtarget.hasExtLSX()) {
316 for (
MVT VT : LSXVTs) {
330 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
358 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
360 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
362 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
366 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
390 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
391 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
406 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
408 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
415 if (Subtarget.hasExtLASX()) {
416 for (
MVT VT : LASXVTs) {
431 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
460 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
462 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
464 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
468 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
487 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
492 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
499 if (Subtarget.hasBasicF()) {
510 if (Subtarget.hasExtLSX()) {
522 if (Subtarget.hasExtLASX()) {
549 if (Subtarget.hasLAMCAS())
552 if (Subtarget.hasSCQ()) {
572 switch (
Op.getOpcode()) {
574 return lowerATOMIC_FENCE(
Op, DAG);
576 return lowerEH_DWARF_CFA(
Op, DAG);
578 return lowerGlobalAddress(
Op, DAG);
580 return lowerGlobalTLSAddress(
Op, DAG);
582 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
584 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
586 return lowerINTRINSIC_VOID(
Op, DAG);
588 return lowerBlockAddress(
Op, DAG);
590 return lowerJumpTable(
Op, DAG);
592 return lowerShiftLeftParts(
Op, DAG);
594 return lowerShiftRightParts(
Op, DAG,
true);
596 return lowerShiftRightParts(
Op, DAG,
false);
598 return lowerConstantPool(
Op, DAG);
600 return lowerFP_TO_SINT(
Op, DAG);
602 return lowerBITCAST(
Op, DAG);
604 return lowerUINT_TO_FP(
Op, DAG);
606 return lowerSINT_TO_FP(
Op, DAG);
608 return lowerVASTART(
Op, DAG);
610 return lowerFRAMEADDR(
Op, DAG);
612 return lowerRETURNADDR(
Op, DAG);
614 return lowerWRITE_REGISTER(
Op, DAG);
616 return lowerINSERT_VECTOR_ELT(
Op, DAG);
618 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
620 return lowerBUILD_VECTOR(
Op, DAG);
622 return lowerCONCAT_VECTORS(
Op, DAG);
624 return lowerVECTOR_SHUFFLE(
Op, DAG);
626 return lowerBITREVERSE(
Op, DAG);
628 return lowerSCALAR_TO_VECTOR(
Op, DAG);
630 return lowerPREFETCH(
Op, DAG);
632 return lowerSELECT(
Op, DAG);
634 return lowerBRCOND(
Op, DAG);
636 return lowerFP_TO_FP16(
Op, DAG);
638 return lowerFP16_TO_FP(
Op, DAG);
640 return lowerFP_TO_BF16(
Op, DAG);
642 return lowerBF16_TO_FP(
Op, DAG);
644 return lowerVECREDUCE_ADD(
Op, DAG);
647 return lowerRotate(
Op, DAG);
655 return lowerVECREDUCE(
Op, DAG);
657 return lowerConstantFP(
Op, DAG);
659 return lowerSETCC(
Op, DAG);
661 return lowerFP_ROUND(
Op, DAG);
663 return lowerFP_EXTEND(
Op, DAG);
665 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
667 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
676 EVT VT = V.getValueType();
682 return V.getOperand(0);
686 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
688 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
698 if (!V->isOnlyUserOf(SplatValue.getNode()))
702 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
710 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
738 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
739 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
746 if (Opcode0 != Opcode1)
749 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
756 EVT VT =
N.getValueType();
770 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
771 SSVT0 == MVT::v4f64) {
790 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
791 N->getOpcode() == LoongArchISD::VPERMI) &&
792 Opcode0 == LoongArchISD::VFCVT) {
797 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
800 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
801 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
807 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
823 MVT VT =
Op.getSimpleValueType();
824 MVT SVT =
In.getSimpleValueType();
826 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
839 EVT VT =
Op.getValueType();
841 EVT SVT = Src.getValueType();
844 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
846 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
847 if (!V2F32ToV2F64 && !V4F32ToV4F64)
859 const uint64_t
Imm =
Op.getConstantOperandVal(1);
874 if (
SDValue V = CheckVecHighPart(Src)) {
876 "Unexpected wide vector");
877 Opcode = LoongArchISD::VFCVTH;
880 Opcode = LoongArchISD::VFCVTL;
882 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
887 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
893 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
905 EVT VT =
Op.getValueType();
910 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
911 (VT == MVT::f64 && Subtarget.hasBasicD()));
928 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
938 if (Subtarget.is64Bit())
940 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
941 : LoongArchISD::MOVGR2FR_W,
945 if (Subtarget.is64Bit()) {
947 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
951 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
963 EVT ResultVT =
Op.getValueType();
964 EVT OperandVT =
Op.getOperand(0).getValueType();
969 if (ResultVT == SetCCResultVT)
972 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
973 "SETCC operands must have the same type!");
977 Op.getOperand(1),
Op.getOperand(2));
979 if (ResultVT.
bitsGT(SetCCResultVT))
981 else if (ResultVT.
bitsLT(SetCCResultVT))
993SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
997 MVT SrcVT = Src.getSimpleValueType();
998 MVT DstVT =
Op.getSimpleValueType();
1009 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1029 MVT OpVT =
Op.getSimpleValueType();
1036 unsigned LegalVecSize = 128;
1037 bool isLASX256Vector =
1047 if (isLASX256Vector) {
1053 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1054 EleBits = std::min(EleBits, 64u);
1057 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1060 if (isLASX256Vector) {
1086 MVT OpVT =
Op.getSimpleValueType();
1099 MVT GRLenVT = Subtarget.getGRLenVT();
1101 for (
int i = NumEles; i > 1; i /= 2) {
1104 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1113 unsigned IsData =
Op.getConstantOperandVal(4);
1118 return Op.getOperand(0);
1125 MVT VT =
Op.getSimpleValueType();
1131 unsigned Opcode =
Op.getOpcode();
1134 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1140 CstSplatValue =
C->getAPIntValue();
1148 APInt CstSplatValue;
1149 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1153 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1169 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1185 if (
LHS == LHS2 &&
RHS == RHS2) {
1190 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1198 return std::nullopt;
1206 MVT VT =
N->getSimpleValueType(0);
1237 if (~TrueVal == FalseVal) {
1277 unsigned SelOpNo = 0;
1287 unsigned ConstSelOpNo = 1;
1288 unsigned OtherSelOpNo = 2;
1295 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1300 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1306 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1308 std::swap(NewConstOps[0], NewConstOps[1]);
1320 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1322 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1325 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1326 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1346 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1360 int64_t
C = RHSC->getSExtValue();
1403 MVT VT =
Op.getSimpleValueType();
1404 MVT GRLenVT = Subtarget.getGRLenVT();
1409 if (
Op.hasOneUse()) {
1410 unsigned UseOpc =
Op->user_begin()->getOpcode();
1412 SDNode *BinOp = *
Op->user_begin();
1419 return lowerSELECT(NewSel, DAG);
1436 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1459 if (TrueVal - 1 == FalseVal)
1461 if (TrueVal + 1 == FalseVal)
1468 RHS == TrueV &&
LHS == FalseV) {
1493 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1500 MVT GRLenVT = Subtarget.getGRLenVT();
1511 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1512 Op.getOperand(0),
LHS,
RHS, TargetCC,
1515 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1516 Op.getOperand(0), CondV,
Op.getOperand(2));
1520 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1526LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1529 MVT OpVT =
Op.getSimpleValueType();
1540 EVT ResTy =
Op->getValueType(0);
1545 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1555 for (
unsigned int i = 0; i < NewEltNum; i++) {
1558 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1559 ? (
unsigned)LoongArchISD::BITREV_8B
1577 for (
unsigned int i = 0; i < NewEltNum; i++)
1578 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1579 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1597 if (EltBits > 32 || EltBits == 1)
1625 int MaskOffset,
const APInt &Zeroable) {
1626 int Size = Mask.size();
1627 unsigned SizeInBits =
Size * ScalarSizeInBits;
1629 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1630 for (
int i = 0; i <
Size; i += Scale)
1631 for (
int j = 0; j < Shift; ++j)
1632 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1640 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1641 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1646 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1647 for (
int i = 0; i !=
Size; i += Scale) {
1648 unsigned Pos =
Left ? i + Shift : i;
1649 unsigned Low =
Left ? i : i + Shift;
1650 unsigned Len = Scale - Shift;
1655 int ShiftEltBits = ScalarSizeInBits * Scale;
1656 bool ByteShift = ShiftEltBits > 64;
1657 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1658 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1659 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1663 Scale = ByteShift ? Scale / 2 : Scale;
1669 return (
int)ShiftAmt;
1672 unsigned MaxWidth = 128;
1673 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1674 for (
int Shift = 1; Shift != Scale; ++Shift)
1675 for (
bool Left : {
true,
false})
1676 if (CheckZeros(Shift, Scale,
Left)) {
1677 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1702 const APInt &Zeroable) {
1703 int Size = Mask.size();
1717 Mask,
Size, Zeroable);
1725 "Illegal integer vector type");
1734template <
typename ValType>
1737 unsigned CheckStride,
1739 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1743 if (*
I != -1 && *
I != ExpectedIndex)
1745 ExpectedIndex += ExpectedIndexStride;
1749 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1761 int Size = Mask.size();
1770 int VectorSizeInBits =
V1.getValueSizeInBits();
1771 int ScalarSizeInBits = VectorSizeInBits /
Size;
1772 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1773 (void)ScalarSizeInBits;
1775 for (
int i = 0; i <
Size; ++i) {
1781 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1798 RepeatedMask.
assign(LaneSize, -1);
1799 int Size = Mask.size();
1800 for (
int i = 0; i <
Size; ++i) {
1801 assert(Mask[i] == -1 || Mask[i] >= 0);
1804 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1811 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1812 if (RepeatedMask[i % LaneSize] < 0)
1814 RepeatedMask[i % LaneSize] = LocalM;
1815 else if (RepeatedMask[i % LaneSize] != LocalM)
1832 int NumElts = RepeatedMask.
size();
1834 int Scale = 16 / NumElts;
1836 for (
int i = 0; i < NumElts; ++i) {
1837 int M = RepeatedMask[i];
1838 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1839 "Unexpected mask index.");
1844 int StartIdx = i - (M % NumElts);
1851 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1854 Rotation = CandidateRotation;
1855 else if (Rotation != CandidateRotation)
1870 else if (TargetV != MaskV)
1875 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1876 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1885 return Rotation * Scale;
1904 if (ByteRotation <= 0)
1911 int LoByteShift = 16 - ByteRotation;
1912 int HiByteShift = ByteRotation;
1935 const APInt &Zeroable) {
1949 for (
int i = 0; i < NumElements; i++) {
1953 if (i % Scale != 0) {
1965 M = M % NumElements;
1968 Offset = M - (i / Scale);
1971 if (
Offset % (NumElements / Scale))
1973 }
else if (InputV != V)
1976 if (M != (
Offset + (i / Scale)))
1986 unsigned VilVLoHi = LoongArchISD::VILVL;
1987 if (
Offset >= (NumElements / 2)) {
1988 VilVLoHi = LoongArchISD::VILVH;
1989 Offset -= (NumElements / 2);
1996 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2000 }
while (Scale > 1);
2006 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2007 NumExtElements *= 2) {
2027 int SplatIndex = -1;
2028 for (
const auto &M : Mask) {
2035 if (SplatIndex == -1)
2038 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2040 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2070 unsigned SubVecSize = 4;
2071 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2074 int SubMask[4] = {-1, -1, -1, -1};
2075 for (
unsigned i = 0; i < SubVecSize; ++i) {
2076 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2082 M -= 4 * (j / SubVecSize);
2083 if (M < 0 || M >= 4)
2089 if (SubMask[i] == -1)
2093 else if (M != -1 && M != SubMask[i])
2100 for (
int i = SubVecSize - 1; i >= 0; --i) {
2113 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2114 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2117 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2135 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2144 for (
int i = 0; i < WidenNumElts; ++i)
2145 WidenMask[i] = WidenNumElts - 1 - i;
2153 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2177 const auto &Begin = Mask.begin();
2178 const auto &End = Mask.end();
2195 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2217 const auto &Begin = Mask.begin();
2218 const auto &End = Mask.end();
2235 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2258 const auto &Begin = Mask.begin();
2259 const auto &End = Mask.end();
2260 unsigned HalfSize = Mask.size() / 2;
2278 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2301 const auto &Begin = Mask.begin();
2302 const auto &End = Mask.end();
2319 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2341 const auto &Begin = Mask.begin();
2342 const auto &Mid = Mask.begin() + Mask.size() / 2;
2343 const auto &End = Mask.end();
2361 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2383 const auto &Begin = Mask.begin();
2384 const auto &Mid = Mask.begin() + Mask.size() / 2;
2385 const auto &End = Mask.end();
2402 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2428 if (Mask.size() != NumElts)
2431 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2434 for (
unsigned i = 0; i < NumElts; ++i) {
2437 if (Mask[i] !=
int(
Base + i)) {
2450 int DiffMask = Mask[DiffPos];
2451 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2457 if (
unsigned(DiffMask) < NumElts) {
2462 SrcIdx =
unsigned(DiffMask) - NumElts;
2478 if (
SDValue Result = tryLowerToExtrAndIns(0))
2480 return tryLowerToExtrAndIns(NumElts);
2488 unsigned &MaskImm) {
2489 unsigned MaskSize = Mask.size();
2491 auto isValid = [&](
int M,
int Off) {
2492 return (M == -1) || (M >= Off && M < Off + 4);
2495 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2496 auto immPart = [&](
int M,
unsigned Off) {
2497 return (M == -1 ? 0 : (M - Off)) & 0x3;
2499 MaskImm |= immPart(MLo, Off) << (
I * 2);
2500 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2503 for (
unsigned i = 0; i < 4; i += 2) {
2505 int MHi = Mask[i + 1];
2507 if (MaskSize == 8) {
2508 int M2Lo = Mask[i + 4];
2509 int M2Hi = Mask[i + 5];
2510 if (M2Lo != MLo + 4 || M2Hi != MHi + 4)
2516 buildImm(MLo, MHi, 0, i);
2519 buildImm(MLo, MHi, MaskSize, i);
2549 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2554 unsigned MaskImm = 0;
2558 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2585 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2598 "Vector type is unsupported for lsx!");
2600 "Two operands have different types!");
2602 "Unexpected mask size for shuffle!");
2603 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2605 APInt KnownUndef, KnownZero;
2607 APInt Zeroable = KnownUndef | KnownZero;
2680 int SplatIndex = -1;
2681 for (
const auto &M : Mask) {
2688 if (SplatIndex == -1)
2691 const auto &Begin = Mask.begin();
2692 const auto &End = Mask.end();
2693 int HalfSize = Mask.size() / 2;
2695 if (SplatIndex >= HalfSize)
2698 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2702 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2716 if (Mask.size() == 4) {
2717 unsigned MaskImm = 0;
2718 for (
int i = 1; i >= 0; --i) {
2720 int MHi = Mask[i + 2];
2721 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2722 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2724 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2729 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2731 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2734 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2747 unsigned MaskSize = Mask.size();
2752 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2754 unsigned MaskImm = 0;
2758 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2763 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2764 unsigned MaskImm = 0;
2765 for (
unsigned i = 0; i < MaskSize; ++i) {
2768 if (Mask[i] >= (
int)MaskSize)
2770 MaskImm |= Mask[i] << (i * 2);
2773 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2785 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2789 unsigned HalfSize = NumElts / 2;
2790 bool FrontLo =
true, FrontHi =
true;
2791 bool BackLo =
true, BackHi =
true;
2793 auto inRange = [](
int val,
int low,
int high) {
2794 return (val == -1) || (val >= low && val < high);
2797 for (
unsigned i = 0; i < HalfSize; ++i) {
2798 int Fronti = Mask[i];
2799 int Backi = Mask[i + HalfSize];
2801 FrontLo &=
inRange(Fronti, 0, HalfSize);
2802 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2803 BackLo &=
inRange(Backi, 0, HalfSize);
2804 BackHi &=
inRange(Backi, HalfSize, NumElts);
2810 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2815 for (
unsigned i = 0; i < NumElts; ++i)
2820 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2842 const auto &Begin = Mask.begin();
2843 const auto &End = Mask.end();
2844 unsigned HalfSize = Mask.size() / 2;
2845 unsigned LeftSize = HalfSize / 2;
2853 Mask.size() + HalfSize - LeftSize, 1) &&
2855 Mask.size() + HalfSize + LeftSize, 1))
2866 Mask.size() + HalfSize - LeftSize, 1) &&
2868 Mask.size() + HalfSize + LeftSize, 1))
2873 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2881 const auto &Begin = Mask.begin();
2882 const auto &End = Mask.end();
2883 unsigned HalfSize = Mask.size() / 2;
2891 Mask.size() + HalfSize, 1))
2902 Mask.size() + HalfSize, 1))
2907 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2915 const auto &Begin = Mask.begin();
2916 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2917 const auto &Mid = Mask.begin() + Mask.size() / 2;
2918 const auto &RightMid = Mask.end() - Mask.size() / 4;
2919 const auto &End = Mask.end();
2920 unsigned HalfSize = Mask.size() / 2;
2942 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2950 const auto &Begin = Mask.begin();
2951 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2952 const auto &Mid = Mask.begin() + Mask.size() / 2;
2953 const auto &RightMid = Mask.end() - Mask.size() / 4;
2954 const auto &End = Mask.end();
2955 unsigned HalfSize = Mask.size() / 2;
2978 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2987 int HalfSize = NumElts / 2;
2991 if ((
int)Mask.size() != NumElts)
2994 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
2996 for (
int i = 0; i < NumElts; ++i) {
2999 if (Mask[i] !=
Base + i) {
3001 if (DiffPos.
size() > 2)
3009 if (DiffPos.
size() == 1) {
3010 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3011 DiffPos.
push_back(DiffPos[0] + HalfSize);
3012 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3013 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3017 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3021 int DiffMaskLo = Mask[DiffPos[0]];
3022 int DiffMaskHi = Mask[DiffPos[1]];
3023 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3024 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3025 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3026 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3028 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3029 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3031 if (DiffMaskHi != DiffMaskLo + HalfSize)
3035 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3037 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3058 if (
SDValue Result = tryLowerToExtrAndIns(0))
3060 return tryLowerToExtrAndIns(NumElts);
3069 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3074 int MaskSize = Mask.size();
3080 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3082 for (
int i = 0; i < MaskSize; ++i) {
3083 if (Mask[i] ==
Base + i || Mask[i] == -1)
3085 if (Mask[i] != Replaced)
3096 int Idx = checkReplaceOne(0, MaskSize);
3098 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3102 Idx = checkReplaceOne(MaskSize, 0);
3104 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3115 int MaskSize = Mask.size();
3116 int HalfSize = Mask.size() / 2;
3117 const auto &Begin = Mask.begin();
3118 const auto &Mid = Mask.begin() + HalfSize;
3119 const auto &End = Mask.end();
3131 for (
auto it = Begin; it < Mid; it++) {
3134 else if ((*it >= 0 && *it < HalfSize) ||
3135 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3136 int M = *it < HalfSize ? *it : *it - HalfSize;
3141 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3143 for (
auto it = Mid; it < End; it++) {
3146 else if ((*it >= HalfSize && *it < MaskSize) ||
3147 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3148 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3153 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3157 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3185 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3187 int MaskSize = Mask.size();
3188 int HalfSize = Mask.size() / 2;
3191 HalfMaskType preMask =
None, postMask =
None;
3193 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3194 return M < 0 || (M >= 0 && M < HalfSize) ||
3195 (M >= MaskSize && M < MaskSize + HalfSize);
3197 preMask = HighLaneTy;
3198 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3199 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3200 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3202 preMask = LowLaneTy;
3204 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3205 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3206 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3208 postMask = LowLaneTy;
3209 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3210 return M < 0 || (M >= 0 && M < HalfSize) ||
3211 (M >= MaskSize && M < MaskSize + HalfSize);
3213 postMask = HighLaneTy;
3221 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3224 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3232 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3237 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3238 *it = *it < 0 ? *it : *it - HalfSize;
3240 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3241 *it = *it < 0 ? *it : *it + HalfSize;
3243 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3251 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3256 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3257 *it = *it < 0 ? *it : *it - HalfSize;
3259 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3267 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3272 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3273 *it = *it < 0 ? *it : *it + HalfSize;
3298 int Size = Mask.size();
3299 int LaneSize =
Size / 2;
3301 bool LaneCrossing[2] = {
false,
false};
3302 for (
int i = 0; i <
Size; ++i)
3303 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3304 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3307 if (!LaneCrossing[0] && !LaneCrossing[1])
3311 InLaneMask.
assign(Mask.begin(), Mask.end());
3312 for (
int i = 0; i <
Size; ++i) {
3313 int &M = InLaneMask[i];
3316 if (((M %
Size) / LaneSize) != (i / LaneSize))
3317 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3322 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3337 "Vector type is unsupported for lasx!");
3339 "Two operands have different types!");
3341 "Unexpected mask size for shuffle!");
3342 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3343 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3345 APInt KnownUndef, KnownZero;
3347 APInt Zeroable = KnownUndef | KnownZero;
3434 ArrayRef<int> OrigMask = SVOp->
getMask();
3437 MVT VT =
Op.getSimpleValueType();
3441 bool V1IsUndef =
V1.isUndef();
3442 bool V2IsUndef = V2.
isUndef();
3443 if (V1IsUndef && V2IsUndef)
3456 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3457 SmallVector<int, 8> NewMask(OrigMask);
3458 for (
int &M : NewMask)
3459 if (M >= NumElements)
3465 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3466 (void)MaskUpperLimit;
3468 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3469 "Out of bounds shuffle index");
3491 std::tie(Res, Chain) =
3492 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3493 if (Subtarget.is64Bit())
3494 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3506 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3510 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3511 CallOptions,
DL, Chain);
3517 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3523 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3524 if (Subtarget.is64Bit())
3525 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3531 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3532 MVT VT =
Op.getSimpleValueType();
3537 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3558 "Unsupported vector type for broadcast.");
3561 bool IsIdeneity =
true;
3563 for (
int i = 0; i !=
NumOps; i++) {
3565 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3577 auto ExtType = LN->getExtensionType();
3582 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3587 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3605 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3619 EVT ResTy,
unsigned first) {
3622 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3625 Node->op_begin() + first + NumElts);
3634 MVT VT =
Node->getSimpleValueType(0);
3635 EVT ResTy =
Op->getValueType(0);
3638 APInt SplatValue, SplatUndef;
3639 unsigned SplatBitSize;
3642 bool UseSameConstant =
true;
3647 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3648 (!Subtarget.hasExtLASX() || !Is256Vec))
3654 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3656 SplatBitSize <= 64) {
3658 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3662 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3669 if ((Is128Vec && ResTy == MVT::v4i32) ||
3670 (Is256Vec && ResTy == MVT::v8i32))
3676 switch (SplatBitSize) {
3680 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3683 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3686 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3689 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3697 if (ViaVecTy != ResTy)
3706 for (
unsigned i = 0; i < NumElts; ++i) {
3711 ConstantValue = Opi;
3712 else if (ConstantValue != Opi)
3713 UseSameConstant =
false;
3718 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3720 for (
unsigned i = 0; i < NumElts; ++i) {
3738 BitVector UndefElements;
3739 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3740 UndefElements.
count() == 0) {
3744 EVT FillTy = Is256Vec
3750 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3753 unsigned SplatLen = NumElts / SeqLen;
3759 if (SplatEltTy == MVT::i128)
3760 SplatTy = MVT::v4i64;
3768 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3769 : LoongArchISD::XVREPLVE0,
3770 DL, SplatTy, SrcVec);
3772 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3785 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3786 ResTy == MVT::v4f64) {
3787 unsigned NonUndefCount = 0;
3788 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3789 if (!
Node->getOperand(i).isUndef()) {
3791 if (NonUndefCount > 1)
3795 if (NonUndefCount == 1)
3808 VecTy, NumElts / 2);
3819 MVT ResVT =
Op.getSimpleValueType();
3823 unsigned NumFreezeUndef = 0;
3824 unsigned NumZero = 0;
3825 unsigned NumNonZero = 0;
3826 unsigned NonZeros = 0;
3827 SmallSet<SDValue, 4> Undefs;
3828 for (
unsigned i = 0; i != NumOperands; ++i) {
3843 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3850 if (NumNonZero > 2) {
3854 Ops.slice(0, NumOperands / 2));
3856 Ops.slice(NumOperands / 2));
3869 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3871 for (
unsigned i = 0; i != NumOperands; ++i) {
3872 if ((NonZeros & (1 << i)) == 0)
3883LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3885 MVT EltVT =
Op.getSimpleValueType();
3890 MVT GRLenVT = Subtarget.getGRLenVT();
3918 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3922 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3924 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3933 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3942LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3944 MVT VT =
Op.getSimpleValueType();
3967 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3969 for (
unsigned i = 0; i < NumElts; ++i) {
3977 for (
unsigned i = 0; i < NumElts; ++i) {
3986 for (
unsigned i = 0; i < NumElts; ++i)
4018 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4020 "On LA64, only 64-bit registers can be written.");
4021 return Op.getOperand(0);
4024 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4026 "On LA32, only 32-bit registers can be written.");
4027 return Op.getOperand(0);
4037 "be a constant integer");
4043 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4044 EVT VT =
Op.getValueType();
4047 unsigned Depth =
Op.getConstantOperandVal(0);
4048 int GRLenInBytes = Subtarget.getGRLen() / 8;
4051 int Offset = -(GRLenInBytes * 2);
4063 if (
Op.getConstantOperandVal(0) != 0) {
4065 "return address can only be determined for the current frame");
4071 MVT GRLenVT = Subtarget.getGRLenVT();
4083 auto Size = Subtarget.getGRLen() / 8;
4091 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4101 MachinePointerInfo(SV));
4106 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4107 !Subtarget.hasBasicD() &&
"unexpected target features");
4113 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4117 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4127 EVT RetVT =
Op.getValueType();
4133 std::tie(Result, Chain) =
4140 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4141 !Subtarget.hasBasicD() &&
"unexpected target features");
4152 EVT RetVT =
Op.getValueType();
4158 std::tie(Result, Chain) =
4167 EVT VT =
Op.getValueType();
4171 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4172 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4174 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4176 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4179 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4193 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4194 !Subtarget.hasBasicD()) {
4196 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4218 N->getOffset(), Flags);
4226template <
class NodeTy>
4229 bool IsLocal)
const {
4240 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4321 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4323 const GlobalValue *GV =
N->getGlobal();
4335 unsigned Opc,
bool UseGOT,
4339 MVT GRLenVT = Subtarget.getGRLenVT();
4353 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4391 Args.emplace_back(Load, CallTy);
4394 TargetLowering::CallLoweringInfo CLI(DAG);
4409 const GlobalValue *GV =
N->getGlobal();
4423LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4430 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4433 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4446 return getDynamicTLSAddr(
N, DAG,
4447 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4448 : LoongArch::PseudoLA_TLS_GD,
4455 return getDynamicTLSAddr(
N, DAG,
4456 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4457 : LoongArch::PseudoLA_TLS_LD,
4462 return getStaticTLSAddr(
N, DAG,
4463 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4464 : LoongArch::PseudoLA_TLS_IE,
4471 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4475 return getTLSDescAddr(
N, DAG,
4476 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4477 : LoongArch::PseudoLA_TLS_DESC,
4481template <
unsigned N>
4486 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4487 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4489 ": argument out of range.");
4496LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4498 switch (
Op.getConstantOperandVal(0)) {
4501 case Intrinsic::thread_pointer: {
4505 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4506 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4507 case Intrinsic::loongarch_lsx_vreplvei_d:
4508 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4510 case Intrinsic::loongarch_lsx_vreplvei_w:
4511 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4512 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4513 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4514 case Intrinsic::loongarch_lasx_xvpickve_d:
4515 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4517 case Intrinsic::loongarch_lasx_xvinsve0_d:
4519 case Intrinsic::loongarch_lsx_vsat_b:
4520 case Intrinsic::loongarch_lsx_vsat_bu:
4521 case Intrinsic::loongarch_lsx_vrotri_b:
4522 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4523 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4524 case Intrinsic::loongarch_lsx_vsrlri_b:
4525 case Intrinsic::loongarch_lsx_vsrari_b:
4526 case Intrinsic::loongarch_lsx_vreplvei_h:
4527 case Intrinsic::loongarch_lasx_xvsat_b:
4528 case Intrinsic::loongarch_lasx_xvsat_bu:
4529 case Intrinsic::loongarch_lasx_xvrotri_b:
4530 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4531 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4532 case Intrinsic::loongarch_lasx_xvsrlri_b:
4533 case Intrinsic::loongarch_lasx_xvsrari_b:
4534 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4535 case Intrinsic::loongarch_lasx_xvpickve_w:
4536 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4538 case Intrinsic::loongarch_lasx_xvinsve0_w:
4540 case Intrinsic::loongarch_lsx_vsat_h:
4541 case Intrinsic::loongarch_lsx_vsat_hu:
4542 case Intrinsic::loongarch_lsx_vrotri_h:
4543 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4544 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4545 case Intrinsic::loongarch_lsx_vsrlri_h:
4546 case Intrinsic::loongarch_lsx_vsrari_h:
4547 case Intrinsic::loongarch_lsx_vreplvei_b:
4548 case Intrinsic::loongarch_lasx_xvsat_h:
4549 case Intrinsic::loongarch_lasx_xvsat_hu:
4550 case Intrinsic::loongarch_lasx_xvrotri_h:
4551 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4552 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4553 case Intrinsic::loongarch_lasx_xvsrlri_h:
4554 case Intrinsic::loongarch_lasx_xvsrari_h:
4555 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4557 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4558 case Intrinsic::loongarch_lsx_vsrani_b_h:
4559 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4560 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4561 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4562 case Intrinsic::loongarch_lsx_vssrani_b_h:
4563 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4564 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4565 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4566 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4567 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4568 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4569 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4570 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4571 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4572 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4573 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4574 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4575 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4576 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4577 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4578 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4579 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4580 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4582 case Intrinsic::loongarch_lsx_vsat_w:
4583 case Intrinsic::loongarch_lsx_vsat_wu:
4584 case Intrinsic::loongarch_lsx_vrotri_w:
4585 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4586 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4587 case Intrinsic::loongarch_lsx_vsrlri_w:
4588 case Intrinsic::loongarch_lsx_vsrari_w:
4589 case Intrinsic::loongarch_lsx_vslei_bu:
4590 case Intrinsic::loongarch_lsx_vslei_hu:
4591 case Intrinsic::loongarch_lsx_vslei_wu:
4592 case Intrinsic::loongarch_lsx_vslei_du:
4593 case Intrinsic::loongarch_lsx_vslti_bu:
4594 case Intrinsic::loongarch_lsx_vslti_hu:
4595 case Intrinsic::loongarch_lsx_vslti_wu:
4596 case Intrinsic::loongarch_lsx_vslti_du:
4597 case Intrinsic::loongarch_lsx_vbsll_v:
4598 case Intrinsic::loongarch_lsx_vbsrl_v:
4599 case Intrinsic::loongarch_lasx_xvsat_w:
4600 case Intrinsic::loongarch_lasx_xvsat_wu:
4601 case Intrinsic::loongarch_lasx_xvrotri_w:
4602 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4603 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4604 case Intrinsic::loongarch_lasx_xvsrlri_w:
4605 case Intrinsic::loongarch_lasx_xvsrari_w:
4606 case Intrinsic::loongarch_lasx_xvslei_bu:
4607 case Intrinsic::loongarch_lasx_xvslei_hu:
4608 case Intrinsic::loongarch_lasx_xvslei_wu:
4609 case Intrinsic::loongarch_lasx_xvslei_du:
4610 case Intrinsic::loongarch_lasx_xvslti_bu:
4611 case Intrinsic::loongarch_lasx_xvslti_hu:
4612 case Intrinsic::loongarch_lasx_xvslti_wu:
4613 case Intrinsic::loongarch_lasx_xvslti_du:
4614 case Intrinsic::loongarch_lasx_xvbsll_v:
4615 case Intrinsic::loongarch_lasx_xvbsrl_v:
4617 case Intrinsic::loongarch_lsx_vseqi_b:
4618 case Intrinsic::loongarch_lsx_vseqi_h:
4619 case Intrinsic::loongarch_lsx_vseqi_w:
4620 case Intrinsic::loongarch_lsx_vseqi_d:
4621 case Intrinsic::loongarch_lsx_vslei_b:
4622 case Intrinsic::loongarch_lsx_vslei_h:
4623 case Intrinsic::loongarch_lsx_vslei_w:
4624 case Intrinsic::loongarch_lsx_vslei_d:
4625 case Intrinsic::loongarch_lsx_vslti_b:
4626 case Intrinsic::loongarch_lsx_vslti_h:
4627 case Intrinsic::loongarch_lsx_vslti_w:
4628 case Intrinsic::loongarch_lsx_vslti_d:
4629 case Intrinsic::loongarch_lasx_xvseqi_b:
4630 case Intrinsic::loongarch_lasx_xvseqi_h:
4631 case Intrinsic::loongarch_lasx_xvseqi_w:
4632 case Intrinsic::loongarch_lasx_xvseqi_d:
4633 case Intrinsic::loongarch_lasx_xvslei_b:
4634 case Intrinsic::loongarch_lasx_xvslei_h:
4635 case Intrinsic::loongarch_lasx_xvslei_w:
4636 case Intrinsic::loongarch_lasx_xvslei_d:
4637 case Intrinsic::loongarch_lasx_xvslti_b:
4638 case Intrinsic::loongarch_lasx_xvslti_h:
4639 case Intrinsic::loongarch_lasx_xvslti_w:
4640 case Intrinsic::loongarch_lasx_xvslti_d:
4642 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4643 case Intrinsic::loongarch_lsx_vsrani_h_w:
4644 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4645 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4646 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4647 case Intrinsic::loongarch_lsx_vssrani_h_w:
4648 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4649 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4650 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4651 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4652 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4653 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4654 case Intrinsic::loongarch_lsx_vfrstpi_b:
4655 case Intrinsic::loongarch_lsx_vfrstpi_h:
4656 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4657 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4658 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4659 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4660 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4661 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4662 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4663 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4664 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4665 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4666 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4667 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4668 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4669 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4671 case Intrinsic::loongarch_lsx_vsat_d:
4672 case Intrinsic::loongarch_lsx_vsat_du:
4673 case Intrinsic::loongarch_lsx_vrotri_d:
4674 case Intrinsic::loongarch_lsx_vsrlri_d:
4675 case Intrinsic::loongarch_lsx_vsrari_d:
4676 case Intrinsic::loongarch_lasx_xvsat_d:
4677 case Intrinsic::loongarch_lasx_xvsat_du:
4678 case Intrinsic::loongarch_lasx_xvrotri_d:
4679 case Intrinsic::loongarch_lasx_xvsrlri_d:
4680 case Intrinsic::loongarch_lasx_xvsrari_d:
4682 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4683 case Intrinsic::loongarch_lsx_vsrani_w_d:
4684 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4685 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4686 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4687 case Intrinsic::loongarch_lsx_vssrani_w_d:
4688 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4689 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4690 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4691 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4692 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4693 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4694 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4695 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4696 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4697 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4698 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4699 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4700 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4701 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4702 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4703 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4704 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4705 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4707 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4708 case Intrinsic::loongarch_lsx_vsrani_d_q:
4709 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4710 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4711 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4712 case Intrinsic::loongarch_lsx_vssrani_d_q:
4713 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4714 case Intrinsic::loongarch_lsx_vssrani_du_q:
4715 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4716 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4717 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4718 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4719 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4720 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4721 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4722 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4723 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4724 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4725 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4726 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4727 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4728 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4729 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4730 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4732 case Intrinsic::loongarch_lsx_vnori_b:
4733 case Intrinsic::loongarch_lsx_vshuf4i_b:
4734 case Intrinsic::loongarch_lsx_vshuf4i_h:
4735 case Intrinsic::loongarch_lsx_vshuf4i_w:
4736 case Intrinsic::loongarch_lasx_xvnori_b:
4737 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4738 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4739 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4740 case Intrinsic::loongarch_lasx_xvpermi_d:
4742 case Intrinsic::loongarch_lsx_vshuf4i_d:
4743 case Intrinsic::loongarch_lsx_vpermi_w:
4744 case Intrinsic::loongarch_lsx_vbitseli_b:
4745 case Intrinsic::loongarch_lsx_vextrins_b:
4746 case Intrinsic::loongarch_lsx_vextrins_h:
4747 case Intrinsic::loongarch_lsx_vextrins_w:
4748 case Intrinsic::loongarch_lsx_vextrins_d:
4749 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4750 case Intrinsic::loongarch_lasx_xvpermi_w:
4751 case Intrinsic::loongarch_lasx_xvpermi_q:
4752 case Intrinsic::loongarch_lasx_xvbitseli_b:
4753 case Intrinsic::loongarch_lasx_xvextrins_b:
4754 case Intrinsic::loongarch_lasx_xvextrins_h:
4755 case Intrinsic::loongarch_lasx_xvextrins_w:
4756 case Intrinsic::loongarch_lasx_xvextrins_d:
4758 case Intrinsic::loongarch_lsx_vrepli_b:
4759 case Intrinsic::loongarch_lsx_vrepli_h:
4760 case Intrinsic::loongarch_lsx_vrepli_w:
4761 case Intrinsic::loongarch_lsx_vrepli_d:
4762 case Intrinsic::loongarch_lasx_xvrepli_b:
4763 case Intrinsic::loongarch_lasx_xvrepli_h:
4764 case Intrinsic::loongarch_lasx_xvrepli_w:
4765 case Intrinsic::loongarch_lasx_xvrepli_d:
4767 case Intrinsic::loongarch_lsx_vldi:
4768 case Intrinsic::loongarch_lasx_xvldi:
4784LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4787 MVT GRLenVT = Subtarget.getGRLenVT();
4788 EVT VT =
Op.getValueType();
4790 const StringRef ErrorMsgOOR =
"argument out of range";
4791 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4792 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4794 switch (
Op.getConstantOperandVal(1)) {
4797 case Intrinsic::loongarch_crc_w_b_w:
4798 case Intrinsic::loongarch_crc_w_h_w:
4799 case Intrinsic::loongarch_crc_w_w_w:
4800 case Intrinsic::loongarch_crc_w_d_w:
4801 case Intrinsic::loongarch_crcc_w_b_w:
4802 case Intrinsic::loongarch_crcc_w_h_w:
4803 case Intrinsic::loongarch_crcc_w_w_w:
4804 case Intrinsic::loongarch_crcc_w_d_w:
4806 case Intrinsic::loongarch_csrrd_w:
4807 case Intrinsic::loongarch_csrrd_d: {
4808 unsigned Imm =
Op.getConstantOperandVal(2);
4811 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4814 case Intrinsic::loongarch_csrwr_w:
4815 case Intrinsic::loongarch_csrwr_d: {
4816 unsigned Imm =
Op.getConstantOperandVal(3);
4819 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4820 {Chain,
Op.getOperand(2),
4823 case Intrinsic::loongarch_csrxchg_w:
4824 case Intrinsic::loongarch_csrxchg_d: {
4825 unsigned Imm =
Op.getConstantOperandVal(4);
4828 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4829 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4832 case Intrinsic::loongarch_iocsrrd_d: {
4834 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4837#define IOCSRRD_CASE(NAME, NODE) \
4838 case Intrinsic::loongarch_##NAME: { \
4839 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4840 {Chain, Op.getOperand(2)}); \
4846 case Intrinsic::loongarch_cpucfg: {
4847 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4848 {Chain,
Op.getOperand(2)});
4850 case Intrinsic::loongarch_lddir_d: {
4851 unsigned Imm =
Op.getConstantOperandVal(3);
4856 case Intrinsic::loongarch_movfcsr2gr: {
4857 if (!Subtarget.hasBasicF())
4859 unsigned Imm =
Op.getConstantOperandVal(2);
4862 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4865 case Intrinsic::loongarch_lsx_vld:
4866 case Intrinsic::loongarch_lsx_vldrepl_b:
4867 case Intrinsic::loongarch_lasx_xvld:
4868 case Intrinsic::loongarch_lasx_xvldrepl_b:
4872 case Intrinsic::loongarch_lsx_vldrepl_h:
4873 case Intrinsic::loongarch_lasx_xvldrepl_h:
4877 Op,
"argument out of range or not a multiple of 2", DAG)
4879 case Intrinsic::loongarch_lsx_vldrepl_w:
4880 case Intrinsic::loongarch_lasx_xvldrepl_w:
4884 Op,
"argument out of range or not a multiple of 4", DAG)
4886 case Intrinsic::loongarch_lsx_vldrepl_d:
4887 case Intrinsic::loongarch_lasx_xvldrepl_d:
4891 Op,
"argument out of range or not a multiple of 8", DAG)
4902 return Op.getOperand(0);
4908 MVT GRLenVT = Subtarget.getGRLenVT();
4910 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4912 const StringRef ErrorMsgOOR =
"argument out of range";
4913 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4914 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4915 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4917 switch (IntrinsicEnum) {
4921 case Intrinsic::loongarch_cacop_d:
4922 case Intrinsic::loongarch_cacop_w: {
4923 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4925 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4934 case Intrinsic::loongarch_dbar: {
4941 case Intrinsic::loongarch_ibar: {
4948 case Intrinsic::loongarch_break: {
4955 case Intrinsic::loongarch_movgr2fcsr: {
4956 if (!Subtarget.hasBasicF())
4966 case Intrinsic::loongarch_syscall: {
4973#define IOCSRWR_CASE(NAME, NODE) \
4974 case Intrinsic::loongarch_##NAME: { \
4975 SDValue Op3 = Op.getOperand(3); \
4976 return Subtarget.is64Bit() \
4977 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4978 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4979 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4980 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4987 case Intrinsic::loongarch_iocsrwr_d: {
4988 return !Subtarget.is64Bit()
4995#define ASRT_LE_GT_CASE(NAME) \
4996 case Intrinsic::loongarch_##NAME: { \
4997 return !Subtarget.is64Bit() \
4998 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5003#undef ASRT_LE_GT_CASE
5004 case Intrinsic::loongarch_ldpte_d: {
5005 unsigned Imm =
Op.getConstantOperandVal(3);
5006 return !Subtarget.is64Bit()
5011 case Intrinsic::loongarch_lsx_vst:
5012 case Intrinsic::loongarch_lasx_xvst:
5016 case Intrinsic::loongarch_lasx_xvstelm_b:
5021 case Intrinsic::loongarch_lsx_vstelm_b:
5026 case Intrinsic::loongarch_lasx_xvstelm_h:
5031 Op,
"argument out of range or not a multiple of 2", DAG)
5033 case Intrinsic::loongarch_lsx_vstelm_h:
5038 Op,
"argument out of range or not a multiple of 2", DAG)
5040 case Intrinsic::loongarch_lasx_xvstelm_w:
5045 Op,
"argument out of range or not a multiple of 4", DAG)
5047 case Intrinsic::loongarch_lsx_vstelm_w:
5052 Op,
"argument out of range or not a multiple of 4", DAG)
5054 case Intrinsic::loongarch_lasx_xvstelm_d:
5059 Op,
"argument out of range or not a multiple of 8", DAG)
5061 case Intrinsic::loongarch_lsx_vstelm_d:
5066 Op,
"argument out of range or not a multiple of 8", DAG)
5077 EVT VT =
Lo.getValueType();
5118 EVT VT =
Lo.getValueType();
5172 return LoongArchISD::DIV_W;
5174 return LoongArchISD::DIV_WU;
5176 return LoongArchISD::MOD_W;
5178 return LoongArchISD::MOD_WU;
5180 return LoongArchISD::SLL_W;
5182 return LoongArchISD::SRA_W;
5184 return LoongArchISD::SRL_W;
5187 return LoongArchISD::ROTR_W;
5189 return LoongArchISD::CTZ_W;
5191 return LoongArchISD::CLZ_W;
5210 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5211 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5215 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5221 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5248 StringRef ErrorMsg,
bool WithChain =
true) {
5253 Results.push_back(
N->getOperand(0));
5256template <
unsigned N>
5261 const StringRef ErrorMsgOOR =
"argument out of range";
5262 unsigned Imm =
Node->getConstantOperandVal(2);
5296 switch (
N->getConstantOperandVal(0)) {
5299 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5301 LoongArchISD::VPICK_SEXT_ELT);
5303 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5304 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5306 LoongArchISD::VPICK_SEXT_ELT);
5308 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5310 LoongArchISD::VPICK_SEXT_ELT);
5312 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5314 LoongArchISD::VPICK_ZEXT_ELT);
5316 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5317 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5319 LoongArchISD::VPICK_ZEXT_ELT);
5321 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5323 LoongArchISD::VPICK_ZEXT_ELT);
5325 case Intrinsic::loongarch_lsx_bz_b:
5326 case Intrinsic::loongarch_lsx_bz_h:
5327 case Intrinsic::loongarch_lsx_bz_w:
5328 case Intrinsic::loongarch_lsx_bz_d:
5329 case Intrinsic::loongarch_lasx_xbz_b:
5330 case Intrinsic::loongarch_lasx_xbz_h:
5331 case Intrinsic::loongarch_lasx_xbz_w:
5332 case Intrinsic::loongarch_lasx_xbz_d:
5334 LoongArchISD::VALL_ZERO);
5336 case Intrinsic::loongarch_lsx_bz_v:
5337 case Intrinsic::loongarch_lasx_xbz_v:
5339 LoongArchISD::VANY_ZERO);
5341 case Intrinsic::loongarch_lsx_bnz_b:
5342 case Intrinsic::loongarch_lsx_bnz_h:
5343 case Intrinsic::loongarch_lsx_bnz_w:
5344 case Intrinsic::loongarch_lsx_bnz_d:
5345 case Intrinsic::loongarch_lasx_xbnz_b:
5346 case Intrinsic::loongarch_lasx_xbnz_h:
5347 case Intrinsic::loongarch_lasx_xbnz_w:
5348 case Intrinsic::loongarch_lasx_xbnz_d:
5350 LoongArchISD::VALL_NONZERO);
5352 case Intrinsic::loongarch_lsx_bnz_v:
5353 case Intrinsic::loongarch_lasx_xbnz_v:
5355 LoongArchISD::VANY_NONZERO);
5363 assert(
N->getValueType(0) == MVT::i128 &&
5364 "AtomicCmpSwap on types less than 128 should be legal");
5368 switch (
MemOp->getMergedOrdering()) {
5372 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5376 Opcode = LoongArch::PseudoCmpXchg128;
5383 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5384 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5385 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5386 NewVal.first, NewVal.second,
N->getOperand(0)};
5389 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5400 EVT VT =
N->getValueType(0);
5401 switch (
N->getOpcode()) {
5406 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5407 "Unexpected custom legalisation");
5414 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5415 "Unexpected custom legalisation");
5417 Subtarget.hasDiv32() && VT == MVT::i32
5424 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5425 "Unexpected custom legalisation");
5433 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5434 "Unexpected custom legalisation");
5441 MVT VT =
N->getSimpleValueType(0);
5442 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5443 "Unexpected custom legalisation");
5445 "Unexpected type action!");
5450 Ld->getPointerInfo(), Ld->getBaseAlign(),
5451 Ld->getMemOperand()->getFlags());
5462 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5463 "Unexpected custom legalisation");
5470 if (Src.getValueType() == MVT::f16)
5481 EVT OpVT = Src.getValueType();
5485 std::tie(Result, Chain) =
5492 EVT SrcVT = Src.getValueType();
5493 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5494 Subtarget.hasBasicF()) {
5496 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5498 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5500 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5508 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5509 "Unexpected custom legalisation");
5512 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5517 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5518 "Unexpected custom legalisation");
5524 if (OpVT == MVT::v2f64) {
5534 assert((VT == MVT::i16 || VT == MVT::i32) &&
5535 "Unexpected custom legalization");
5536 MVT GRLenVT = Subtarget.getGRLenVT();
5543 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5548 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5556 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5557 "Unexpected custom legalization");
5558 MVT GRLenVT = Subtarget.getGRLenVT();
5565 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5568 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5576 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5577 "Unexpected custom legalisation");
5584 MVT GRLenVT = Subtarget.getGRLenVT();
5585 const StringRef ErrorMsgOOR =
"argument out of range";
5586 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5587 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5589 switch (
N->getConstantOperandVal(1)) {
5592 case Intrinsic::loongarch_movfcsr2gr: {
5593 if (!Subtarget.hasBasicF()) {
5603 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5610#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5611 case Intrinsic::loongarch_##NAME: { \
5612 SDValue NODE = DAG.getNode( \
5613 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5614 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5615 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5616 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5617 Results.push_back(NODE.getValue(1)); \
5626#undef CRC_CASE_EXT_BINARYOP
5628#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5629 case Intrinsic::loongarch_##NAME: { \
5630 SDValue NODE = DAG.getNode( \
5631 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5633 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5634 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5635 Results.push_back(NODE.getValue(1)); \
5640#undef CRC_CASE_EXT_UNARYOP
5641#define CSR_CASE(ID) \
5642 case Intrinsic::loongarch_##ID: { \
5643 if (!Subtarget.is64Bit()) \
5644 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5652 case Intrinsic::loongarch_csrrd_w: {
5659 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5666 case Intrinsic::loongarch_csrwr_w: {
5667 unsigned Imm =
N->getConstantOperandVal(3);
5673 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5681 case Intrinsic::loongarch_csrxchg_w: {
5682 unsigned Imm =
N->getConstantOperandVal(4);
5688 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5697#define IOCSRRD_CASE(NAME, NODE) \
5698 case Intrinsic::loongarch_##NAME: { \
5699 SDValue IOCSRRDResults = \
5700 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5701 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5702 Results.push_back( \
5703 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5704 Results.push_back(IOCSRRDResults.getValue(1)); \
5711 case Intrinsic::loongarch_cpucfg: {
5713 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5720 case Intrinsic::loongarch_lddir_d: {
5721 if (!Subtarget.is64Bit()) {
5731 if (Subtarget.is64Bit())
5733 "On LA64, only 64-bit registers can be read.");
5736 "On LA32, only 32-bit registers can be read.");
5738 Results.push_back(
N->getOperand(0));
5749 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5762 MVT VT =
N->getSimpleValueType(0);
5768 EVT InVT = In.getValueType();
5779 for (
unsigned I = 0;
I < MinElts; ++
I)
5780 TruncMask[
I] = Scale *
I;
5782 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5783 MVT SVT = In.getSimpleValueType().getScalarType();
5789 "Illegal vector type in truncation");
5801 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
5804 EVT DstVT =
N->getValueType(0);
5806 MVT SrcVT = Src.getSimpleValueType();
5820 unsigned WidenSrcElts = 128 / SrcEltBits;
5827 unsigned FirstStageEltBits = 128 / NumElts;
5831 SrcVT = FirstStageVT;
5832 SrcEltBits = FirstStageEltBits;
5839 while (SrcEltBits < DstEltBits) {
5840 unsigned NextEltBits = SrcEltBits * 2;
5843 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
5861 Blocks = std::move(NextBlocks);
5862 SrcVT = NextBlockVT;
5863 SrcEltBits = NextEltBits;
5880 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5882 MVT VT =
N->getSimpleValueType(0);
5901 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5905 unsigned MinSizeInBits) {
5913 unsigned SplatBitSize;
5916 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
5917 HasAnyUndefs, MinSizeInBits,
5929 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
5940 unsigned EltIdx = IdxC->getZExtValue();
5942 Start = (int)EltIdx - (
int)(i * 2);
5943 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
5949 else if (Src != CurSrc)
5953 if (!Src || Start < 0)
5963 if (!Subtarget.hasExtLSX())
5966 unsigned Opc =
N->getOpcode();
5969 EVT VT =
N->getValueType(0);
5976 unsigned ExtOpc =
LHS.getOpcode();
5984 if (ExtOpc !=
RHS.getOpcode())
5987 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
5990 unsigned OddIdx, EvenIdx;
5994 if (!LHSVec || !RHSVec)
5996 if (OddIdx != 1 || EvenIdx != 0)
6006 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6019 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6021 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6023 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6035 EVT VT =
N->getValueType(0);
6101 if (
And.getOperand(0) ==
X) {
6130 if (ShiftVal != (SplatVal + 1))
6139 : LoongArchISD::VSRAR,
6149 SDValue FirstOperand =
N->getOperand(0);
6150 SDValue SecondOperand =
N->getOperand(1);
6151 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6152 EVT ValTy =
N->getValueType(0);
6155 unsigned SMIdx, SMLen;
6164 if (!Subtarget.has32S())
6220 NewOperand = FirstOperand;
6223 msb = lsb + SMLen - 1;
6227 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6241 EVT DstVT =
N.getValueType();
6248 EVT SrcVT = Src.getValueType();
6252 if (
N.getConstantOperandVal(1) != 0)
6268 if (NumElts % 2 != 0)
6274 for (
unsigned I = 0;
I != NumElts; ++
I) {
6287 SrcVT = Src.getValueType();
6297 }
else if (ThisSrc != Src) {
6301 unsigned Half = NumElts / 2;
6302 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6303 if (CI->getZExtValue() != ExpectedIdx)
6313 if (!Subtarget.hasExtLSX())
6318 EVT VT =
N->getValueType(0);
6325 unsigned ExtOpc =
LHS.getOpcode();
6333 if (!
LHS.hasOneUse())
6359 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6368 if (!Subtarget.has32S())
6380 SDValue FirstOperand =
N->getOperand(0);
6382 EVT ValTy =
N->getValueType(0);
6385 unsigned MaskIdx, MaskLen;
6400 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6401 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6425 switch (Src.getOpcode()) {
6428 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6438 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6451 switch (Src.getOpcode()) {
6461 Src.getOpcode(),
DL, SExtVT,
6467 DL, SExtVT, Src.getOperand(0),
6479 EVT VT =
N->getValueType(0);
6481 EVT SrcVT = Src.getValueType();
6483 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6488 EVT CmpVT = Src.getOperand(0).getValueType();
6493 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6506 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6511 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6516 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6521 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6523 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6528 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6530 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6535 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6552 EVT VT =
N->getValueType(0);
6554 EVT SrcVT = Src.getValueType();
6571 bool UseLASX =
false;
6572 bool PropagateSExt =
false;
6574 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6575 EVT CmpVT = Src.getOperand(0).getValueType();
6584 SExtVT = MVT::v2i64;
6587 SExtVT = MVT::v4i32;
6589 SExtVT = MVT::v4i64;
6591 PropagateSExt =
true;
6595 SExtVT = MVT::v8i16;
6597 SExtVT = MVT::v8i32;
6599 PropagateSExt =
true;
6603 SExtVT = MVT::v16i8;
6605 SExtVT = MVT::v16i16;
6607 PropagateSExt =
true;
6611 SExtVT = MVT::v32i8;
6619 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6620 if (Src.getSimpleValueType() == MVT::v32i8) {
6628 }
else if (UseLASX) {
6634 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6647 EVT ValTy =
N->getValueType(0);
6648 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6652 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6654 bool SwapAndRetried =
false;
6657 if (!Subtarget.has32S())
6663 if (ValBits != 32 && ValBits != 64)
6678 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6681 (MaskIdx0 + MaskLen0 <= ValBits)) {
6702 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6703 (MaskIdx0 + MaskLen0 <= ValBits)) {
6720 (MaskIdx0 + MaskLen0 <= 64) &&
6728 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6729 : (MaskIdx0 + MaskLen0 - 1),
6745 (MaskIdx0 + MaskLen0 <= ValBits)) {
6768 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6769 : (MaskIdx0 + MaskLen0 - 1),
6784 unsigned MaskIdx, MaskLen;
6785 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6794 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6812 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
6818 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6826 if (!SwapAndRetried) {
6828 SwapAndRetried =
true;
6832 SwapAndRetried =
false;
6849 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6858 if (!SwapAndRetried) {
6860 SwapAndRetried =
true;
6870 switch (V.getNode()->getOpcode()) {
6882 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6890 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6967 SDNode *AndNode =
N->getOperand(0).getNode();
6975 SDValue CmpInputValue =
N->getOperand(1);
6984 if (!CN || !CN->
isZero())
6986 AndInputValue1 = AndInputValue1.
getOperand(0);
6990 if (AndInputValue2 != CmpInputValue)
7023 TruncInputValue1, TruncInputValue2);
7025 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7038 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7041 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7066 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7094 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7127 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7128 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7144 EVT VT =
N->getValueType(0);
7147 if (TrueV == FalseV)
7178 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7179 {LHS, RHS, CC, TrueV, FalseV});
7184template <
unsigned N>
7188 bool IsSigned =
false) {
7192 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7193 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7195 ": argument out of range.");
7201template <
unsigned N>
7205 EVT ResTy =
Node->getValueType(0);
7209 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7210 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7212 ": argument out of range.");
7217 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7223 EVT ResTy =
Node->getValueType(0);
7231 EVT ResTy =
Node->getValueType(0);
7240template <
unsigned N>
7243 EVT ResTy =
Node->getValueType(0);
7248 ": argument out of range.");
7258template <
unsigned N>
7261 EVT ResTy =
Node->getValueType(0);
7266 ": argument out of range.");
7275template <
unsigned N>
7278 EVT ResTy =
Node->getValueType(0);
7283 ": argument out of range.");
7292template <
unsigned W>
7295 unsigned Imm =
N->getConstantOperandVal(2);
7297 const StringRef ErrorMsg =
"argument out of range";
7299 return DAG.
getUNDEF(
N->getValueType(0));
7305 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7313 switch (
N->getConstantOperandVal(0)) {
7316 case Intrinsic::loongarch_lsx_vadd_b:
7317 case Intrinsic::loongarch_lsx_vadd_h:
7318 case Intrinsic::loongarch_lsx_vadd_w:
7319 case Intrinsic::loongarch_lsx_vadd_d:
7320 case Intrinsic::loongarch_lasx_xvadd_b:
7321 case Intrinsic::loongarch_lasx_xvadd_h:
7322 case Intrinsic::loongarch_lasx_xvadd_w:
7323 case Intrinsic::loongarch_lasx_xvadd_d:
7326 case Intrinsic::loongarch_lsx_vaddi_bu:
7327 case Intrinsic::loongarch_lsx_vaddi_hu:
7328 case Intrinsic::loongarch_lsx_vaddi_wu:
7329 case Intrinsic::loongarch_lsx_vaddi_du:
7330 case Intrinsic::loongarch_lasx_xvaddi_bu:
7331 case Intrinsic::loongarch_lasx_xvaddi_hu:
7332 case Intrinsic::loongarch_lasx_xvaddi_wu:
7333 case Intrinsic::loongarch_lasx_xvaddi_du:
7336 case Intrinsic::loongarch_lsx_vsub_b:
7337 case Intrinsic::loongarch_lsx_vsub_h:
7338 case Intrinsic::loongarch_lsx_vsub_w:
7339 case Intrinsic::loongarch_lsx_vsub_d:
7340 case Intrinsic::loongarch_lasx_xvsub_b:
7341 case Intrinsic::loongarch_lasx_xvsub_h:
7342 case Intrinsic::loongarch_lasx_xvsub_w:
7343 case Intrinsic::loongarch_lasx_xvsub_d:
7346 case Intrinsic::loongarch_lsx_vsubi_bu:
7347 case Intrinsic::loongarch_lsx_vsubi_hu:
7348 case Intrinsic::loongarch_lsx_vsubi_wu:
7349 case Intrinsic::loongarch_lsx_vsubi_du:
7350 case Intrinsic::loongarch_lasx_xvsubi_bu:
7351 case Intrinsic::loongarch_lasx_xvsubi_hu:
7352 case Intrinsic::loongarch_lasx_xvsubi_wu:
7353 case Intrinsic::loongarch_lasx_xvsubi_du:
7356 case Intrinsic::loongarch_lsx_vneg_b:
7357 case Intrinsic::loongarch_lsx_vneg_h:
7358 case Intrinsic::loongarch_lsx_vneg_w:
7359 case Intrinsic::loongarch_lsx_vneg_d:
7360 case Intrinsic::loongarch_lasx_xvneg_b:
7361 case Intrinsic::loongarch_lasx_xvneg_h:
7362 case Intrinsic::loongarch_lasx_xvneg_w:
7363 case Intrinsic::loongarch_lasx_xvneg_d:
7367 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7369 SDLoc(
N),
N->getValueType(0)),
7371 case Intrinsic::loongarch_lsx_vmax_b:
7372 case Intrinsic::loongarch_lsx_vmax_h:
7373 case Intrinsic::loongarch_lsx_vmax_w:
7374 case Intrinsic::loongarch_lsx_vmax_d:
7375 case Intrinsic::loongarch_lasx_xvmax_b:
7376 case Intrinsic::loongarch_lasx_xvmax_h:
7377 case Intrinsic::loongarch_lasx_xvmax_w:
7378 case Intrinsic::loongarch_lasx_xvmax_d:
7381 case Intrinsic::loongarch_lsx_vmax_bu:
7382 case Intrinsic::loongarch_lsx_vmax_hu:
7383 case Intrinsic::loongarch_lsx_vmax_wu:
7384 case Intrinsic::loongarch_lsx_vmax_du:
7385 case Intrinsic::loongarch_lasx_xvmax_bu:
7386 case Intrinsic::loongarch_lasx_xvmax_hu:
7387 case Intrinsic::loongarch_lasx_xvmax_wu:
7388 case Intrinsic::loongarch_lasx_xvmax_du:
7391 case Intrinsic::loongarch_lsx_vmaxi_b:
7392 case Intrinsic::loongarch_lsx_vmaxi_h:
7393 case Intrinsic::loongarch_lsx_vmaxi_w:
7394 case Intrinsic::loongarch_lsx_vmaxi_d:
7395 case Intrinsic::loongarch_lasx_xvmaxi_b:
7396 case Intrinsic::loongarch_lasx_xvmaxi_h:
7397 case Intrinsic::loongarch_lasx_xvmaxi_w:
7398 case Intrinsic::loongarch_lasx_xvmaxi_d:
7401 case Intrinsic::loongarch_lsx_vmaxi_bu:
7402 case Intrinsic::loongarch_lsx_vmaxi_hu:
7403 case Intrinsic::loongarch_lsx_vmaxi_wu:
7404 case Intrinsic::loongarch_lsx_vmaxi_du:
7405 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7406 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7407 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7408 case Intrinsic::loongarch_lasx_xvmaxi_du:
7411 case Intrinsic::loongarch_lsx_vmin_b:
7412 case Intrinsic::loongarch_lsx_vmin_h:
7413 case Intrinsic::loongarch_lsx_vmin_w:
7414 case Intrinsic::loongarch_lsx_vmin_d:
7415 case Intrinsic::loongarch_lasx_xvmin_b:
7416 case Intrinsic::loongarch_lasx_xvmin_h:
7417 case Intrinsic::loongarch_lasx_xvmin_w:
7418 case Intrinsic::loongarch_lasx_xvmin_d:
7421 case Intrinsic::loongarch_lsx_vmin_bu:
7422 case Intrinsic::loongarch_lsx_vmin_hu:
7423 case Intrinsic::loongarch_lsx_vmin_wu:
7424 case Intrinsic::loongarch_lsx_vmin_du:
7425 case Intrinsic::loongarch_lasx_xvmin_bu:
7426 case Intrinsic::loongarch_lasx_xvmin_hu:
7427 case Intrinsic::loongarch_lasx_xvmin_wu:
7428 case Intrinsic::loongarch_lasx_xvmin_du:
7431 case Intrinsic::loongarch_lsx_vmini_b:
7432 case Intrinsic::loongarch_lsx_vmini_h:
7433 case Intrinsic::loongarch_lsx_vmini_w:
7434 case Intrinsic::loongarch_lsx_vmini_d:
7435 case Intrinsic::loongarch_lasx_xvmini_b:
7436 case Intrinsic::loongarch_lasx_xvmini_h:
7437 case Intrinsic::loongarch_lasx_xvmini_w:
7438 case Intrinsic::loongarch_lasx_xvmini_d:
7441 case Intrinsic::loongarch_lsx_vmini_bu:
7442 case Intrinsic::loongarch_lsx_vmini_hu:
7443 case Intrinsic::loongarch_lsx_vmini_wu:
7444 case Intrinsic::loongarch_lsx_vmini_du:
7445 case Intrinsic::loongarch_lasx_xvmini_bu:
7446 case Intrinsic::loongarch_lasx_xvmini_hu:
7447 case Intrinsic::loongarch_lasx_xvmini_wu:
7448 case Intrinsic::loongarch_lasx_xvmini_du:
7451 case Intrinsic::loongarch_lsx_vmul_b:
7452 case Intrinsic::loongarch_lsx_vmul_h:
7453 case Intrinsic::loongarch_lsx_vmul_w:
7454 case Intrinsic::loongarch_lsx_vmul_d:
7455 case Intrinsic::loongarch_lasx_xvmul_b:
7456 case Intrinsic::loongarch_lasx_xvmul_h:
7457 case Intrinsic::loongarch_lasx_xvmul_w:
7458 case Intrinsic::loongarch_lasx_xvmul_d:
7461 case Intrinsic::loongarch_lsx_vmadd_b:
7462 case Intrinsic::loongarch_lsx_vmadd_h:
7463 case Intrinsic::loongarch_lsx_vmadd_w:
7464 case Intrinsic::loongarch_lsx_vmadd_d:
7465 case Intrinsic::loongarch_lasx_xvmadd_b:
7466 case Intrinsic::loongarch_lasx_xvmadd_h:
7467 case Intrinsic::loongarch_lasx_xvmadd_w:
7468 case Intrinsic::loongarch_lasx_xvmadd_d: {
7469 EVT ResTy =
N->getValueType(0);
7474 case Intrinsic::loongarch_lsx_vmsub_b:
7475 case Intrinsic::loongarch_lsx_vmsub_h:
7476 case Intrinsic::loongarch_lsx_vmsub_w:
7477 case Intrinsic::loongarch_lsx_vmsub_d:
7478 case Intrinsic::loongarch_lasx_xvmsub_b:
7479 case Intrinsic::loongarch_lasx_xvmsub_h:
7480 case Intrinsic::loongarch_lasx_xvmsub_w:
7481 case Intrinsic::loongarch_lasx_xvmsub_d: {
7482 EVT ResTy =
N->getValueType(0);
7487 case Intrinsic::loongarch_lsx_vdiv_b:
7488 case Intrinsic::loongarch_lsx_vdiv_h:
7489 case Intrinsic::loongarch_lsx_vdiv_w:
7490 case Intrinsic::loongarch_lsx_vdiv_d:
7491 case Intrinsic::loongarch_lasx_xvdiv_b:
7492 case Intrinsic::loongarch_lasx_xvdiv_h:
7493 case Intrinsic::loongarch_lasx_xvdiv_w:
7494 case Intrinsic::loongarch_lasx_xvdiv_d:
7497 case Intrinsic::loongarch_lsx_vdiv_bu:
7498 case Intrinsic::loongarch_lsx_vdiv_hu:
7499 case Intrinsic::loongarch_lsx_vdiv_wu:
7500 case Intrinsic::loongarch_lsx_vdiv_du:
7501 case Intrinsic::loongarch_lasx_xvdiv_bu:
7502 case Intrinsic::loongarch_lasx_xvdiv_hu:
7503 case Intrinsic::loongarch_lasx_xvdiv_wu:
7504 case Intrinsic::loongarch_lasx_xvdiv_du:
7507 case Intrinsic::loongarch_lsx_vmod_b:
7508 case Intrinsic::loongarch_lsx_vmod_h:
7509 case Intrinsic::loongarch_lsx_vmod_w:
7510 case Intrinsic::loongarch_lsx_vmod_d:
7511 case Intrinsic::loongarch_lasx_xvmod_b:
7512 case Intrinsic::loongarch_lasx_xvmod_h:
7513 case Intrinsic::loongarch_lasx_xvmod_w:
7514 case Intrinsic::loongarch_lasx_xvmod_d:
7517 case Intrinsic::loongarch_lsx_vmod_bu:
7518 case Intrinsic::loongarch_lsx_vmod_hu:
7519 case Intrinsic::loongarch_lsx_vmod_wu:
7520 case Intrinsic::loongarch_lsx_vmod_du:
7521 case Intrinsic::loongarch_lasx_xvmod_bu:
7522 case Intrinsic::loongarch_lasx_xvmod_hu:
7523 case Intrinsic::loongarch_lasx_xvmod_wu:
7524 case Intrinsic::loongarch_lasx_xvmod_du:
7527 case Intrinsic::loongarch_lsx_vand_v:
7528 case Intrinsic::loongarch_lasx_xvand_v:
7531 case Intrinsic::loongarch_lsx_vor_v:
7532 case Intrinsic::loongarch_lasx_xvor_v:
7535 case Intrinsic::loongarch_lsx_vxor_v:
7536 case Intrinsic::loongarch_lasx_xvxor_v:
7539 case Intrinsic::loongarch_lsx_vnor_v:
7540 case Intrinsic::loongarch_lasx_xvnor_v: {
7545 case Intrinsic::loongarch_lsx_vandi_b:
7546 case Intrinsic::loongarch_lasx_xvandi_b:
7549 case Intrinsic::loongarch_lsx_vori_b:
7550 case Intrinsic::loongarch_lasx_xvori_b:
7553 case Intrinsic::loongarch_lsx_vxori_b:
7554 case Intrinsic::loongarch_lasx_xvxori_b:
7557 case Intrinsic::loongarch_lsx_vsll_b:
7558 case Intrinsic::loongarch_lsx_vsll_h:
7559 case Intrinsic::loongarch_lsx_vsll_w:
7560 case Intrinsic::loongarch_lsx_vsll_d:
7561 case Intrinsic::loongarch_lasx_xvsll_b:
7562 case Intrinsic::loongarch_lasx_xvsll_h:
7563 case Intrinsic::loongarch_lasx_xvsll_w:
7564 case Intrinsic::loongarch_lasx_xvsll_d:
7567 case Intrinsic::loongarch_lsx_vslli_b:
7568 case Intrinsic::loongarch_lasx_xvslli_b:
7571 case Intrinsic::loongarch_lsx_vslli_h:
7572 case Intrinsic::loongarch_lasx_xvslli_h:
7575 case Intrinsic::loongarch_lsx_vslli_w:
7576 case Intrinsic::loongarch_lasx_xvslli_w:
7579 case Intrinsic::loongarch_lsx_vslli_d:
7580 case Intrinsic::loongarch_lasx_xvslli_d:
7583 case Intrinsic::loongarch_lsx_vsrl_b:
7584 case Intrinsic::loongarch_lsx_vsrl_h:
7585 case Intrinsic::loongarch_lsx_vsrl_w:
7586 case Intrinsic::loongarch_lsx_vsrl_d:
7587 case Intrinsic::loongarch_lasx_xvsrl_b:
7588 case Intrinsic::loongarch_lasx_xvsrl_h:
7589 case Intrinsic::loongarch_lasx_xvsrl_w:
7590 case Intrinsic::loongarch_lasx_xvsrl_d:
7593 case Intrinsic::loongarch_lsx_vsrli_b:
7594 case Intrinsic::loongarch_lasx_xvsrli_b:
7597 case Intrinsic::loongarch_lsx_vsrli_h:
7598 case Intrinsic::loongarch_lasx_xvsrli_h:
7601 case Intrinsic::loongarch_lsx_vsrli_w:
7602 case Intrinsic::loongarch_lasx_xvsrli_w:
7605 case Intrinsic::loongarch_lsx_vsrli_d:
7606 case Intrinsic::loongarch_lasx_xvsrli_d:
7609 case Intrinsic::loongarch_lsx_vsra_b:
7610 case Intrinsic::loongarch_lsx_vsra_h:
7611 case Intrinsic::loongarch_lsx_vsra_w:
7612 case Intrinsic::loongarch_lsx_vsra_d:
7613 case Intrinsic::loongarch_lasx_xvsra_b:
7614 case Intrinsic::loongarch_lasx_xvsra_h:
7615 case Intrinsic::loongarch_lasx_xvsra_w:
7616 case Intrinsic::loongarch_lasx_xvsra_d:
7619 case Intrinsic::loongarch_lsx_vsrai_b:
7620 case Intrinsic::loongarch_lasx_xvsrai_b:
7623 case Intrinsic::loongarch_lsx_vsrai_h:
7624 case Intrinsic::loongarch_lasx_xvsrai_h:
7627 case Intrinsic::loongarch_lsx_vsrai_w:
7628 case Intrinsic::loongarch_lasx_xvsrai_w:
7631 case Intrinsic::loongarch_lsx_vsrai_d:
7632 case Intrinsic::loongarch_lasx_xvsrai_d:
7635 case Intrinsic::loongarch_lsx_vclz_b:
7636 case Intrinsic::loongarch_lsx_vclz_h:
7637 case Intrinsic::loongarch_lsx_vclz_w:
7638 case Intrinsic::loongarch_lsx_vclz_d:
7639 case Intrinsic::loongarch_lasx_xvclz_b:
7640 case Intrinsic::loongarch_lasx_xvclz_h:
7641 case Intrinsic::loongarch_lasx_xvclz_w:
7642 case Intrinsic::loongarch_lasx_xvclz_d:
7644 case Intrinsic::loongarch_lsx_vpcnt_b:
7645 case Intrinsic::loongarch_lsx_vpcnt_h:
7646 case Intrinsic::loongarch_lsx_vpcnt_w:
7647 case Intrinsic::loongarch_lsx_vpcnt_d:
7648 case Intrinsic::loongarch_lasx_xvpcnt_b:
7649 case Intrinsic::loongarch_lasx_xvpcnt_h:
7650 case Intrinsic::loongarch_lasx_xvpcnt_w:
7651 case Intrinsic::loongarch_lasx_xvpcnt_d:
7653 case Intrinsic::loongarch_lsx_vbitclr_b:
7654 case Intrinsic::loongarch_lsx_vbitclr_h:
7655 case Intrinsic::loongarch_lsx_vbitclr_w:
7656 case Intrinsic::loongarch_lsx_vbitclr_d:
7657 case Intrinsic::loongarch_lasx_xvbitclr_b:
7658 case Intrinsic::loongarch_lasx_xvbitclr_h:
7659 case Intrinsic::loongarch_lasx_xvbitclr_w:
7660 case Intrinsic::loongarch_lasx_xvbitclr_d:
7662 case Intrinsic::loongarch_lsx_vbitclri_b:
7663 case Intrinsic::loongarch_lasx_xvbitclri_b:
7665 case Intrinsic::loongarch_lsx_vbitclri_h:
7666 case Intrinsic::loongarch_lasx_xvbitclri_h:
7668 case Intrinsic::loongarch_lsx_vbitclri_w:
7669 case Intrinsic::loongarch_lasx_xvbitclri_w:
7671 case Intrinsic::loongarch_lsx_vbitclri_d:
7672 case Intrinsic::loongarch_lasx_xvbitclri_d:
7674 case Intrinsic::loongarch_lsx_vbitset_b:
7675 case Intrinsic::loongarch_lsx_vbitset_h:
7676 case Intrinsic::loongarch_lsx_vbitset_w:
7677 case Intrinsic::loongarch_lsx_vbitset_d:
7678 case Intrinsic::loongarch_lasx_xvbitset_b:
7679 case Intrinsic::loongarch_lasx_xvbitset_h:
7680 case Intrinsic::loongarch_lasx_xvbitset_w:
7681 case Intrinsic::loongarch_lasx_xvbitset_d: {
7682 EVT VecTy =
N->getValueType(0);
7688 case Intrinsic::loongarch_lsx_vbitseti_b:
7689 case Intrinsic::loongarch_lasx_xvbitseti_b:
7691 case Intrinsic::loongarch_lsx_vbitseti_h:
7692 case Intrinsic::loongarch_lasx_xvbitseti_h:
7694 case Intrinsic::loongarch_lsx_vbitseti_w:
7695 case Intrinsic::loongarch_lasx_xvbitseti_w:
7697 case Intrinsic::loongarch_lsx_vbitseti_d:
7698 case Intrinsic::loongarch_lasx_xvbitseti_d:
7700 case Intrinsic::loongarch_lsx_vbitrev_b:
7701 case Intrinsic::loongarch_lsx_vbitrev_h:
7702 case Intrinsic::loongarch_lsx_vbitrev_w:
7703 case Intrinsic::loongarch_lsx_vbitrev_d:
7704 case Intrinsic::loongarch_lasx_xvbitrev_b:
7705 case Intrinsic::loongarch_lasx_xvbitrev_h:
7706 case Intrinsic::loongarch_lasx_xvbitrev_w:
7707 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7708 EVT VecTy =
N->getValueType(0);
7714 case Intrinsic::loongarch_lsx_vbitrevi_b:
7715 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7717 case Intrinsic::loongarch_lsx_vbitrevi_h:
7718 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7720 case Intrinsic::loongarch_lsx_vbitrevi_w:
7721 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7723 case Intrinsic::loongarch_lsx_vbitrevi_d:
7724 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7726 case Intrinsic::loongarch_lsx_vfadd_s:
7727 case Intrinsic::loongarch_lsx_vfadd_d:
7728 case Intrinsic::loongarch_lasx_xvfadd_s:
7729 case Intrinsic::loongarch_lasx_xvfadd_d:
7732 case Intrinsic::loongarch_lsx_vfsub_s:
7733 case Intrinsic::loongarch_lsx_vfsub_d:
7734 case Intrinsic::loongarch_lasx_xvfsub_s:
7735 case Intrinsic::loongarch_lasx_xvfsub_d:
7738 case Intrinsic::loongarch_lsx_vfmul_s:
7739 case Intrinsic::loongarch_lsx_vfmul_d:
7740 case Intrinsic::loongarch_lasx_xvfmul_s:
7741 case Intrinsic::loongarch_lasx_xvfmul_d:
7744 case Intrinsic::loongarch_lsx_vfdiv_s:
7745 case Intrinsic::loongarch_lsx_vfdiv_d:
7746 case Intrinsic::loongarch_lasx_xvfdiv_s:
7747 case Intrinsic::loongarch_lasx_xvfdiv_d:
7750 case Intrinsic::loongarch_lsx_vfmadd_s:
7751 case Intrinsic::loongarch_lsx_vfmadd_d:
7752 case Intrinsic::loongarch_lasx_xvfmadd_s:
7753 case Intrinsic::loongarch_lasx_xvfmadd_d:
7755 N->getOperand(2),
N->getOperand(3));
7756 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7758 N->getOperand(1),
N->getOperand(2),
7760 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7761 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7763 N->getOperand(1),
N->getOperand(2),
7765 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7766 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7768 N->getOperand(1),
N->getOperand(2),
7770 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7772 N->getOperand(1),
N->getOperand(2),
7774 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7775 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7776 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7777 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7778 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7779 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7780 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7781 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7782 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7785 case Intrinsic::loongarch_lsx_vreplve_b:
7786 case Intrinsic::loongarch_lsx_vreplve_h:
7787 case Intrinsic::loongarch_lsx_vreplve_w:
7788 case Intrinsic::loongarch_lsx_vreplve_d:
7789 case Intrinsic::loongarch_lasx_xvreplve_b:
7790 case Intrinsic::loongarch_lasx_xvreplve_h:
7791 case Intrinsic::loongarch_lasx_xvreplve_w:
7792 case Intrinsic::loongarch_lasx_xvreplve_d:
7793 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7797 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7801 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7802 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7806 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7810 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7814 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
7815 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
7819 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
7823 case Intrinsic::loongarch_lsx_bz_b:
7824 case Intrinsic::loongarch_lsx_bz_h:
7825 case Intrinsic::loongarch_lsx_bz_w:
7826 case Intrinsic::loongarch_lsx_bz_d:
7827 case Intrinsic::loongarch_lasx_xbz_b:
7828 case Intrinsic::loongarch_lasx_xbz_h:
7829 case Intrinsic::loongarch_lasx_xbz_w:
7830 case Intrinsic::loongarch_lasx_xbz_d:
7832 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
7835 case Intrinsic::loongarch_lsx_bz_v:
7836 case Intrinsic::loongarch_lasx_xbz_v:
7838 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7841 case Intrinsic::loongarch_lsx_bnz_b:
7842 case Intrinsic::loongarch_lsx_bnz_h:
7843 case Intrinsic::loongarch_lsx_bnz_w:
7844 case Intrinsic::loongarch_lsx_bnz_d:
7845 case Intrinsic::loongarch_lasx_xbnz_b:
7846 case Intrinsic::loongarch_lasx_xbnz_h:
7847 case Intrinsic::loongarch_lasx_xbnz_w:
7848 case Intrinsic::loongarch_lasx_xbnz_d:
7850 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7853 case Intrinsic::loongarch_lsx_bnz_v:
7854 case Intrinsic::loongarch_lasx_xbnz_v:
7856 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7859 case Intrinsic::loongarch_lasx_concat_128_s:
7860 case Intrinsic::loongarch_lasx_concat_128_d:
7861 case Intrinsic::loongarch_lasx_concat_128:
7863 N->getOperand(1),
N->getOperand(2));
7875 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
7887 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
7889 "Unexpected value type!");
7898 MVT VT =
N->getSimpleValueType(0);
7919 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
7932 APInt V =
C->getValueAPF().bitcastToAPInt();
7947 MVT VT =
N->getSimpleValueType(0);
8008 EVT VT =
N->getValueType(0);
8010 if (VT != MVT::f32 && VT != MVT::f64)
8012 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8014 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8037 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
8051 if (!Subtarget.hasExtLSX())
8055 EVT DstVT =
N->getValueType(0);
8057 EVT SrcVT = Src.getValueType();
8067 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8072 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8075 if (DstEltBits < 32) {
8081 if (SrcEltBits != 64 || DstEltBits != 32)
8086 if (Subtarget.hasExtLASX())
8094 unsigned BlockNumElts = BlockBits / 64;
8097 Src.getOperand(0).getValueType() == BlockVT) {
8098 for (
unsigned i = 0; i < Src.getNumOperands(); i++)
8100 }
else if (SrcBits > BlockBits) {
8102 for (
unsigned i = 0; i < SrcBits / BlockBits; i++)
8107 BlockBits = SrcBits;
8111 MVT NativeVT = BlockBits == 256 ? MVT::v8i32 : MVT::v4i32;
8113 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8118 if (BlockBits == 256) {
8128 if (Blocks.
size() == 1)
8185 Subtarget.hasExtLASX() && N1.
hasOneUse())
8197 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8207 EVT VT =
N.getValueType();
8224 switch (
N.getOpcode()) {
8240 EVT VT =
N->getValueType(0);
8255 EVT VT =
N->getValueType(0);
8257 if (VT.
isVector() &&
N->getNumOperands() == 2)
8270 EVT VT =
N->getValueType(0);
8282 SDValue TrueVal =
N->getOperand(1);
8283 SDValue FalseVal =
N->getOperand(2);
8317 if (FalseVal.getOpcode() !=
ISD::ADD)
8320 SDValue Add0 = FalseVal.getOperand(0);
8321 SDValue Add1 = FalseVal.getOperand(1);
8391 : LoongArchISD::VSRAR,
8398 switch (
N->getOpcode()) {
8426 case LoongArchISD::BITREV_W:
8428 case LoongArchISD::BR_CC:
8430 case LoongArchISD::SELECT_CC:
8434 case LoongArchISD::MOVGR2FR_W_LA64:
8436 case LoongArchISD::MOVFR2GR_S_LA64:
8438 case LoongArchISD::CRC_W_B_W:
8439 case LoongArchISD::CRC_W_H_W:
8440 case LoongArchISD::CRCC_W_B_W:
8441 case LoongArchISD::CRCC_W_H_W:
8442 case LoongArchISD::VMSKLTZ:
8443 case LoongArchISD::XVMSKLTZ:
8445 case LoongArchISD::SPLIT_PAIR_F64:
8447 case LoongArchISD::VANDN:
8453 case LoongArchISD::VPACKEV:
8454 case LoongArchISD::VPERMI:
8480 MF->
insert(It, BreakMBB);
8484 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8485 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
8497 MBB->addSuccessor(BreakMBB);
8498 MBB->addSuccessor(SinkMBB);
8504 BreakMBB->addSuccessor(SinkMBB);
8516 switch (
MI.getOpcode()) {
8519 case LoongArch::PseudoVBZ:
8520 CondOpc = LoongArch::VSETEQZ_V;
8522 case LoongArch::PseudoVBZ_B:
8523 CondOpc = LoongArch::VSETANYEQZ_B;
8525 case LoongArch::PseudoVBZ_H:
8526 CondOpc = LoongArch::VSETANYEQZ_H;
8528 case LoongArch::PseudoVBZ_W:
8529 CondOpc = LoongArch::VSETANYEQZ_W;
8531 case LoongArch::PseudoVBZ_D:
8532 CondOpc = LoongArch::VSETANYEQZ_D;
8534 case LoongArch::PseudoVBNZ:
8535 CondOpc = LoongArch::VSETNEZ_V;
8537 case LoongArch::PseudoVBNZ_B:
8538 CondOpc = LoongArch::VSETALLNEZ_B;
8540 case LoongArch::PseudoVBNZ_H:
8541 CondOpc = LoongArch::VSETALLNEZ_H;
8543 case LoongArch::PseudoVBNZ_W:
8544 CondOpc = LoongArch::VSETALLNEZ_W;
8546 case LoongArch::PseudoVBNZ_D:
8547 CondOpc = LoongArch::VSETALLNEZ_D;
8549 case LoongArch::PseudoXVBZ:
8550 CondOpc = LoongArch::XVSETEQZ_V;
8552 case LoongArch::PseudoXVBZ_B:
8553 CondOpc = LoongArch::XVSETANYEQZ_B;
8555 case LoongArch::PseudoXVBZ_H:
8556 CondOpc = LoongArch::XVSETANYEQZ_H;
8558 case LoongArch::PseudoXVBZ_W:
8559 CondOpc = LoongArch::XVSETANYEQZ_W;
8561 case LoongArch::PseudoXVBZ_D:
8562 CondOpc = LoongArch::XVSETANYEQZ_D;
8564 case LoongArch::PseudoXVBNZ:
8565 CondOpc = LoongArch::XVSETNEZ_V;
8567 case LoongArch::PseudoXVBNZ_B:
8568 CondOpc = LoongArch::XVSETALLNEZ_B;
8570 case LoongArch::PseudoXVBNZ_H:
8571 CondOpc = LoongArch::XVSETALLNEZ_H;
8573 case LoongArch::PseudoXVBNZ_W:
8574 CondOpc = LoongArch::XVSETALLNEZ_W;
8576 case LoongArch::PseudoXVBNZ_D:
8577 CondOpc = LoongArch::XVSETALLNEZ_D;
8592 F->insert(It, FalseBB);
8593 F->insert(It, TrueBB);
8594 F->insert(It, SinkBB);
8597 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
8626 MI.getOperand(0).getReg())
8633 MI.eraseFromParent();
8641 unsigned BroadcastOp;
8643 switch (
MI.getOpcode()) {
8646 case LoongArch::PseudoXVINSGR2VR_B:
8648 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8649 InsOp = LoongArch::XVEXTRINS_B;
8651 case LoongArch::PseudoXVINSGR2VR_H:
8653 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8654 InsOp = LoongArch::XVEXTRINS_H;
8666 unsigned Idx =
MI.getOperand(3).getImm();
8674 .
addReg(XSrc, {}, LoongArch::sub_128);
8676 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8677 : LoongArch::VINSGR2VR_B),
8685 .
addImm(LoongArch::sub_128);
8692 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8695 .
addImm(Idx >= HalfSize ? 48 : 18);
8700 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8703 MI.eraseFromParent();
8710 assert(Subtarget.hasExtLSX());
8718 unsigned BroadcastOp, CTOp, PickOp;
8719 switch (
MI.getOpcode()) {
8722 case LoongArch::PseudoCTPOP_B:
8723 BroadcastOp = LoongArch::VREPLGR2VR_B;
8724 CTOp = LoongArch::VPCNT_B;
8725 PickOp = LoongArch::VPICKVE2GR_B;
8727 case LoongArch::PseudoCTPOP_H:
8728 case LoongArch::PseudoCTPOP_H_LA32:
8729 BroadcastOp = LoongArch::VREPLGR2VR_H;
8730 CTOp = LoongArch::VPCNT_H;
8731 PickOp = LoongArch::VPICKVE2GR_H;
8733 case LoongArch::PseudoCTPOP_W:
8734 case LoongArch::PseudoCTPOP_W_LA32:
8735 BroadcastOp = LoongArch::VREPLGR2VR_W;
8736 CTOp = LoongArch::VPCNT_W;
8737 PickOp = LoongArch::VPICKVE2GR_W;
8739 case LoongArch::PseudoCTPOP_D:
8740 BroadcastOp = LoongArch::VREPLGR2VR_D;
8741 CTOp = LoongArch::VPCNT_D;
8742 PickOp = LoongArch::VPICKVE2GR_D;
8752 MI.eraseFromParent();
8766 unsigned EleBits = 8;
8767 unsigned NotOpc = 0;
8770 switch (
MI.getOpcode()) {
8773 case LoongArch::PseudoVMSKLTZ_B:
8774 MskOpc = LoongArch::VMSKLTZ_B;
8776 case LoongArch::PseudoVMSKLTZ_H:
8777 MskOpc = LoongArch::VMSKLTZ_H;
8780 case LoongArch::PseudoVMSKLTZ_W:
8781 MskOpc = LoongArch::VMSKLTZ_W;
8784 case LoongArch::PseudoVMSKLTZ_D:
8785 MskOpc = LoongArch::VMSKLTZ_D;
8788 case LoongArch::PseudoVMSKGEZ_B:
8789 MskOpc = LoongArch::VMSKGEZ_B;
8791 case LoongArch::PseudoVMSKEQZ_B:
8792 MskOpc = LoongArch::VMSKNZ_B;
8793 NotOpc = LoongArch::VNOR_V;
8795 case LoongArch::PseudoVMSKNEZ_B:
8796 MskOpc = LoongArch::VMSKNZ_B;
8798 case LoongArch::PseudoXVMSKLTZ_B:
8799 MskOpc = LoongArch::XVMSKLTZ_B;
8800 RC = &LoongArch::LASX256RegClass;
8802 case LoongArch::PseudoXVMSKLTZ_H:
8803 MskOpc = LoongArch::XVMSKLTZ_H;
8804 RC = &LoongArch::LASX256RegClass;
8807 case LoongArch::PseudoXVMSKLTZ_W:
8808 MskOpc = LoongArch::XVMSKLTZ_W;
8809 RC = &LoongArch::LASX256RegClass;
8812 case LoongArch::PseudoXVMSKLTZ_D:
8813 MskOpc = LoongArch::XVMSKLTZ_D;
8814 RC = &LoongArch::LASX256RegClass;
8817 case LoongArch::PseudoXVMSKGEZ_B:
8818 MskOpc = LoongArch::XVMSKGEZ_B;
8819 RC = &LoongArch::LASX256RegClass;
8821 case LoongArch::PseudoXVMSKEQZ_B:
8822 MskOpc = LoongArch::XVMSKNZ_B;
8823 NotOpc = LoongArch::XVNOR_V;
8824 RC = &LoongArch::LASX256RegClass;
8826 case LoongArch::PseudoXVMSKNEZ_B:
8827 MskOpc = LoongArch::XVMSKNZ_B;
8828 RC = &LoongArch::LASX256RegClass;
8843 if (
TRI->getRegSizeInBits(*RC) > 128) {
8853 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
8854 : LoongArch::BSTRINS_W),
8858 .
addImm(256 / EleBits - 1)
8866 MI.eraseFromParent();
8873 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
8874 "Unexpected instruction");
8886 MI.eraseFromParent();
8893 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
8894 "Unexpected instruction");
8910 MI.eraseFromParent();
8915 switch (
MI.getOpcode()) {
8918 case LoongArch::Select_GPR_Using_CC_GPR:
8954 if (
MI.getOperand(2).isReg())
8955 RHS =
MI.getOperand(2).getReg();
8956 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
8960 SelectDests.
insert(
MI.getOperand(0).getReg());
8964 SequenceMBBI !=
E; ++SequenceMBBI) {
8965 if (SequenceMBBI->isDebugInstr())
8968 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
8969 !SequenceMBBI->getOperand(2).isReg() ||
8970 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
8971 SequenceMBBI->getOperand(3).getImm() != CC ||
8972 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
8973 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
8975 LastSelectPseudo = &*SequenceMBBI;
8977 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
8980 if (SequenceMBBI->hasUnmodeledSideEffects() ||
8981 SequenceMBBI->mayLoadOrStore() ||
8982 SequenceMBBI->usesCustomInsertionHook())
8985 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9000 F->insert(
I, IfFalseMBB);
9001 F->insert(
I, TailMBB);
9004 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9010 TailMBB->
push_back(DebugInstr->removeFromParent());
9014 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9024 if (
MI.getOperand(2).isImm())
9036 auto SelectMBBI =
MI.getIterator();
9037 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9039 while (SelectMBBI != SelectEnd) {
9040 auto Next = std::next(SelectMBBI);
9044 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9045 .
addReg(SelectMBBI->getOperand(4).getReg())
9047 .
addReg(SelectMBBI->getOperand(5).getReg())
9054 F->getProperties().resetNoPHIs();
9060 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9063 switch (
MI.getOpcode()) {
9066 case LoongArch::DIV_W:
9067 case LoongArch::DIV_WU:
9068 case LoongArch::MOD_W:
9069 case LoongArch::MOD_WU:
9070 case LoongArch::DIV_D:
9071 case LoongArch::DIV_DU:
9072 case LoongArch::MOD_D:
9073 case LoongArch::MOD_DU:
9076 case LoongArch::WRFCSR: {
9078 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9079 .
addReg(
MI.getOperand(1).getReg());
9080 MI.eraseFromParent();
9083 case LoongArch::RDFCSR: {
9084 MachineInstr *ReadFCSR =
9086 MI.getOperand(0).getReg())
9087 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9089 MI.eraseFromParent();
9092 case LoongArch::Select_GPR_Using_CC_GPR:
9094 case LoongArch::BuildPairF64Pseudo:
9096 case LoongArch::SplitPairF64Pseudo:
9098 case LoongArch::PseudoVBZ:
9099 case LoongArch::PseudoVBZ_B:
9100 case LoongArch::PseudoVBZ_H:
9101 case LoongArch::PseudoVBZ_W:
9102 case LoongArch::PseudoVBZ_D:
9103 case LoongArch::PseudoVBNZ:
9104 case LoongArch::PseudoVBNZ_B:
9105 case LoongArch::PseudoVBNZ_H:
9106 case LoongArch::PseudoVBNZ_W:
9107 case LoongArch::PseudoVBNZ_D:
9108 case LoongArch::PseudoXVBZ:
9109 case LoongArch::PseudoXVBZ_B:
9110 case LoongArch::PseudoXVBZ_H:
9111 case LoongArch::PseudoXVBZ_W:
9112 case LoongArch::PseudoXVBZ_D:
9113 case LoongArch::PseudoXVBNZ:
9114 case LoongArch::PseudoXVBNZ_B:
9115 case LoongArch::PseudoXVBNZ_H:
9116 case LoongArch::PseudoXVBNZ_W:
9117 case LoongArch::PseudoXVBNZ_D:
9119 case LoongArch::PseudoXVINSGR2VR_B:
9120 case LoongArch::PseudoXVINSGR2VR_H:
9122 case LoongArch::PseudoCTPOP_B:
9123 case LoongArch::PseudoCTPOP_H:
9124 case LoongArch::PseudoCTPOP_W:
9125 case LoongArch::PseudoCTPOP_D:
9126 case LoongArch::PseudoCTPOP_H_LA32:
9127 case LoongArch::PseudoCTPOP_W_LA32:
9129 case LoongArch::PseudoVMSKLTZ_B:
9130 case LoongArch::PseudoVMSKLTZ_H:
9131 case LoongArch::PseudoVMSKLTZ_W:
9132 case LoongArch::PseudoVMSKLTZ_D:
9133 case LoongArch::PseudoVMSKGEZ_B:
9134 case LoongArch::PseudoVMSKEQZ_B:
9135 case LoongArch::PseudoVMSKNEZ_B:
9136 case LoongArch::PseudoXVMSKLTZ_B:
9137 case LoongArch::PseudoXVMSKLTZ_H:
9138 case LoongArch::PseudoXVMSKLTZ_W:
9139 case LoongArch::PseudoXVMSKLTZ_D:
9140 case LoongArch::PseudoXVMSKGEZ_B:
9141 case LoongArch::PseudoXVMSKEQZ_B:
9142 case LoongArch::PseudoXVMSKNEZ_B:
9144 case TargetOpcode::STATEPOINT:
9150 MI.addOperand(*
MI.getMF(),
9152 LoongArch::R1,
true,
9155 if (!Subtarget.is64Bit())
9158 case LoongArch::PROBED_STACKALLOC_DYN:
9165 unsigned *
Fast)
const {
9166 if (!Subtarget.hasUAL())
9184 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9185 LoongArch::R10, LoongArch::R11};
9200 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9201 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9202 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9203 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9204 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9205 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9211 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9212 LoongArch::F6, LoongArch::F7};
9215 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9216 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9219 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9220 LoongArch::VR6, LoongArch::VR7};
9223 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9224 LoongArch::XR6, LoongArch::XR7};
9227 switch (State.getCallingConv()) {
9229 if (!State.isVarArg())
9233 return State.AllocateReg(
ArgGPRs);
9241 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9243 unsigned GRLenInBytes = GRLen / 8;
9254 State.AllocateStack(GRLenInBytes, StackAlign),
9257 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9268 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9276 unsigned ValNo,
MVT ValVT,
9279 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9280 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9281 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9286 if (IsRet && ValNo > 1)
9290 bool UseGPRForFloat =
true;
9300 UseGPRForFloat = ArgFlags.
isVarArg();
9313 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9316 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9317 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9319 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9325 State.getPendingArgFlags();
9328 "PendingLocs and PendingArgFlags out of sync");
9332 UseGPRForFloat =
true;
9334 if (UseGPRForFloat && ValVT == MVT::f32) {
9337 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9340 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9343 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9385 PendingLocs.
size() <= 2) {
9386 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9391 PendingLocs.
clear();
9392 PendingArgFlags.
clear();
9399 unsigned StoreSizeBytes = GRLen / 8;
9402 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9404 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9408 UseGPRForFloat =
false;
9409 StoreSizeBytes = 16;
9410 StackAlign =
Align(16);
9413 UseGPRForFloat =
false;
9414 StoreSizeBytes = 32;
9415 StackAlign =
Align(32);
9421 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9425 if (!PendingLocs.
empty()) {
9427 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9428 for (
auto &It : PendingLocs) {
9430 It.convertToReg(
Reg);
9435 PendingLocs.clear();
9436 PendingArgFlags.
clear();
9439 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9440 "Expected an GRLenVT at this stage");
9457void LoongArchTargetLowering::analyzeInputArgs(
9460 LoongArchCCAssignFn Fn)
const {
9462 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9463 MVT ArgVT = Ins[i].VT;
9464 Type *ArgTy =
nullptr;
9466 ArgTy = FType->getReturnType();
9467 else if (Ins[i].isOrigArg())
9468 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9472 CCInfo, IsRet, ArgTy)) {
9473 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9480void LoongArchTargetLowering::analyzeOutputArgs(
9483 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9484 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9485 MVT ArgVT = Outs[i].VT;
9486 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
9490 CCInfo, IsRet, OrigTy)) {
9491 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
9510 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
9532 if (In.isOrigArg()) {
9537 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
9538 (
BitWidth < 32 && In.Flags.isZExt())) {
9588 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9601 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9605 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
9619 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
9631 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
9635 LoongArch::R23, LoongArch::R24, LoongArch::R25,
9636 LoongArch::R26, LoongArch::R27, LoongArch::R28,
9637 LoongArch::R29, LoongArch::R30, LoongArch::R31};
9644 if (LocVT == MVT::f32) {
9647 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9648 LoongArch::F26, LoongArch::F27};
9655 if (LocVT == MVT::f64) {
9658 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9659 LoongArch::F30_64, LoongArch::F31_64};
9690 "GHC calling convention requires the F and D extensions");
9695 MVT GRLenVT = Subtarget.getGRLenVT();
9696 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9705 return CI->isMustTailCall();
9710 std::vector<SDValue> OutChains;
9719 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9721 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
9738 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
9747 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
9748 assert(ArgPartOffset == 0);
9749 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
9751 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
9775 int VaArgOffset, VarArgsSaveSize;
9779 if (ArgRegs.
size() == Idx) {
9781 VarArgsSaveSize = 0;
9783 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
9784 VaArgOffset = -VarArgsSaveSize;
9790 LoongArchFI->setVarArgsFrameIndex(FI);
9798 VarArgsSaveSize += GRLenInBytes;
9803 for (
unsigned I = Idx;
I < ArgRegs.
size();
9804 ++
I, VaArgOffset += GRLenInBytes) {
9805 const Register Reg = RegInfo.createVirtualRegister(RC);
9806 RegInfo.addLiveIn(ArgRegs[
I], Reg);
9814 ->setValue((
Value *)
nullptr);
9815 OutChains.push_back(Store);
9817 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
9822 if (!OutChains.empty()) {
9823 OutChains.push_back(Chain);
9838 if (
N->getNumValues() != 1)
9840 if (!
N->hasNUsesOfValue(1, 0))
9843 SDNode *Copy = *
N->user_begin();
9849 if (Copy->getGluedNode())
9853 bool HasRet =
false;
9855 if (
Node->getOpcode() != LoongArchISD::RET)
9863 Chain = Copy->getOperand(0);
9868bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
9872 auto CalleeCC = CLI.CallConv;
9873 auto &Outs = CLI.Outs;
9875 auto CallerCC = Caller.getCallingConv();
9877 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
9886 for (
auto &Arg : Outs)
9887 if (Arg.Flags.isByVal())
9903 for (
auto &VA : ArgLocs)
9909 auto IsCallerStructRet = Caller.hasStructRetAttr();
9910 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
9911 if (IsCallerStructRet || IsCalleeStructRet)
9916 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
9917 if (CalleeCC != CallerCC) {
9918 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
9919 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
9945 MVT GRLenVT = Subtarget.getGRLenVT();
9957 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
9961 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
9967 "site marked musttail");
9974 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9976 if (!Flags.isByVal())
9980 unsigned Size = Flags.getByValSize();
9981 Align Alignment = Flags.getNonZeroByValAlign();
9988 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
9990 false,
nullptr, std::nullopt,
10002 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10005 SDValue ArgValue = OutVals[OutIdx];
10013 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10014 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10026 if (!StackPtr.getNode())
10038 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10052 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10072 const Argument *FormalArg =
nullptr;
10073 unsigned FilteredIdx = 0;
10074 for (
const auto &CallArg : CLI.
CB->
args()) {
10075 if (CallArg->getType()->isEmptyTy())
10077 if (FilteredIdx == CallArgIdx) {
10086 unsigned FormalArgIdx = CallArgIdx;
10088 FormalArgIdx = FormalArg->
getArgNo();
10092 if (Arg.getType()->isEmptyTy())
10094 if (FilteredIdx == CallArgIdx) {
10095 FormalArgIdx = Arg.getArgNo();
10108 SDValue IncomingPtr = CopyOp;
10125 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10126 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10127 SDValue PartValue = OutVals[OutIdx + 1];
10128 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10139 ArgValue = IncomingPtr;
10143 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10155 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10156 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10157 assert(ArgPartOffset == 0);
10162 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10163 SDValue PartValue = OutVals[OutIdx + 1];
10164 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10176 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10178 for (
const auto &Part : Parts) {
10179 SDValue PartValue = Part.first;
10180 SDValue PartOffset = Part.second;
10187 ArgValue = SpillSlot;
10194 if (Flags.isByVal())
10195 ArgValue = ByValArgs[j++];
10203 "Tail call not allowed if stack is used for passing parameters");
10206 if (!StackPtr.getNode())
10219 if (!MemOpChains.
empty())
10225 for (
auto &Reg : RegsToPass) {
10226 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10248 Ops.push_back(Chain);
10249 Ops.push_back(Callee);
10253 for (
auto &Reg : RegsToPass)
10254 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10259 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10260 assert(Mask &&
"Missing call preserved mask for calling convention");
10266 Ops.push_back(Glue);
10275 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10278 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10281 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10282 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10304 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10307 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10308 auto &VA = RVLocs[i];
10316 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10317 assert(VA.needsCustom());
10322 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10323 RetValue, RetValue2);
10336 const Type *RetTy)
const {
10338 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10340 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10344 Outs[i].Flags, CCInfo,
true,
nullptr))
10370 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10371 SDValue Val = OutVals[OutIdx];
10380 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10384 Register RegHi = RVLocs[++i].getLocReg();
10409 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10417 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10420 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10422 RequiredImm = (0b10101 << 8) | (V >> 8);
10423 return {
true, RequiredImm};
10424 }
else if (SplatBitSize == 32) {
10426 if (!(V & 0xFFFF00FF)) {
10427 RequiredImm = (0b10001 << 8) | (V >> 8);
10428 return {
true, RequiredImm};
10431 if (!(V & 0xFF00FFFF)) {
10432 RequiredImm = (0b10010 << 8) | (V >> 16);
10433 return {
true, RequiredImm};
10436 if (!(V & 0x00FFFFFF)) {
10437 RequiredImm = (0b10011 << 8) | (V >> 24);
10438 return {
true, RequiredImm};
10441 if ((V & 0xFFFF00FF) == 0xFF) {
10442 RequiredImm = (0b10110 << 8) | (V >> 8);
10443 return {
true, RequiredImm};
10446 if ((V & 0xFF00FFFF) == 0xFFFF) {
10447 RequiredImm = (0b10111 << 8) | (V >> 16);
10448 return {
true, RequiredImm};
10451 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
10453 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10454 return {
true, RequiredImm};
10456 }
else if (SplatBitSize == 64) {
10458 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
10459 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
10461 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10462 return {
true, RequiredImm};
10465 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
10466 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
10468 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
10469 return {
true, RequiredImm};
10472 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
10474 for (
int i = 0; i < 8; ++i) {
10476 if (
byte == 0 ||
byte == 0xFF)
10477 res |= ((
byte & 1) << i);
10482 return {
true, res};
10484 auto [IsSame, Suffix] = sameBitsPreByte(V);
10486 RequiredImm = (0b11001 << 8) | Suffix;
10487 return {
true, RequiredImm};
10490 return {
false, RequiredImm};
10495 if (!Subtarget.hasExtLSX())
10498 if (VT == MVT::f32) {
10499 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
10500 return (masked == 0x3e000000 || masked == 0x40000000);
10503 if (VT == MVT::f64) {
10504 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
10505 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
10511bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
10512 bool ForCodeSize)
const {
10514 if (VT == MVT::f32 && !Subtarget.hasBasicF())
10516 if (VT == MVT::f64 && !Subtarget.hasBasicD())
10518 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
10529bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
10539 Type *Ty =
I->getOperand(0)->getType();
10541 unsigned Size = Ty->getIntegerBitWidth();
10561 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
10566 if (Subtarget.hasExtLASX())
10568 else if (Subtarget.hasExtLSX())
10575 EVT VT =
Y.getValueType();
10578 return Subtarget.hasExtLSX() && VT.
isInteger();
10589 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
10590 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
10591 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
10592 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
10595 Info.memVT = MVT::i32;
10596 Info.ptrVal =
I.getArgOperand(0);
10598 Info.align =
Align(4);
10617 "Unable to expand");
10618 unsigned MinWordSize = 4;
10630 Value *AlignedAddr = Builder.CreateIntrinsic(
10631 Intrinsic::ptrmask, {PtrTy, IntTy},
10632 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
10635 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
10636 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
10637 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
10638 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
10639 Value *Mask = Builder.CreateShl(
10640 ConstantInt::get(WordType,
10641 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
10643 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
10644 Value *ValOperand_Shifted =
10645 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
10646 ShiftAmt,
"ValOperand_Shifted");
10649 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
10651 NewOperand = ValOperand_Shifted;
10654 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
10657 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
10658 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
10659 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
10678 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
10686 if (Subtarget.hasLAMCAS()) {
10708 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
10710 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
10712 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
10714 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
10716 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
10718 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
10720 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
10722 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
10732 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
10734 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
10736 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
10738 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
10740 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
10742 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
10744 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
10746 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
10758 if (Subtarget.hasLAMCAS())
10770 unsigned GRLen = Subtarget.getGRLen();
10772 Value *FailureOrdering =
10773 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
10774 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
10776 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
10777 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
10778 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
10779 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10782 Value *Result = Builder.CreateIntrinsic(
10783 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
10785 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10801 Builder.CreateNot(Mask,
"Inv_Mask"),
10808 unsigned GRLen = Subtarget.getGRLen();
10817 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
10818 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10819 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
10832 unsigned ValWidth =
10835 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
10836 Result = Builder.CreateCall(LlwOpScwLoop,
10837 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
10840 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
10844 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10867 const Constant *PersonalityFn)
const {
10868 return LoongArch::R4;
10872 const Constant *PersonalityFn)
const {
10873 return LoongArch::R5;
10884 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
10885 return RefinementSteps;
10890 assert(Subtarget.hasFrecipe() &&
10891 "Reciprocal estimate queried on unsupported target");
10902 return Subtarget.hasBasicD();
10906 return Subtarget.hasExtLSX();
10910 return Subtarget.hasExtLASX();
10919 int &RefinementSteps,
10920 bool &UseOneConstNR,
10921 bool Reciprocal)
const {
10923 "Enabled should never be Disabled here");
10925 if (!Subtarget.hasFrecipe())
10940 UseOneConstNR =
false;
10946 if (Reciprocal || RefinementSteps > 0)
10956 int &RefinementSteps)
const {
10958 "Enabled should never be Disabled here");
10960 if (!Subtarget.hasFrecipe())
10974 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
10982LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11002 if (Constraint.
size() == 1) {
11003 switch (Constraint[0]) {
11019 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11028 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11035std::pair<unsigned, const TargetRegisterClass *>
11036LoongArchTargetLowering::getRegForInlineAsmConstraint(
11040 if (Constraint.
size() == 1) {
11041 switch (Constraint[0]) {
11046 return std::make_pair(0U, &LoongArch::GPRRegClass);
11048 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11050 if (Subtarget.hasBasicF() && VT == MVT::f32)
11051 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11052 if (Subtarget.hasBasicD() && VT == MVT::f64)
11053 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11054 if (Subtarget.hasExtLSX() &&
11055 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11056 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11057 if (Subtarget.hasExtLASX() &&
11058 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11059 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11079 bool IsFP = Constraint[2] ==
'f';
11080 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11081 std::pair<unsigned, const TargetRegisterClass *>
R;
11086 unsigned RegNo =
R.first;
11087 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11088 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11089 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11090 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11100void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11104 if (Constraint.
size() == 1) {
11105 switch (Constraint[0]) {
11109 uint64_t CVal =
C->getSExtValue();
11112 Subtarget.getGRLenVT()));
11118 uint64_t CVal =
C->getSExtValue();
11121 Subtarget.getGRLenVT()));
11127 if (
C->getZExtValue() == 0)
11134 uint64_t CVal =
C->getZExtValue();
11147#define GET_REGISTER_MATCHER
11148#include "LoongArchGenAsmMatcher.inc"
11154 std::string NewRegName = Name.second.str();
11160 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11161 if (!ReservedRegs.
test(Reg))
11178 const APInt &Imm = ConstNode->getAPIntValue();
11180 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
11181 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
11184 if (ConstNode->hasOneUse() &&
11185 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
11186 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
11192 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
11193 unsigned Shifts = Imm.countr_zero();
11199 APInt ImmPop = Imm.ashr(Shifts);
11200 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11204 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
11205 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
11206 (ImmSmall - Imm).isPowerOf2())
11216 Type *Ty,
unsigned AS,
11235 switch (AM.
Scale) {
11271 EVT MemVT = LD->getMemoryVT();
11272 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11283 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11292 if (
Y.getValueType().isVector())
11304 Type *Ty,
bool IsSigned)
const {
11305 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11314 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11315 Type.getSizeInBits() < Subtarget.getGRLen()))
11325 Align &PrefAlign)
const {
11329 if (Subtarget.is64Bit()) {
11331 PrefAlign =
Align(8);
11334 PrefAlign =
Align(4);
11349bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11351 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
11352 bool IsABIRegCopy = CC.has_value();
11355 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11356 PartVT == MVT::f32) {
11371SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11373 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11374 bool IsABIRegCopy = CC.has_value();
11376 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11377 PartVT == MVT::f32) {
11394 if (VT == MVT::f16 && Subtarget.hasBasicF())
11400unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11403 if (VT == MVT::f16 && Subtarget.hasBasicF())
11412 unsigned Opc =
Op.getOpcode();
11417 case LoongArchISD::VPICK_ZEXT_ELT: {
11431 unsigned Depth)
const {
11432 EVT VT =
Op.getValueType();
11434 unsigned Opc =
Op.getOpcode();
11438 case LoongArchISD::CRC_W_B_W:
11439 case LoongArchISD::CRC_W_H_W:
11440 case LoongArchISD::CRCC_W_B_W:
11441 case LoongArchISD::CRCC_W_H_W: {
11443 APInt DemandedSrcBits =
11445 Opc == LoongArchISD::CRCC_W_B_W)
11449 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
11451 case LoongArchISD::VMSKLTZ:
11452 case LoongArchISD::XVMSKLTZ: {
11454 MVT SrcVT = Src.getSimpleValueType();
11459 if (OriginalDemandedBits.
countr_zero() >= NumElts)
11463 APInt KnownUndef, KnownZero;
11479 if (KnownSrc.
One[SrcBits - 1])
11481 else if (KnownSrc.
Zero[SrcBits - 1])
11486 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
11493 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
11516 unsigned Index)
const {
11525 unsigned Index)
const {
11529 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
11544 Align StackAlign)
const {
11548 unsigned StackProbeSize =
11552 return StackProbeSize ? StackProbeSize : StackAlign.
value();
11556LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
11570 const EVT VT =
Op.getValueType();
11581 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
11591 const Register TargetReg =
MI.getOperand(0).getReg();
11594 const bool IsLA64 = Subtarget.is64Bit();
11595 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
11602 MF.
insert(MBBInsertPoint, LoopTestMBB);
11605 MF.
insert(MBBInsertPoint, ExitMBB);
11616 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
11622 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
11628 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
11643 MBB->addSuccessor(LoopTestMBB);
11645 MI.eraseFromParent();
11647 return ExitMBB->
begin()->getParent();
static MCRegister MatchRegisterName(StringRef Name)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSELECT_CCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue performHorizWideningCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static SDValue performDemandedBitsCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue matchLowHalfOf128BitLanes(SDValue N)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue matchDeinterleaveBuildVector(SDValue N, unsigned &StartIndex)
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt 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.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type count() const
Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void setIncomingIndirectArg(unsigned ArgIndex, Register Reg)
void addSExt32Register(Register Reg)
Register getIncomingIndirectArg(unsigned ArgIndex) const
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
unsigned getBitWidth() const
Get the bit width of this value.
void resetAll()
Resets the known state of all bits.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)