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}) {
354 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
356 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
358 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
386 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
387 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
403 if (Subtarget.hasExtLASX()) {
404 for (
MVT VT : LASXVTs) {
419 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
444 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
446 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
448 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
452 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
473 if (Subtarget.hasBasicF()) {
484 if (Subtarget.hasExtLSX()) {
490 if (Subtarget.hasExtLASX()) {
517 if (Subtarget.hasLAMCAS())
520 if (Subtarget.hasSCQ()) {
540 switch (
Op.getOpcode()) {
542 return lowerATOMIC_FENCE(
Op, DAG);
544 return lowerEH_DWARF_CFA(
Op, DAG);
546 return lowerGlobalAddress(
Op, DAG);
548 return lowerGlobalTLSAddress(
Op, DAG);
550 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
552 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
554 return lowerINTRINSIC_VOID(
Op, DAG);
556 return lowerBlockAddress(
Op, DAG);
558 return lowerJumpTable(
Op, DAG);
560 return lowerShiftLeftParts(
Op, DAG);
562 return lowerShiftRightParts(
Op, DAG,
true);
564 return lowerShiftRightParts(
Op, DAG,
false);
566 return lowerConstantPool(
Op, DAG);
568 return lowerFP_TO_SINT(
Op, DAG);
570 return lowerBITCAST(
Op, DAG);
572 return lowerUINT_TO_FP(
Op, DAG);
574 return lowerSINT_TO_FP(
Op, DAG);
576 return lowerVASTART(
Op, DAG);
578 return lowerFRAMEADDR(
Op, DAG);
580 return lowerRETURNADDR(
Op, DAG);
582 return lowerWRITE_REGISTER(
Op, DAG);
584 return lowerINSERT_VECTOR_ELT(
Op, DAG);
586 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
588 return lowerBUILD_VECTOR(
Op, DAG);
590 return lowerCONCAT_VECTORS(
Op, DAG);
592 return lowerVECTOR_SHUFFLE(
Op, DAG);
594 return lowerBITREVERSE(
Op, DAG);
596 return lowerSCALAR_TO_VECTOR(
Op, DAG);
598 return lowerPREFETCH(
Op, DAG);
600 return lowerSELECT(
Op, DAG);
602 return lowerBRCOND(
Op, DAG);
604 return lowerFP_TO_FP16(
Op, DAG);
606 return lowerFP16_TO_FP(
Op, DAG);
608 return lowerFP_TO_BF16(
Op, DAG);
610 return lowerBF16_TO_FP(
Op, DAG);
612 return lowerVECREDUCE_ADD(
Op, DAG);
615 return lowerRotate(
Op, DAG);
623 return lowerVECREDUCE(
Op, DAG);
625 return lowerConstantFP(
Op, DAG);
627 return lowerSETCC(
Op, DAG);
629 return lowerFP_ROUND(
Op, DAG);
638 EVT VT = V.getValueType();
644 return V.getOperand(0);
648 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
650 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
660 if (!V->isOnlyUserOf(SplatValue.getNode()))
664 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
672 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
700 (
N->getOpcode() == LoongArchISD::VPACKEV)) &&
707 if (Opcode0 != Opcode1)
710 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
717 EVT VT =
N.getValueType();
731 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
732 SSVT0 == MVT::v4f64) {
751 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
752 Opcode0 == LoongArchISD::VFCVT) {
758 if (Subtarget.hasExtLSX() && (VT == MVT::v2i64 || VT == MVT::v2f64) &&
759 SVT0 == MVT::v4f32 && SSVT0 == MVT::v2f64) {
773 MVT VT =
Op.getSimpleValueType();
774 MVT SVT =
In.getSimpleValueType();
776 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
787 EVT VT =
Op.getValueType();
792 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
793 (VT == MVT::f64 && Subtarget.hasBasicD()));
810 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
820 if (Subtarget.is64Bit())
822 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
823 : LoongArchISD::MOVGR2FR_W,
827 if (Subtarget.is64Bit()) {
829 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
833 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
845 EVT ResultVT =
Op.getValueType();
846 EVT OperandVT =
Op.getOperand(0).getValueType();
851 if (ResultVT == SetCCResultVT)
854 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
855 "SETCC operands must have the same type!");
859 Op.getOperand(1),
Op.getOperand(2));
861 if (ResultVT.
bitsGT(SetCCResultVT))
863 else if (ResultVT.
bitsLT(SetCCResultVT))
881 MVT OpVT =
Op.getSimpleValueType();
888 unsigned LegalVecSize = 128;
889 bool isLASX256Vector =
899 if (isLASX256Vector) {
904 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
907 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
910 if (isLASX256Vector) {
936 MVT OpVT =
Op.getSimpleValueType();
949 MVT GRLenVT = Subtarget.getGRLenVT();
951 for (
int i = NumEles; i > 1; i /= 2) {
954 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
963 unsigned IsData =
Op.getConstantOperandVal(4);
968 return Op.getOperand(0);
975 MVT VT =
Op.getSimpleValueType();
981 unsigned Opcode =
Op.getOpcode();
984 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
990 CstSplatValue =
C->getAPIntValue();
999 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1003 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1019 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1035 if (
LHS == LHS2 &&
RHS == RHS2) {
1040 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1048 return std::nullopt;
1056 MVT VT =
N->getSimpleValueType(0);
1087 if (~TrueVal == FalseVal) {
1127 unsigned SelOpNo = 0;
1137 unsigned ConstSelOpNo = 1;
1138 unsigned OtherSelOpNo = 2;
1145 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1150 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1156 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1158 std::swap(NewConstOps[0], NewConstOps[1]);
1170 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1172 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1175 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1176 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1196 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1210 int64_t
C = RHSC->getSExtValue();
1253 MVT VT =
Op.getSimpleValueType();
1254 MVT GRLenVT = Subtarget.getGRLenVT();
1259 if (
Op.hasOneUse()) {
1260 unsigned UseOpc =
Op->user_begin()->getOpcode();
1262 SDNode *BinOp = *
Op->user_begin();
1269 return lowerSELECT(NewSel, DAG);
1286 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1309 if (TrueVal - 1 == FalseVal)
1311 if (TrueVal + 1 == FalseVal)
1318 RHS == TrueV &&
LHS == FalseV) {
1343 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1350 MVT GRLenVT = Subtarget.getGRLenVT();
1361 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1362 Op.getOperand(0),
LHS,
RHS, TargetCC,
1365 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1366 Op.getOperand(0), CondV,
Op.getOperand(2));
1370 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1376LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1379 MVT OpVT =
Op.getSimpleValueType();
1390 EVT ResTy =
Op->getValueType(0);
1395 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1405 for (
unsigned int i = 0; i < NewEltNum; i++) {
1408 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1409 ? (
unsigned)LoongArchISD::BITREV_8B
1427 for (
unsigned int i = 0; i < NewEltNum; i++)
1428 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1429 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1447 if (EltBits > 32 || EltBits == 1)
1475 int MaskOffset,
const APInt &Zeroable) {
1476 int Size = Mask.size();
1477 unsigned SizeInBits =
Size * ScalarSizeInBits;
1479 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1480 for (
int i = 0; i <
Size; i += Scale)
1481 for (
int j = 0; j < Shift; ++j)
1482 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1490 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1491 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1496 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1497 for (
int i = 0; i !=
Size; i += Scale) {
1498 unsigned Pos =
Left ? i + Shift : i;
1499 unsigned Low =
Left ? i : i + Shift;
1500 unsigned Len = Scale - Shift;
1505 int ShiftEltBits = ScalarSizeInBits * Scale;
1506 bool ByteShift = ShiftEltBits > 64;
1507 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1508 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1509 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1513 Scale = ByteShift ? Scale / 2 : Scale;
1519 return (
int)ShiftAmt;
1522 unsigned MaxWidth = 128;
1523 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1524 for (
int Shift = 1; Shift != Scale; ++Shift)
1525 for (
bool Left : {
true,
false})
1526 if (CheckZeros(Shift, Scale,
Left)) {
1527 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1552 const APInt &Zeroable) {
1553 int Size = Mask.size();
1567 Mask,
Size, Zeroable);
1575 "Illegal integer vector type");
1584template <
typename ValType>
1587 unsigned CheckStride,
1589 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1593 if (*
I != -1 && *
I != ExpectedIndex)
1595 ExpectedIndex += ExpectedIndexStride;
1599 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1611 int Size = Mask.size();
1621 int ScalarSizeInBits = VectorSizeInBits /
Size;
1622 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1623 (void)ScalarSizeInBits;
1625 for (
int i = 0; i <
Size; ++i) {
1631 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1648 RepeatedMask.
assign(LaneSize, -1);
1649 int Size = Mask.size();
1650 for (
int i = 0; i <
Size; ++i) {
1651 assert(Mask[i] == -1 || Mask[i] >= 0);
1654 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1661 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1662 if (RepeatedMask[i % LaneSize] < 0)
1664 RepeatedMask[i % LaneSize] = LocalM;
1665 else if (RepeatedMask[i % LaneSize] != LocalM)
1682 int NumElts = RepeatedMask.
size();
1684 int Scale = 16 / NumElts;
1686 for (
int i = 0; i < NumElts; ++i) {
1687 int M = RepeatedMask[i];
1688 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1689 "Unexpected mask index.");
1694 int StartIdx = i - (M % NumElts);
1701 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1704 Rotation = CandidateRotation;
1705 else if (Rotation != CandidateRotation)
1709 SDValue MaskV = M < NumElts ? V1 : V2;
1720 else if (TargetV != MaskV)
1725 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1726 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1735 return Rotation * Scale;
1754 if (ByteRotation <= 0)
1761 int LoByteShift = 16 - ByteRotation;
1762 int HiByteShift = ByteRotation;
1785 const APInt &Zeroable) {
1799 for (
int i = 0; i < NumElements; i++) {
1803 if (i % Scale != 0) {
1814 SDValue V = M < NumElements ? V1 : V2;
1815 M = M % NumElements;
1818 Offset = M - (i / Scale);
1821 if (
Offset % (NumElements / Scale))
1823 }
else if (InputV != V)
1826 if (M != (
Offset + (i / Scale)))
1836 unsigned VilVLoHi = LoongArchISD::VILVL;
1837 if (
Offset >= (NumElements / 2)) {
1838 VilVLoHi = LoongArchISD::VILVH;
1839 Offset -= (NumElements / 2);
1846 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1850 }
while (Scale > 1);
1856 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1857 NumExtElements *= 2) {
1877 int SplatIndex = -1;
1878 for (
const auto &M : Mask) {
1885 if (SplatIndex == -1)
1888 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1890 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
1920 unsigned SubVecSize = 4;
1921 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1924 int SubMask[4] = {-1, -1, -1, -1};
1925 for (
unsigned i = 0; i < SubVecSize; ++i) {
1926 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1932 M -= 4 * (j / SubVecSize);
1933 if (M < 0 || M >= 4)
1939 if (SubMask[i] == -1)
1943 else if (M != -1 && M != SubMask[i])
1950 for (
int i = SubVecSize - 1; i >= 0; --i) {
1963 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1964 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
1967 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
1985 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
1994 for (
int i = 0; i < WidenNumElts; ++i)
1995 WidenMask[i] = WidenNumElts - 1 - i;
2003 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2027 const auto &Begin = Mask.begin();
2028 const auto &End = Mask.end();
2029 SDValue OriV1 = V1, OriV2 = V2;
2045 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
2067 const auto &Begin = Mask.begin();
2068 const auto &End = Mask.end();
2069 SDValue OriV1 = V1, OriV2 = V2;
2085 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2108 const auto &Begin = Mask.begin();
2109 const auto &End = Mask.end();
2110 unsigned HalfSize = Mask.size() / 2;
2111 SDValue OriV1 = V1, OriV2 = V2;
2128 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2151 const auto &Begin = Mask.begin();
2152 const auto &End = Mask.end();
2153 SDValue OriV1 = V1, OriV2 = V2;
2169 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2191 const auto &Begin = Mask.begin();
2192 const auto &Mid = Mask.begin() + Mask.size() / 2;
2193 const auto &End = Mask.end();
2194 SDValue OriV1 = V1, OriV2 = V2;
2211 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2233 const auto &Begin = Mask.begin();
2234 const auto &Mid = Mask.begin() + Mask.size() / 2;
2235 const auto &End = Mask.end();
2236 SDValue OriV1 = V1, OriV2 = V2;
2252 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2278 if (Mask.size() != NumElts)
2281 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2284 for (
unsigned i = 0; i < NumElts; ++i) {
2287 if (Mask[i] !=
int(
Base + i)) {
2300 int DiffMask = Mask[DiffPos];
2301 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2307 if (
unsigned(DiffMask) < NumElts) {
2312 SrcIdx =
unsigned(DiffMask) - NumElts;
2328 if (
SDValue Result = tryLowerToExtrAndIns(0))
2330 return tryLowerToExtrAndIns(NumElts);
2356 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2369 "Vector type is unsupported for lsx!");
2371 "Two operands have different types!");
2373 "Unexpected mask size for shuffle!");
2374 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2376 APInt KnownUndef, KnownZero;
2378 APInt Zeroable = KnownUndef | KnownZero;
2448 int SplatIndex = -1;
2449 for (
const auto &M : Mask) {
2456 if (SplatIndex == -1)
2459 const auto &Begin = Mask.begin();
2460 const auto &End = Mask.end();
2461 int HalfSize = Mask.size() / 2;
2463 if (SplatIndex >= HalfSize)
2466 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2470 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2484 if (Mask.size() <= 4)
2495 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2498 unsigned MaskImm = 0;
2499 for (
unsigned i = 0; i < Mask.size(); ++i) {
2502 MaskImm |= Mask[i] << (i * 2);
2505 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2514 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2518 unsigned HalfSize = NumElts / 2;
2519 bool FrontLo =
true, FrontHi =
true;
2520 bool BackLo =
true, BackHi =
true;
2522 auto inRange = [](
int val,
int low,
int high) {
2523 return (val == -1) || (val >= low && val < high);
2526 for (
unsigned i = 0; i < HalfSize; ++i) {
2527 int Fronti = Mask[i];
2528 int Backi = Mask[i + HalfSize];
2530 FrontLo &=
inRange(Fronti, 0, HalfSize);
2531 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2532 BackLo &=
inRange(Backi, 0, HalfSize);
2533 BackHi &=
inRange(Backi, HalfSize, NumElts);
2539 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2544 for (
unsigned i = 0; i < NumElts; ++i)
2549 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2571 const auto &Begin = Mask.begin();
2572 const auto &End = Mask.end();
2573 unsigned HalfSize = Mask.size() / 2;
2574 unsigned LeftSize = HalfSize / 2;
2575 SDValue OriV1 = V1, OriV2 = V2;
2582 Mask.size() + HalfSize - LeftSize, 1) &&
2584 Mask.size() + HalfSize + LeftSize, 1))
2595 Mask.size() + HalfSize - LeftSize, 1) &&
2597 Mask.size() + HalfSize + LeftSize, 1))
2602 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2610 const auto &Begin = Mask.begin();
2611 const auto &End = Mask.end();
2612 unsigned HalfSize = Mask.size() / 2;
2613 SDValue OriV1 = V1, OriV2 = V2;
2620 Mask.size() + HalfSize, 1))
2631 Mask.size() + HalfSize, 1))
2636 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2644 const auto &Begin = Mask.begin();
2645 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2646 const auto &Mid = Mask.begin() + Mask.size() / 2;
2647 const auto &RightMid = Mask.end() - Mask.size() / 4;
2648 const auto &End = Mask.end();
2649 unsigned HalfSize = Mask.size() / 2;
2650 SDValue OriV1 = V1, OriV2 = V2;
2671 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2679 const auto &Begin = Mask.begin();
2680 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2681 const auto &Mid = Mask.begin() + Mask.size() / 2;
2682 const auto &RightMid = Mask.end() - Mask.size() / 4;
2683 const auto &End = Mask.end();
2684 unsigned HalfSize = Mask.size() / 2;
2685 SDValue OriV1 = V1, OriV2 = V2;
2707 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2716 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2721 int MaskSize = Mask.size();
2727 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2729 for (
int i = 0; i < MaskSize; ++i) {
2730 if (Mask[i] ==
Base + i || Mask[i] == -1)
2732 if (Mask[i] != Replaced)
2743 int Idx = checkReplaceOne(0, MaskSize);
2745 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
2749 Idx = checkReplaceOne(MaskSize, 0);
2751 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
2762 int MaskSize = Mask.size();
2763 int HalfSize = Mask.size() / 2;
2764 const auto &Begin = Mask.begin();
2765 const auto &Mid = Mask.begin() + HalfSize;
2766 const auto &End = Mask.end();
2778 for (
auto it = Begin; it < Mid; it++) {
2781 else if ((*it >= 0 && *it < HalfSize) ||
2782 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2783 int M = *it < HalfSize ? *it : *it - HalfSize;
2788 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2790 for (
auto it = Mid; it < End; it++) {
2793 else if ((*it >= HalfSize && *it < MaskSize) ||
2794 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2795 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2800 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2804 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2832 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2834 int MaskSize = Mask.size();
2835 int HalfSize = Mask.size() / 2;
2838 HalfMaskType preMask =
None, postMask =
None;
2840 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2841 return M < 0 || (M >= 0 && M < HalfSize) ||
2842 (M >= MaskSize && M < MaskSize + HalfSize);
2844 preMask = HighLaneTy;
2845 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2846 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2847 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2849 preMask = LowLaneTy;
2851 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2852 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2853 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2855 postMask = LowLaneTy;
2856 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2857 return M < 0 || (M >= 0 && M < HalfSize) ||
2858 (M >= MaskSize && M < MaskSize + HalfSize);
2860 postMask = HighLaneTy;
2868 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2871 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2873 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2879 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2884 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2885 *it = *it < 0 ? *it : *it - HalfSize;
2887 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2888 *it = *it < 0 ? *it : *it + HalfSize;
2890 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2892 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2898 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2903 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2904 *it = *it < 0 ? *it : *it - HalfSize;
2906 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2908 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2914 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2919 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2920 *it = *it < 0 ? *it : *it + HalfSize;
2945 int Size = Mask.size();
2946 int LaneSize =
Size / 2;
2948 bool LaneCrossing[2] = {
false,
false};
2949 for (
int i = 0; i <
Size; ++i)
2950 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2951 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2954 if (!LaneCrossing[0] && !LaneCrossing[1])
2958 InLaneMask.
assign(Mask.begin(), Mask.end());
2959 for (
int i = 0; i <
Size; ++i) {
2960 int &M = InLaneMask[i];
2963 if (((M %
Size) / LaneSize) != (i / LaneSize))
2964 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2969 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2984 "Vector type is unsupported for lasx!");
2986 "Two operands have different types!");
2988 "Unexpected mask size for shuffle!");
2989 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2990 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2992 APInt KnownUndef, KnownZero;
2994 APInt Zeroable = KnownUndef | KnownZero;
3071 ArrayRef<int> OrigMask = SVOp->
getMask();
3074 MVT VT =
Op.getSimpleValueType();
3078 bool V1IsUndef = V1.
isUndef();
3079 bool V2IsUndef = V2.
isUndef();
3080 if (V1IsUndef && V2IsUndef)
3093 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3094 SmallVector<int, 8> NewMask(OrigMask);
3095 for (
int &M : NewMask)
3096 if (M >= NumElements)
3102 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3103 (void)MaskUpperLimit;
3105 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3106 "Out of bounds shuffle index");
3128 std::tie(Res, Chain) =
3129 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3130 if (Subtarget.is64Bit())
3131 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3143 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3147 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3148 CallOptions,
DL, Chain);
3154 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3160 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3161 if (Subtarget.is64Bit())
3162 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3168 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3169 MVT VT =
Op.getSimpleValueType();
3174 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3195 "Unsupported vector type for broadcast.");
3198 bool IsIdeneity =
true;
3200 for (
int i = 0; i !=
NumOps; i++) {
3202 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3214 auto ExtType = LN->getExtensionType();
3219 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3224 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3242 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3256 EVT ResTy,
unsigned first) {
3259 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3262 Node->op_begin() + first + NumElts);
3271 MVT VT =
Node->getSimpleValueType(0);
3272 EVT ResTy =
Op->getValueType(0);
3275 APInt SplatValue, SplatUndef;
3276 unsigned SplatBitSize;
3279 bool UseSameConstant =
true;
3284 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3285 (!Subtarget.hasExtLASX() || !Is256Vec))
3291 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3293 SplatBitSize <= 64) {
3295 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3299 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3306 if ((Is128Vec && ResTy == MVT::v4i32) ||
3307 (Is256Vec && ResTy == MVT::v8i32))
3313 switch (SplatBitSize) {
3317 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3320 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3323 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3326 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3334 if (ViaVecTy != ResTy)
3343 for (
unsigned i = 0; i < NumElts; ++i) {
3348 ConstantValue = Opi;
3349 else if (ConstantValue != Opi)
3350 UseSameConstant =
false;
3355 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3357 for (
unsigned i = 0; i < NumElts; ++i) {
3375 BitVector UndefElements;
3376 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3377 UndefElements.
count() == 0) {
3381 EVT FillTy = Is256Vec
3387 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3390 unsigned SplatLen = NumElts / SeqLen;
3396 if (SplatEltTy == MVT::i128)
3397 SplatTy = MVT::v4i64;
3405 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3406 : LoongArchISD::XVREPLVE0,
3407 DL, SplatTy, SrcVec);
3409 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3422 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3423 ResTy == MVT::v4f64) {
3424 unsigned NonUndefCount = 0;
3425 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3426 if (!
Node->getOperand(i).isUndef()) {
3428 if (NonUndefCount > 1)
3432 if (NonUndefCount == 1)
3445 VecTy, NumElts / 2);
3456 MVT ResVT =
Op.getSimpleValueType();
3460 unsigned NumFreezeUndef = 0;
3461 unsigned NumZero = 0;
3462 unsigned NumNonZero = 0;
3463 unsigned NonZeros = 0;
3464 SmallSet<SDValue, 4> Undefs;
3465 for (
unsigned i = 0; i != NumOperands; ++i) {
3480 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3487 if (NumNonZero > 2) {
3491 Ops.slice(0, NumOperands / 2));
3493 Ops.slice(NumOperands / 2));
3506 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3508 for (
unsigned i = 0; i != NumOperands; ++i) {
3509 if ((NonZeros & (1 << i)) == 0)
3520LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3522 MVT EltVT =
Op.getSimpleValueType();
3527 MVT GRLenVT = Subtarget.getGRLenVT();
3555 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3559 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3561 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3570 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3579LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3581 MVT VT =
Op.getSimpleValueType();
3604 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3606 for (
unsigned i = 0; i < NumElts; ++i) {
3614 for (
unsigned i = 0; i < NumElts; ++i) {
3623 for (
unsigned i = 0; i < NumElts; ++i)
3655 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3657 "On LA64, only 64-bit registers can be written.");
3658 return Op.getOperand(0);
3661 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3663 "On LA32, only 32-bit registers can be written.");
3664 return Op.getOperand(0);
3674 "be a constant integer");
3680 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3681 EVT VT =
Op.getValueType();
3684 unsigned Depth =
Op.getConstantOperandVal(0);
3685 int GRLenInBytes = Subtarget.getGRLen() / 8;
3688 int Offset = -(GRLenInBytes * 2);
3700 if (
Op.getConstantOperandVal(0) != 0) {
3702 "return address can only be determined for the current frame");
3708 MVT GRLenVT = Subtarget.getGRLenVT();
3720 auto Size = Subtarget.getGRLen() / 8;
3728 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3738 MachinePointerInfo(SV));
3743 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3744 !Subtarget.hasBasicD() &&
"unexpected target features");
3750 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3754 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
3764 EVT RetVT =
Op.getValueType();
3770 std::tie(Result, Chain) =
3777 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3778 !Subtarget.hasBasicD() &&
"unexpected target features");
3789 EVT RetVT =
Op.getValueType();
3795 std::tie(Result, Chain) =
3804 EVT VT =
Op.getValueType();
3808 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3809 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3811 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
3813 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3816 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
3830 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3831 !Subtarget.hasBasicD()) {
3833 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
3855 N->getOffset(), Flags);
3863template <
class NodeTy>
3866 bool IsLocal)
const {
3877 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3958 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3960 const GlobalValue *GV =
N->getGlobal();
3972 unsigned Opc,
bool UseGOT,
3976 MVT GRLenVT = Subtarget.getGRLenVT();
3990 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4028 Args.emplace_back(Load, CallTy);
4031 TargetLowering::CallLoweringInfo CLI(DAG);
4046 const GlobalValue *GV =
N->getGlobal();
4060LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4067 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4070 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4083 return getDynamicTLSAddr(
N, DAG,
4084 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4085 : LoongArch::PseudoLA_TLS_GD,
4092 return getDynamicTLSAddr(
N, DAG,
4093 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4094 : LoongArch::PseudoLA_TLS_LD,
4099 return getStaticTLSAddr(
N, DAG,
4100 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4101 : LoongArch::PseudoLA_TLS_IE,
4108 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4112 return getTLSDescAddr(
N, DAG,
4113 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4114 : LoongArch::PseudoLA_TLS_DESC,
4118template <
unsigned N>
4123 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4124 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4126 ": argument out of range.");
4133LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4135 switch (
Op.getConstantOperandVal(0)) {
4138 case Intrinsic::thread_pointer: {
4142 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4143 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4144 case Intrinsic::loongarch_lsx_vreplvei_d:
4145 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4147 case Intrinsic::loongarch_lsx_vreplvei_w:
4148 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4149 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4150 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4151 case Intrinsic::loongarch_lasx_xvpickve_d:
4152 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4154 case Intrinsic::loongarch_lasx_xvinsve0_d:
4156 case Intrinsic::loongarch_lsx_vsat_b:
4157 case Intrinsic::loongarch_lsx_vsat_bu:
4158 case Intrinsic::loongarch_lsx_vrotri_b:
4159 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4160 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4161 case Intrinsic::loongarch_lsx_vsrlri_b:
4162 case Intrinsic::loongarch_lsx_vsrari_b:
4163 case Intrinsic::loongarch_lsx_vreplvei_h:
4164 case Intrinsic::loongarch_lasx_xvsat_b:
4165 case Intrinsic::loongarch_lasx_xvsat_bu:
4166 case Intrinsic::loongarch_lasx_xvrotri_b:
4167 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4168 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4169 case Intrinsic::loongarch_lasx_xvsrlri_b:
4170 case Intrinsic::loongarch_lasx_xvsrari_b:
4171 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4172 case Intrinsic::loongarch_lasx_xvpickve_w:
4173 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4175 case Intrinsic::loongarch_lasx_xvinsve0_w:
4177 case Intrinsic::loongarch_lsx_vsat_h:
4178 case Intrinsic::loongarch_lsx_vsat_hu:
4179 case Intrinsic::loongarch_lsx_vrotri_h:
4180 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4181 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4182 case Intrinsic::loongarch_lsx_vsrlri_h:
4183 case Intrinsic::loongarch_lsx_vsrari_h:
4184 case Intrinsic::loongarch_lsx_vreplvei_b:
4185 case Intrinsic::loongarch_lasx_xvsat_h:
4186 case Intrinsic::loongarch_lasx_xvsat_hu:
4187 case Intrinsic::loongarch_lasx_xvrotri_h:
4188 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4189 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4190 case Intrinsic::loongarch_lasx_xvsrlri_h:
4191 case Intrinsic::loongarch_lasx_xvsrari_h:
4192 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4194 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4195 case Intrinsic::loongarch_lsx_vsrani_b_h:
4196 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4197 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4198 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4199 case Intrinsic::loongarch_lsx_vssrani_b_h:
4200 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4201 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4202 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4203 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4204 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4205 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4206 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4207 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4208 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4209 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4210 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4211 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4212 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4213 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4214 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4215 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4216 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4217 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4219 case Intrinsic::loongarch_lsx_vsat_w:
4220 case Intrinsic::loongarch_lsx_vsat_wu:
4221 case Intrinsic::loongarch_lsx_vrotri_w:
4222 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4223 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4224 case Intrinsic::loongarch_lsx_vsrlri_w:
4225 case Intrinsic::loongarch_lsx_vsrari_w:
4226 case Intrinsic::loongarch_lsx_vslei_bu:
4227 case Intrinsic::loongarch_lsx_vslei_hu:
4228 case Intrinsic::loongarch_lsx_vslei_wu:
4229 case Intrinsic::loongarch_lsx_vslei_du:
4230 case Intrinsic::loongarch_lsx_vslti_bu:
4231 case Intrinsic::loongarch_lsx_vslti_hu:
4232 case Intrinsic::loongarch_lsx_vslti_wu:
4233 case Intrinsic::loongarch_lsx_vslti_du:
4234 case Intrinsic::loongarch_lsx_vbsll_v:
4235 case Intrinsic::loongarch_lsx_vbsrl_v:
4236 case Intrinsic::loongarch_lasx_xvsat_w:
4237 case Intrinsic::loongarch_lasx_xvsat_wu:
4238 case Intrinsic::loongarch_lasx_xvrotri_w:
4239 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4240 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4241 case Intrinsic::loongarch_lasx_xvsrlri_w:
4242 case Intrinsic::loongarch_lasx_xvsrari_w:
4243 case Intrinsic::loongarch_lasx_xvslei_bu:
4244 case Intrinsic::loongarch_lasx_xvslei_hu:
4245 case Intrinsic::loongarch_lasx_xvslei_wu:
4246 case Intrinsic::loongarch_lasx_xvslei_du:
4247 case Intrinsic::loongarch_lasx_xvslti_bu:
4248 case Intrinsic::loongarch_lasx_xvslti_hu:
4249 case Intrinsic::loongarch_lasx_xvslti_wu:
4250 case Intrinsic::loongarch_lasx_xvslti_du:
4251 case Intrinsic::loongarch_lasx_xvbsll_v:
4252 case Intrinsic::loongarch_lasx_xvbsrl_v:
4254 case Intrinsic::loongarch_lsx_vseqi_b:
4255 case Intrinsic::loongarch_lsx_vseqi_h:
4256 case Intrinsic::loongarch_lsx_vseqi_w:
4257 case Intrinsic::loongarch_lsx_vseqi_d:
4258 case Intrinsic::loongarch_lsx_vslei_b:
4259 case Intrinsic::loongarch_lsx_vslei_h:
4260 case Intrinsic::loongarch_lsx_vslei_w:
4261 case Intrinsic::loongarch_lsx_vslei_d:
4262 case Intrinsic::loongarch_lsx_vslti_b:
4263 case Intrinsic::loongarch_lsx_vslti_h:
4264 case Intrinsic::loongarch_lsx_vslti_w:
4265 case Intrinsic::loongarch_lsx_vslti_d:
4266 case Intrinsic::loongarch_lasx_xvseqi_b:
4267 case Intrinsic::loongarch_lasx_xvseqi_h:
4268 case Intrinsic::loongarch_lasx_xvseqi_w:
4269 case Intrinsic::loongarch_lasx_xvseqi_d:
4270 case Intrinsic::loongarch_lasx_xvslei_b:
4271 case Intrinsic::loongarch_lasx_xvslei_h:
4272 case Intrinsic::loongarch_lasx_xvslei_w:
4273 case Intrinsic::loongarch_lasx_xvslei_d:
4274 case Intrinsic::loongarch_lasx_xvslti_b:
4275 case Intrinsic::loongarch_lasx_xvslti_h:
4276 case Intrinsic::loongarch_lasx_xvslti_w:
4277 case Intrinsic::loongarch_lasx_xvslti_d:
4279 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4280 case Intrinsic::loongarch_lsx_vsrani_h_w:
4281 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4282 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4283 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4284 case Intrinsic::loongarch_lsx_vssrani_h_w:
4285 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4286 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4287 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4288 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4289 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4290 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4291 case Intrinsic::loongarch_lsx_vfrstpi_b:
4292 case Intrinsic::loongarch_lsx_vfrstpi_h:
4293 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4294 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4295 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4296 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4297 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4298 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4299 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4300 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4301 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4302 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4303 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4304 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4305 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4306 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4308 case Intrinsic::loongarch_lsx_vsat_d:
4309 case Intrinsic::loongarch_lsx_vsat_du:
4310 case Intrinsic::loongarch_lsx_vrotri_d:
4311 case Intrinsic::loongarch_lsx_vsrlri_d:
4312 case Intrinsic::loongarch_lsx_vsrari_d:
4313 case Intrinsic::loongarch_lasx_xvsat_d:
4314 case Intrinsic::loongarch_lasx_xvsat_du:
4315 case Intrinsic::loongarch_lasx_xvrotri_d:
4316 case Intrinsic::loongarch_lasx_xvsrlri_d:
4317 case Intrinsic::loongarch_lasx_xvsrari_d:
4319 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4320 case Intrinsic::loongarch_lsx_vsrani_w_d:
4321 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4322 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4323 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4324 case Intrinsic::loongarch_lsx_vssrani_w_d:
4325 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4326 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4327 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4328 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4329 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4330 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4331 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4332 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4333 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4334 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4335 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4336 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4337 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4338 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4339 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4340 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4341 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4342 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4344 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4345 case Intrinsic::loongarch_lsx_vsrani_d_q:
4346 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4347 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4348 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4349 case Intrinsic::loongarch_lsx_vssrani_d_q:
4350 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4351 case Intrinsic::loongarch_lsx_vssrani_du_q:
4352 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4353 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4354 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4355 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4356 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4357 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4358 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4359 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4360 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4361 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4362 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4363 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4364 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4365 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4366 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4367 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4369 case Intrinsic::loongarch_lsx_vnori_b:
4370 case Intrinsic::loongarch_lsx_vshuf4i_b:
4371 case Intrinsic::loongarch_lsx_vshuf4i_h:
4372 case Intrinsic::loongarch_lsx_vshuf4i_w:
4373 case Intrinsic::loongarch_lasx_xvnori_b:
4374 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4375 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4376 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4377 case Intrinsic::loongarch_lasx_xvpermi_d:
4379 case Intrinsic::loongarch_lsx_vshuf4i_d:
4380 case Intrinsic::loongarch_lsx_vpermi_w:
4381 case Intrinsic::loongarch_lsx_vbitseli_b:
4382 case Intrinsic::loongarch_lsx_vextrins_b:
4383 case Intrinsic::loongarch_lsx_vextrins_h:
4384 case Intrinsic::loongarch_lsx_vextrins_w:
4385 case Intrinsic::loongarch_lsx_vextrins_d:
4386 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4387 case Intrinsic::loongarch_lasx_xvpermi_w:
4388 case Intrinsic::loongarch_lasx_xvpermi_q:
4389 case Intrinsic::loongarch_lasx_xvbitseli_b:
4390 case Intrinsic::loongarch_lasx_xvextrins_b:
4391 case Intrinsic::loongarch_lasx_xvextrins_h:
4392 case Intrinsic::loongarch_lasx_xvextrins_w:
4393 case Intrinsic::loongarch_lasx_xvextrins_d:
4395 case Intrinsic::loongarch_lsx_vrepli_b:
4396 case Intrinsic::loongarch_lsx_vrepli_h:
4397 case Intrinsic::loongarch_lsx_vrepli_w:
4398 case Intrinsic::loongarch_lsx_vrepli_d:
4399 case Intrinsic::loongarch_lasx_xvrepli_b:
4400 case Intrinsic::loongarch_lasx_xvrepli_h:
4401 case Intrinsic::loongarch_lasx_xvrepli_w:
4402 case Intrinsic::loongarch_lasx_xvrepli_d:
4404 case Intrinsic::loongarch_lsx_vldi:
4405 case Intrinsic::loongarch_lasx_xvldi:
4421LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4424 MVT GRLenVT = Subtarget.getGRLenVT();
4425 EVT VT =
Op.getValueType();
4427 const StringRef ErrorMsgOOR =
"argument out of range";
4428 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4429 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4431 switch (
Op.getConstantOperandVal(1)) {
4434 case Intrinsic::loongarch_crc_w_b_w:
4435 case Intrinsic::loongarch_crc_w_h_w:
4436 case Intrinsic::loongarch_crc_w_w_w:
4437 case Intrinsic::loongarch_crc_w_d_w:
4438 case Intrinsic::loongarch_crcc_w_b_w:
4439 case Intrinsic::loongarch_crcc_w_h_w:
4440 case Intrinsic::loongarch_crcc_w_w_w:
4441 case Intrinsic::loongarch_crcc_w_d_w:
4443 case Intrinsic::loongarch_csrrd_w:
4444 case Intrinsic::loongarch_csrrd_d: {
4445 unsigned Imm =
Op.getConstantOperandVal(2);
4448 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4451 case Intrinsic::loongarch_csrwr_w:
4452 case Intrinsic::loongarch_csrwr_d: {
4453 unsigned Imm =
Op.getConstantOperandVal(3);
4456 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4457 {Chain,
Op.getOperand(2),
4460 case Intrinsic::loongarch_csrxchg_w:
4461 case Intrinsic::loongarch_csrxchg_d: {
4462 unsigned Imm =
Op.getConstantOperandVal(4);
4465 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4466 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4469 case Intrinsic::loongarch_iocsrrd_d: {
4471 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4474#define IOCSRRD_CASE(NAME, NODE) \
4475 case Intrinsic::loongarch_##NAME: { \
4476 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4477 {Chain, Op.getOperand(2)}); \
4483 case Intrinsic::loongarch_cpucfg: {
4484 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4485 {Chain,
Op.getOperand(2)});
4487 case Intrinsic::loongarch_lddir_d: {
4488 unsigned Imm =
Op.getConstantOperandVal(3);
4493 case Intrinsic::loongarch_movfcsr2gr: {
4494 if (!Subtarget.hasBasicF())
4496 unsigned Imm =
Op.getConstantOperandVal(2);
4499 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4502 case Intrinsic::loongarch_lsx_vld:
4503 case Intrinsic::loongarch_lsx_vldrepl_b:
4504 case Intrinsic::loongarch_lasx_xvld:
4505 case Intrinsic::loongarch_lasx_xvldrepl_b:
4509 case Intrinsic::loongarch_lsx_vldrepl_h:
4510 case Intrinsic::loongarch_lasx_xvldrepl_h:
4514 Op,
"argument out of range or not a multiple of 2", DAG)
4516 case Intrinsic::loongarch_lsx_vldrepl_w:
4517 case Intrinsic::loongarch_lasx_xvldrepl_w:
4521 Op,
"argument out of range or not a multiple of 4", DAG)
4523 case Intrinsic::loongarch_lsx_vldrepl_d:
4524 case Intrinsic::loongarch_lasx_xvldrepl_d:
4528 Op,
"argument out of range or not a multiple of 8", DAG)
4539 return Op.getOperand(0);
4545 MVT GRLenVT = Subtarget.getGRLenVT();
4547 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4549 const StringRef ErrorMsgOOR =
"argument out of range";
4550 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4551 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4552 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4554 switch (IntrinsicEnum) {
4558 case Intrinsic::loongarch_cacop_d:
4559 case Intrinsic::loongarch_cacop_w: {
4560 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4562 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4571 case Intrinsic::loongarch_dbar: {
4578 case Intrinsic::loongarch_ibar: {
4585 case Intrinsic::loongarch_break: {
4592 case Intrinsic::loongarch_movgr2fcsr: {
4593 if (!Subtarget.hasBasicF())
4603 case Intrinsic::loongarch_syscall: {
4610#define IOCSRWR_CASE(NAME, NODE) \
4611 case Intrinsic::loongarch_##NAME: { \
4612 SDValue Op3 = Op.getOperand(3); \
4613 return Subtarget.is64Bit() \
4614 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4615 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4616 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4617 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4624 case Intrinsic::loongarch_iocsrwr_d: {
4625 return !Subtarget.is64Bit()
4632#define ASRT_LE_GT_CASE(NAME) \
4633 case Intrinsic::loongarch_##NAME: { \
4634 return !Subtarget.is64Bit() \
4635 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4640#undef ASRT_LE_GT_CASE
4641 case Intrinsic::loongarch_ldpte_d: {
4642 unsigned Imm =
Op.getConstantOperandVal(3);
4643 return !Subtarget.is64Bit()
4648 case Intrinsic::loongarch_lsx_vst:
4649 case Intrinsic::loongarch_lasx_xvst:
4653 case Intrinsic::loongarch_lasx_xvstelm_b:
4658 case Intrinsic::loongarch_lsx_vstelm_b:
4663 case Intrinsic::loongarch_lasx_xvstelm_h:
4668 Op,
"argument out of range or not a multiple of 2", DAG)
4670 case Intrinsic::loongarch_lsx_vstelm_h:
4675 Op,
"argument out of range or not a multiple of 2", DAG)
4677 case Intrinsic::loongarch_lasx_xvstelm_w:
4682 Op,
"argument out of range or not a multiple of 4", DAG)
4684 case Intrinsic::loongarch_lsx_vstelm_w:
4689 Op,
"argument out of range or not a multiple of 4", DAG)
4691 case Intrinsic::loongarch_lasx_xvstelm_d:
4696 Op,
"argument out of range or not a multiple of 8", DAG)
4698 case Intrinsic::loongarch_lsx_vstelm_d:
4703 Op,
"argument out of range or not a multiple of 8", DAG)
4714 EVT VT =
Lo.getValueType();
4755 EVT VT =
Lo.getValueType();
4809 return LoongArchISD::DIV_W;
4811 return LoongArchISD::DIV_WU;
4813 return LoongArchISD::MOD_W;
4815 return LoongArchISD::MOD_WU;
4817 return LoongArchISD::SLL_W;
4819 return LoongArchISD::SRA_W;
4821 return LoongArchISD::SRL_W;
4824 return LoongArchISD::ROTR_W;
4826 return LoongArchISD::CTZ_W;
4828 return LoongArchISD::CLZ_W;
4847 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4848 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4852 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4858 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4885 StringRef ErrorMsg,
bool WithChain =
true) {
4890 Results.push_back(
N->getOperand(0));
4893template <
unsigned N>
4898 const StringRef ErrorMsgOOR =
"argument out of range";
4899 unsigned Imm =
Node->getConstantOperandVal(2);
4933 switch (
N->getConstantOperandVal(0)) {
4936 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4938 LoongArchISD::VPICK_SEXT_ELT);
4940 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4941 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4943 LoongArchISD::VPICK_SEXT_ELT);
4945 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4947 LoongArchISD::VPICK_SEXT_ELT);
4949 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4951 LoongArchISD::VPICK_ZEXT_ELT);
4953 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4954 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4956 LoongArchISD::VPICK_ZEXT_ELT);
4958 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4960 LoongArchISD::VPICK_ZEXT_ELT);
4962 case Intrinsic::loongarch_lsx_bz_b:
4963 case Intrinsic::loongarch_lsx_bz_h:
4964 case Intrinsic::loongarch_lsx_bz_w:
4965 case Intrinsic::loongarch_lsx_bz_d:
4966 case Intrinsic::loongarch_lasx_xbz_b:
4967 case Intrinsic::loongarch_lasx_xbz_h:
4968 case Intrinsic::loongarch_lasx_xbz_w:
4969 case Intrinsic::loongarch_lasx_xbz_d:
4971 LoongArchISD::VALL_ZERO);
4973 case Intrinsic::loongarch_lsx_bz_v:
4974 case Intrinsic::loongarch_lasx_xbz_v:
4976 LoongArchISD::VANY_ZERO);
4978 case Intrinsic::loongarch_lsx_bnz_b:
4979 case Intrinsic::loongarch_lsx_bnz_h:
4980 case Intrinsic::loongarch_lsx_bnz_w:
4981 case Intrinsic::loongarch_lsx_bnz_d:
4982 case Intrinsic::loongarch_lasx_xbnz_b:
4983 case Intrinsic::loongarch_lasx_xbnz_h:
4984 case Intrinsic::loongarch_lasx_xbnz_w:
4985 case Intrinsic::loongarch_lasx_xbnz_d:
4987 LoongArchISD::VALL_NONZERO);
4989 case Intrinsic::loongarch_lsx_bnz_v:
4990 case Intrinsic::loongarch_lasx_xbnz_v:
4992 LoongArchISD::VANY_NONZERO);
5000 assert(
N->getValueType(0) == MVT::i128 &&
5001 "AtomicCmpSwap on types less than 128 should be legal");
5005 switch (
MemOp->getMergedOrdering()) {
5009 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5013 Opcode = LoongArch::PseudoCmpXchg128;
5020 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5021 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5022 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5023 NewVal.first, NewVal.second,
N->getOperand(0)};
5026 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5037 EVT VT =
N->getValueType(0);
5038 switch (
N->getOpcode()) {
5043 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5044 "Unexpected custom legalisation");
5051 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5052 "Unexpected custom legalisation");
5054 Subtarget.hasDiv32() && VT == MVT::i32
5061 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5062 "Unexpected custom legalisation");
5070 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5071 "Unexpected custom legalisation");
5075 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5076 "Unexpected custom legalisation");
5083 if (Src.getValueType() == MVT::f16)
5094 EVT OpVT = Src.getValueType();
5098 std::tie(Result, Chain) =
5105 EVT SrcVT = Src.getValueType();
5106 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5107 Subtarget.hasBasicF()) {
5109 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5111 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5113 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5121 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5122 "Unexpected custom legalisation");
5125 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5130 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5131 "Unexpected custom legalisation");
5137 if (OpVT == MVT::v2f64) {
5147 assert((VT == MVT::i16 || VT == MVT::i32) &&
5148 "Unexpected custom legalization");
5149 MVT GRLenVT = Subtarget.getGRLenVT();
5156 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5161 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5169 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5170 "Unexpected custom legalization");
5171 MVT GRLenVT = Subtarget.getGRLenVT();
5178 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5181 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5189 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5190 "Unexpected custom legalisation");
5197 MVT GRLenVT = Subtarget.getGRLenVT();
5198 const StringRef ErrorMsgOOR =
"argument out of range";
5199 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5200 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5202 switch (
N->getConstantOperandVal(1)) {
5205 case Intrinsic::loongarch_movfcsr2gr: {
5206 if (!Subtarget.hasBasicF()) {
5216 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5223#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5224 case Intrinsic::loongarch_##NAME: { \
5225 SDValue NODE = DAG.getNode( \
5226 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5227 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5228 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5229 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5230 Results.push_back(NODE.getValue(1)); \
5239#undef CRC_CASE_EXT_BINARYOP
5241#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5242 case Intrinsic::loongarch_##NAME: { \
5243 SDValue NODE = DAG.getNode( \
5244 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5246 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5247 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5248 Results.push_back(NODE.getValue(1)); \
5253#undef CRC_CASE_EXT_UNARYOP
5254#define CSR_CASE(ID) \
5255 case Intrinsic::loongarch_##ID: { \
5256 if (!Subtarget.is64Bit()) \
5257 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5265 case Intrinsic::loongarch_csrrd_w: {
5272 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5279 case Intrinsic::loongarch_csrwr_w: {
5280 unsigned Imm =
N->getConstantOperandVal(3);
5286 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5294 case Intrinsic::loongarch_csrxchg_w: {
5295 unsigned Imm =
N->getConstantOperandVal(4);
5301 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5310#define IOCSRRD_CASE(NAME, NODE) \
5311 case Intrinsic::loongarch_##NAME: { \
5312 SDValue IOCSRRDResults = \
5313 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5314 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5315 Results.push_back( \
5316 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5317 Results.push_back(IOCSRRDResults.getValue(1)); \
5324 case Intrinsic::loongarch_cpucfg: {
5326 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5333 case Intrinsic::loongarch_lddir_d: {
5334 if (!Subtarget.is64Bit()) {
5344 if (Subtarget.is64Bit())
5346 "On LA64, only 64-bit registers can be read.");
5349 "On LA32, only 32-bit registers can be read.");
5351 Results.push_back(
N->getOperand(0));
5362 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5375 MVT VT =
N->getSimpleValueType(0);
5381 EVT InVT = In.getValueType();
5392 for (
unsigned I = 0;
I < MinElts; ++
I)
5393 TruncMask[
I] = Scale *
I;
5395 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5396 MVT SVT = In.getSimpleValueType().getScalarType();
5402 "Illegal vector type in truncation");
5418 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5420 MVT VT =
N->getSimpleValueType(0);
5439 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5448 SDValue FirstOperand =
N->getOperand(0);
5449 SDValue SecondOperand =
N->getOperand(1);
5450 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5451 EVT ValTy =
N->getValueType(0);
5454 unsigned SMIdx, SMLen;
5463 if (!Subtarget.has32S())
5519 NewOperand = FirstOperand;
5522 msb = lsb + SMLen - 1;
5526 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5539 if (!Subtarget.has32S())
5551 SDValue FirstOperand =
N->getOperand(0);
5553 EVT ValTy =
N->getValueType(0);
5556 unsigned MaskIdx, MaskLen;
5571 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5572 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
5587 switch (Src.getOpcode()) {
5590 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5600 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5613 switch (Src.getOpcode()) {
5623 Src.getOpcode(),
DL, SExtVT,
5629 DL, SExtVT, Src.getOperand(0),
5641 EVT VT =
N->getValueType(0);
5643 EVT SrcVT = Src.getValueType();
5645 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5650 EVT CmpVT = Src.getOperand(0).getValueType();
5655 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5668 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
5673 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5678 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5683 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5685 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5690 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5692 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5697 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
5714 EVT VT =
N->getValueType(0);
5716 EVT SrcVT = Src.getValueType();
5733 bool UseLASX =
false;
5734 bool PropagateSExt =
false;
5736 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5737 EVT CmpVT = Src.getOperand(0).getValueType();
5746 SExtVT = MVT::v2i64;
5749 SExtVT = MVT::v4i32;
5751 SExtVT = MVT::v4i64;
5753 PropagateSExt =
true;
5757 SExtVT = MVT::v8i16;
5759 SExtVT = MVT::v8i32;
5761 PropagateSExt =
true;
5765 SExtVT = MVT::v16i8;
5767 SExtVT = MVT::v16i16;
5769 PropagateSExt =
true;
5773 SExtVT = MVT::v32i8;
5781 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5782 if (Src.getSimpleValueType() == MVT::v32i8) {
5790 }
else if (UseLASX) {
5796 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5809 EVT ValTy =
N->getValueType(0);
5810 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5814 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5816 bool SwapAndRetried =
false;
5819 if (!Subtarget.has32S())
5825 if (ValBits != 32 && ValBits != 64)
5840 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5843 (MaskIdx0 + MaskLen0 <= ValBits)) {
5864 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5865 (MaskIdx0 + MaskLen0 <= ValBits)) {
5882 (MaskIdx0 + MaskLen0 <= 64) &&
5890 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5891 : (MaskIdx0 + MaskLen0 - 1),
5907 (MaskIdx0 + MaskLen0 <= ValBits)) {
5930 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5931 : (MaskIdx0 + MaskLen0 - 1),
5946 unsigned MaskIdx, MaskLen;
5947 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5956 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5974 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5980 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5988 if (!SwapAndRetried) {
5990 SwapAndRetried =
true;
5994 SwapAndRetried =
false;
6011 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6020 if (!SwapAndRetried) {
6022 SwapAndRetried =
true;
6032 switch (V.getNode()->getOpcode()) {
6044 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6052 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6129 SDNode *AndNode =
N->getOperand(0).getNode();
6137 SDValue CmpInputValue =
N->getOperand(1);
6146 if (!CN || !CN->
isZero())
6148 AndInputValue1 = AndInputValue1.
getOperand(0);
6152 if (AndInputValue2 != CmpInputValue)
6185 TruncInputValue1, TruncInputValue2);
6187 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6200 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6203 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6228 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6256 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6289 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6290 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6306 EVT VT =
N->getValueType(0);
6309 if (TrueV == FalseV)
6340 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6341 {LHS, RHS, CC, TrueV, FalseV});
6346template <
unsigned N>
6350 bool IsSigned =
false) {
6354 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6355 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6357 ": argument out of range.");
6363template <
unsigned N>
6367 EVT ResTy =
Node->getValueType(0);
6371 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6372 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6374 ": argument out of range.");
6379 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6385 EVT ResTy =
Node->getValueType(0);
6393 EVT ResTy =
Node->getValueType(0);
6402template <
unsigned N>
6405 EVT ResTy =
Node->getValueType(0);
6410 ": argument out of range.");
6420template <
unsigned N>
6423 EVT ResTy =
Node->getValueType(0);
6428 ": argument out of range.");
6437template <
unsigned N>
6440 EVT ResTy =
Node->getValueType(0);
6445 ": argument out of range.");
6454template <
unsigned W>
6457 unsigned Imm =
N->getConstantOperandVal(2);
6459 const StringRef ErrorMsg =
"argument out of range";
6461 return DAG.
getUNDEF(
N->getValueType(0));
6467 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6475 switch (
N->getConstantOperandVal(0)) {
6478 case Intrinsic::loongarch_lsx_vadd_b:
6479 case Intrinsic::loongarch_lsx_vadd_h:
6480 case Intrinsic::loongarch_lsx_vadd_w:
6481 case Intrinsic::loongarch_lsx_vadd_d:
6482 case Intrinsic::loongarch_lasx_xvadd_b:
6483 case Intrinsic::loongarch_lasx_xvadd_h:
6484 case Intrinsic::loongarch_lasx_xvadd_w:
6485 case Intrinsic::loongarch_lasx_xvadd_d:
6488 case Intrinsic::loongarch_lsx_vaddi_bu:
6489 case Intrinsic::loongarch_lsx_vaddi_hu:
6490 case Intrinsic::loongarch_lsx_vaddi_wu:
6491 case Intrinsic::loongarch_lsx_vaddi_du:
6492 case Intrinsic::loongarch_lasx_xvaddi_bu:
6493 case Intrinsic::loongarch_lasx_xvaddi_hu:
6494 case Intrinsic::loongarch_lasx_xvaddi_wu:
6495 case Intrinsic::loongarch_lasx_xvaddi_du:
6498 case Intrinsic::loongarch_lsx_vsub_b:
6499 case Intrinsic::loongarch_lsx_vsub_h:
6500 case Intrinsic::loongarch_lsx_vsub_w:
6501 case Intrinsic::loongarch_lsx_vsub_d:
6502 case Intrinsic::loongarch_lasx_xvsub_b:
6503 case Intrinsic::loongarch_lasx_xvsub_h:
6504 case Intrinsic::loongarch_lasx_xvsub_w:
6505 case Intrinsic::loongarch_lasx_xvsub_d:
6508 case Intrinsic::loongarch_lsx_vsubi_bu:
6509 case Intrinsic::loongarch_lsx_vsubi_hu:
6510 case Intrinsic::loongarch_lsx_vsubi_wu:
6511 case Intrinsic::loongarch_lsx_vsubi_du:
6512 case Intrinsic::loongarch_lasx_xvsubi_bu:
6513 case Intrinsic::loongarch_lasx_xvsubi_hu:
6514 case Intrinsic::loongarch_lasx_xvsubi_wu:
6515 case Intrinsic::loongarch_lasx_xvsubi_du:
6518 case Intrinsic::loongarch_lsx_vneg_b:
6519 case Intrinsic::loongarch_lsx_vneg_h:
6520 case Intrinsic::loongarch_lsx_vneg_w:
6521 case Intrinsic::loongarch_lsx_vneg_d:
6522 case Intrinsic::loongarch_lasx_xvneg_b:
6523 case Intrinsic::loongarch_lasx_xvneg_h:
6524 case Intrinsic::loongarch_lasx_xvneg_w:
6525 case Intrinsic::loongarch_lasx_xvneg_d:
6529 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6531 SDLoc(
N),
N->getValueType(0)),
6533 case Intrinsic::loongarch_lsx_vmax_b:
6534 case Intrinsic::loongarch_lsx_vmax_h:
6535 case Intrinsic::loongarch_lsx_vmax_w:
6536 case Intrinsic::loongarch_lsx_vmax_d:
6537 case Intrinsic::loongarch_lasx_xvmax_b:
6538 case Intrinsic::loongarch_lasx_xvmax_h:
6539 case Intrinsic::loongarch_lasx_xvmax_w:
6540 case Intrinsic::loongarch_lasx_xvmax_d:
6543 case Intrinsic::loongarch_lsx_vmax_bu:
6544 case Intrinsic::loongarch_lsx_vmax_hu:
6545 case Intrinsic::loongarch_lsx_vmax_wu:
6546 case Intrinsic::loongarch_lsx_vmax_du:
6547 case Intrinsic::loongarch_lasx_xvmax_bu:
6548 case Intrinsic::loongarch_lasx_xvmax_hu:
6549 case Intrinsic::loongarch_lasx_xvmax_wu:
6550 case Intrinsic::loongarch_lasx_xvmax_du:
6553 case Intrinsic::loongarch_lsx_vmaxi_b:
6554 case Intrinsic::loongarch_lsx_vmaxi_h:
6555 case Intrinsic::loongarch_lsx_vmaxi_w:
6556 case Intrinsic::loongarch_lsx_vmaxi_d:
6557 case Intrinsic::loongarch_lasx_xvmaxi_b:
6558 case Intrinsic::loongarch_lasx_xvmaxi_h:
6559 case Intrinsic::loongarch_lasx_xvmaxi_w:
6560 case Intrinsic::loongarch_lasx_xvmaxi_d:
6563 case Intrinsic::loongarch_lsx_vmaxi_bu:
6564 case Intrinsic::loongarch_lsx_vmaxi_hu:
6565 case Intrinsic::loongarch_lsx_vmaxi_wu:
6566 case Intrinsic::loongarch_lsx_vmaxi_du:
6567 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6568 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6569 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6570 case Intrinsic::loongarch_lasx_xvmaxi_du:
6573 case Intrinsic::loongarch_lsx_vmin_b:
6574 case Intrinsic::loongarch_lsx_vmin_h:
6575 case Intrinsic::loongarch_lsx_vmin_w:
6576 case Intrinsic::loongarch_lsx_vmin_d:
6577 case Intrinsic::loongarch_lasx_xvmin_b:
6578 case Intrinsic::loongarch_lasx_xvmin_h:
6579 case Intrinsic::loongarch_lasx_xvmin_w:
6580 case Intrinsic::loongarch_lasx_xvmin_d:
6583 case Intrinsic::loongarch_lsx_vmin_bu:
6584 case Intrinsic::loongarch_lsx_vmin_hu:
6585 case Intrinsic::loongarch_lsx_vmin_wu:
6586 case Intrinsic::loongarch_lsx_vmin_du:
6587 case Intrinsic::loongarch_lasx_xvmin_bu:
6588 case Intrinsic::loongarch_lasx_xvmin_hu:
6589 case Intrinsic::loongarch_lasx_xvmin_wu:
6590 case Intrinsic::loongarch_lasx_xvmin_du:
6593 case Intrinsic::loongarch_lsx_vmini_b:
6594 case Intrinsic::loongarch_lsx_vmini_h:
6595 case Intrinsic::loongarch_lsx_vmini_w:
6596 case Intrinsic::loongarch_lsx_vmini_d:
6597 case Intrinsic::loongarch_lasx_xvmini_b:
6598 case Intrinsic::loongarch_lasx_xvmini_h:
6599 case Intrinsic::loongarch_lasx_xvmini_w:
6600 case Intrinsic::loongarch_lasx_xvmini_d:
6603 case Intrinsic::loongarch_lsx_vmini_bu:
6604 case Intrinsic::loongarch_lsx_vmini_hu:
6605 case Intrinsic::loongarch_lsx_vmini_wu:
6606 case Intrinsic::loongarch_lsx_vmini_du:
6607 case Intrinsic::loongarch_lasx_xvmini_bu:
6608 case Intrinsic::loongarch_lasx_xvmini_hu:
6609 case Intrinsic::loongarch_lasx_xvmini_wu:
6610 case Intrinsic::loongarch_lasx_xvmini_du:
6613 case Intrinsic::loongarch_lsx_vmul_b:
6614 case Intrinsic::loongarch_lsx_vmul_h:
6615 case Intrinsic::loongarch_lsx_vmul_w:
6616 case Intrinsic::loongarch_lsx_vmul_d:
6617 case Intrinsic::loongarch_lasx_xvmul_b:
6618 case Intrinsic::loongarch_lasx_xvmul_h:
6619 case Intrinsic::loongarch_lasx_xvmul_w:
6620 case Intrinsic::loongarch_lasx_xvmul_d:
6623 case Intrinsic::loongarch_lsx_vmadd_b:
6624 case Intrinsic::loongarch_lsx_vmadd_h:
6625 case Intrinsic::loongarch_lsx_vmadd_w:
6626 case Intrinsic::loongarch_lsx_vmadd_d:
6627 case Intrinsic::loongarch_lasx_xvmadd_b:
6628 case Intrinsic::loongarch_lasx_xvmadd_h:
6629 case Intrinsic::loongarch_lasx_xvmadd_w:
6630 case Intrinsic::loongarch_lasx_xvmadd_d: {
6631 EVT ResTy =
N->getValueType(0);
6636 case Intrinsic::loongarch_lsx_vmsub_b:
6637 case Intrinsic::loongarch_lsx_vmsub_h:
6638 case Intrinsic::loongarch_lsx_vmsub_w:
6639 case Intrinsic::loongarch_lsx_vmsub_d:
6640 case Intrinsic::loongarch_lasx_xvmsub_b:
6641 case Intrinsic::loongarch_lasx_xvmsub_h:
6642 case Intrinsic::loongarch_lasx_xvmsub_w:
6643 case Intrinsic::loongarch_lasx_xvmsub_d: {
6644 EVT ResTy =
N->getValueType(0);
6649 case Intrinsic::loongarch_lsx_vdiv_b:
6650 case Intrinsic::loongarch_lsx_vdiv_h:
6651 case Intrinsic::loongarch_lsx_vdiv_w:
6652 case Intrinsic::loongarch_lsx_vdiv_d:
6653 case Intrinsic::loongarch_lasx_xvdiv_b:
6654 case Intrinsic::loongarch_lasx_xvdiv_h:
6655 case Intrinsic::loongarch_lasx_xvdiv_w:
6656 case Intrinsic::loongarch_lasx_xvdiv_d:
6659 case Intrinsic::loongarch_lsx_vdiv_bu:
6660 case Intrinsic::loongarch_lsx_vdiv_hu:
6661 case Intrinsic::loongarch_lsx_vdiv_wu:
6662 case Intrinsic::loongarch_lsx_vdiv_du:
6663 case Intrinsic::loongarch_lasx_xvdiv_bu:
6664 case Intrinsic::loongarch_lasx_xvdiv_hu:
6665 case Intrinsic::loongarch_lasx_xvdiv_wu:
6666 case Intrinsic::loongarch_lasx_xvdiv_du:
6669 case Intrinsic::loongarch_lsx_vmod_b:
6670 case Intrinsic::loongarch_lsx_vmod_h:
6671 case Intrinsic::loongarch_lsx_vmod_w:
6672 case Intrinsic::loongarch_lsx_vmod_d:
6673 case Intrinsic::loongarch_lasx_xvmod_b:
6674 case Intrinsic::loongarch_lasx_xvmod_h:
6675 case Intrinsic::loongarch_lasx_xvmod_w:
6676 case Intrinsic::loongarch_lasx_xvmod_d:
6679 case Intrinsic::loongarch_lsx_vmod_bu:
6680 case Intrinsic::loongarch_lsx_vmod_hu:
6681 case Intrinsic::loongarch_lsx_vmod_wu:
6682 case Intrinsic::loongarch_lsx_vmod_du:
6683 case Intrinsic::loongarch_lasx_xvmod_bu:
6684 case Intrinsic::loongarch_lasx_xvmod_hu:
6685 case Intrinsic::loongarch_lasx_xvmod_wu:
6686 case Intrinsic::loongarch_lasx_xvmod_du:
6689 case Intrinsic::loongarch_lsx_vand_v:
6690 case Intrinsic::loongarch_lasx_xvand_v:
6693 case Intrinsic::loongarch_lsx_vor_v:
6694 case Intrinsic::loongarch_lasx_xvor_v:
6697 case Intrinsic::loongarch_lsx_vxor_v:
6698 case Intrinsic::loongarch_lasx_xvxor_v:
6701 case Intrinsic::loongarch_lsx_vnor_v:
6702 case Intrinsic::loongarch_lasx_xvnor_v: {
6707 case Intrinsic::loongarch_lsx_vandi_b:
6708 case Intrinsic::loongarch_lasx_xvandi_b:
6711 case Intrinsic::loongarch_lsx_vori_b:
6712 case Intrinsic::loongarch_lasx_xvori_b:
6715 case Intrinsic::loongarch_lsx_vxori_b:
6716 case Intrinsic::loongarch_lasx_xvxori_b:
6719 case Intrinsic::loongarch_lsx_vsll_b:
6720 case Intrinsic::loongarch_lsx_vsll_h:
6721 case Intrinsic::loongarch_lsx_vsll_w:
6722 case Intrinsic::loongarch_lsx_vsll_d:
6723 case Intrinsic::loongarch_lasx_xvsll_b:
6724 case Intrinsic::loongarch_lasx_xvsll_h:
6725 case Intrinsic::loongarch_lasx_xvsll_w:
6726 case Intrinsic::loongarch_lasx_xvsll_d:
6729 case Intrinsic::loongarch_lsx_vslli_b:
6730 case Intrinsic::loongarch_lasx_xvslli_b:
6733 case Intrinsic::loongarch_lsx_vslli_h:
6734 case Intrinsic::loongarch_lasx_xvslli_h:
6737 case Intrinsic::loongarch_lsx_vslli_w:
6738 case Intrinsic::loongarch_lasx_xvslli_w:
6741 case Intrinsic::loongarch_lsx_vslli_d:
6742 case Intrinsic::loongarch_lasx_xvslli_d:
6745 case Intrinsic::loongarch_lsx_vsrl_b:
6746 case Intrinsic::loongarch_lsx_vsrl_h:
6747 case Intrinsic::loongarch_lsx_vsrl_w:
6748 case Intrinsic::loongarch_lsx_vsrl_d:
6749 case Intrinsic::loongarch_lasx_xvsrl_b:
6750 case Intrinsic::loongarch_lasx_xvsrl_h:
6751 case Intrinsic::loongarch_lasx_xvsrl_w:
6752 case Intrinsic::loongarch_lasx_xvsrl_d:
6755 case Intrinsic::loongarch_lsx_vsrli_b:
6756 case Intrinsic::loongarch_lasx_xvsrli_b:
6759 case Intrinsic::loongarch_lsx_vsrli_h:
6760 case Intrinsic::loongarch_lasx_xvsrli_h:
6763 case Intrinsic::loongarch_lsx_vsrli_w:
6764 case Intrinsic::loongarch_lasx_xvsrli_w:
6767 case Intrinsic::loongarch_lsx_vsrli_d:
6768 case Intrinsic::loongarch_lasx_xvsrli_d:
6771 case Intrinsic::loongarch_lsx_vsra_b:
6772 case Intrinsic::loongarch_lsx_vsra_h:
6773 case Intrinsic::loongarch_lsx_vsra_w:
6774 case Intrinsic::loongarch_lsx_vsra_d:
6775 case Intrinsic::loongarch_lasx_xvsra_b:
6776 case Intrinsic::loongarch_lasx_xvsra_h:
6777 case Intrinsic::loongarch_lasx_xvsra_w:
6778 case Intrinsic::loongarch_lasx_xvsra_d:
6781 case Intrinsic::loongarch_lsx_vsrai_b:
6782 case Intrinsic::loongarch_lasx_xvsrai_b:
6785 case Intrinsic::loongarch_lsx_vsrai_h:
6786 case Intrinsic::loongarch_lasx_xvsrai_h:
6789 case Intrinsic::loongarch_lsx_vsrai_w:
6790 case Intrinsic::loongarch_lasx_xvsrai_w:
6793 case Intrinsic::loongarch_lsx_vsrai_d:
6794 case Intrinsic::loongarch_lasx_xvsrai_d:
6797 case Intrinsic::loongarch_lsx_vclz_b:
6798 case Intrinsic::loongarch_lsx_vclz_h:
6799 case Intrinsic::loongarch_lsx_vclz_w:
6800 case Intrinsic::loongarch_lsx_vclz_d:
6801 case Intrinsic::loongarch_lasx_xvclz_b:
6802 case Intrinsic::loongarch_lasx_xvclz_h:
6803 case Intrinsic::loongarch_lasx_xvclz_w:
6804 case Intrinsic::loongarch_lasx_xvclz_d:
6806 case Intrinsic::loongarch_lsx_vpcnt_b:
6807 case Intrinsic::loongarch_lsx_vpcnt_h:
6808 case Intrinsic::loongarch_lsx_vpcnt_w:
6809 case Intrinsic::loongarch_lsx_vpcnt_d:
6810 case Intrinsic::loongarch_lasx_xvpcnt_b:
6811 case Intrinsic::loongarch_lasx_xvpcnt_h:
6812 case Intrinsic::loongarch_lasx_xvpcnt_w:
6813 case Intrinsic::loongarch_lasx_xvpcnt_d:
6815 case Intrinsic::loongarch_lsx_vbitclr_b:
6816 case Intrinsic::loongarch_lsx_vbitclr_h:
6817 case Intrinsic::loongarch_lsx_vbitclr_w:
6818 case Intrinsic::loongarch_lsx_vbitclr_d:
6819 case Intrinsic::loongarch_lasx_xvbitclr_b:
6820 case Intrinsic::loongarch_lasx_xvbitclr_h:
6821 case Intrinsic::loongarch_lasx_xvbitclr_w:
6822 case Intrinsic::loongarch_lasx_xvbitclr_d:
6824 case Intrinsic::loongarch_lsx_vbitclri_b:
6825 case Intrinsic::loongarch_lasx_xvbitclri_b:
6827 case Intrinsic::loongarch_lsx_vbitclri_h:
6828 case Intrinsic::loongarch_lasx_xvbitclri_h:
6830 case Intrinsic::loongarch_lsx_vbitclri_w:
6831 case Intrinsic::loongarch_lasx_xvbitclri_w:
6833 case Intrinsic::loongarch_lsx_vbitclri_d:
6834 case Intrinsic::loongarch_lasx_xvbitclri_d:
6836 case Intrinsic::loongarch_lsx_vbitset_b:
6837 case Intrinsic::loongarch_lsx_vbitset_h:
6838 case Intrinsic::loongarch_lsx_vbitset_w:
6839 case Intrinsic::loongarch_lsx_vbitset_d:
6840 case Intrinsic::loongarch_lasx_xvbitset_b:
6841 case Intrinsic::loongarch_lasx_xvbitset_h:
6842 case Intrinsic::loongarch_lasx_xvbitset_w:
6843 case Intrinsic::loongarch_lasx_xvbitset_d: {
6844 EVT VecTy =
N->getValueType(0);
6850 case Intrinsic::loongarch_lsx_vbitseti_b:
6851 case Intrinsic::loongarch_lasx_xvbitseti_b:
6853 case Intrinsic::loongarch_lsx_vbitseti_h:
6854 case Intrinsic::loongarch_lasx_xvbitseti_h:
6856 case Intrinsic::loongarch_lsx_vbitseti_w:
6857 case Intrinsic::loongarch_lasx_xvbitseti_w:
6859 case Intrinsic::loongarch_lsx_vbitseti_d:
6860 case Intrinsic::loongarch_lasx_xvbitseti_d:
6862 case Intrinsic::loongarch_lsx_vbitrev_b:
6863 case Intrinsic::loongarch_lsx_vbitrev_h:
6864 case Intrinsic::loongarch_lsx_vbitrev_w:
6865 case Intrinsic::loongarch_lsx_vbitrev_d:
6866 case Intrinsic::loongarch_lasx_xvbitrev_b:
6867 case Intrinsic::loongarch_lasx_xvbitrev_h:
6868 case Intrinsic::loongarch_lasx_xvbitrev_w:
6869 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6870 EVT VecTy =
N->getValueType(0);
6876 case Intrinsic::loongarch_lsx_vbitrevi_b:
6877 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6879 case Intrinsic::loongarch_lsx_vbitrevi_h:
6880 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6882 case Intrinsic::loongarch_lsx_vbitrevi_w:
6883 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6885 case Intrinsic::loongarch_lsx_vbitrevi_d:
6886 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6888 case Intrinsic::loongarch_lsx_vfadd_s:
6889 case Intrinsic::loongarch_lsx_vfadd_d:
6890 case Intrinsic::loongarch_lasx_xvfadd_s:
6891 case Intrinsic::loongarch_lasx_xvfadd_d:
6894 case Intrinsic::loongarch_lsx_vfsub_s:
6895 case Intrinsic::loongarch_lsx_vfsub_d:
6896 case Intrinsic::loongarch_lasx_xvfsub_s:
6897 case Intrinsic::loongarch_lasx_xvfsub_d:
6900 case Intrinsic::loongarch_lsx_vfmul_s:
6901 case Intrinsic::loongarch_lsx_vfmul_d:
6902 case Intrinsic::loongarch_lasx_xvfmul_s:
6903 case Intrinsic::loongarch_lasx_xvfmul_d:
6906 case Intrinsic::loongarch_lsx_vfdiv_s:
6907 case Intrinsic::loongarch_lsx_vfdiv_d:
6908 case Intrinsic::loongarch_lasx_xvfdiv_s:
6909 case Intrinsic::loongarch_lasx_xvfdiv_d:
6912 case Intrinsic::loongarch_lsx_vfmadd_s:
6913 case Intrinsic::loongarch_lsx_vfmadd_d:
6914 case Intrinsic::loongarch_lasx_xvfmadd_s:
6915 case Intrinsic::loongarch_lasx_xvfmadd_d:
6917 N->getOperand(2),
N->getOperand(3));
6918 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6920 N->getOperand(1),
N->getOperand(2),
6922 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6923 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6925 N->getOperand(1),
N->getOperand(2),
6927 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6928 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6930 N->getOperand(1),
N->getOperand(2),
6932 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6934 N->getOperand(1),
N->getOperand(2),
6936 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6937 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6938 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6939 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6940 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6941 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6942 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6943 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6944 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
6947 case Intrinsic::loongarch_lsx_vreplve_b:
6948 case Intrinsic::loongarch_lsx_vreplve_h:
6949 case Intrinsic::loongarch_lsx_vreplve_w:
6950 case Intrinsic::loongarch_lsx_vreplve_d:
6951 case Intrinsic::loongarch_lasx_xvreplve_b:
6952 case Intrinsic::loongarch_lasx_xvreplve_h:
6953 case Intrinsic::loongarch_lasx_xvreplve_w:
6954 case Intrinsic::loongarch_lasx_xvreplve_d:
6955 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
6959 case Intrinsic::loongarch_lsx_vpickve2gr_b:
6963 case Intrinsic::loongarch_lsx_vpickve2gr_h:
6964 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
6968 case Intrinsic::loongarch_lsx_vpickve2gr_w:
6972 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
6976 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
6977 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
6981 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
6985 case Intrinsic::loongarch_lsx_bz_b:
6986 case Intrinsic::loongarch_lsx_bz_h:
6987 case Intrinsic::loongarch_lsx_bz_w:
6988 case Intrinsic::loongarch_lsx_bz_d:
6989 case Intrinsic::loongarch_lasx_xbz_b:
6990 case Intrinsic::loongarch_lasx_xbz_h:
6991 case Intrinsic::loongarch_lasx_xbz_w:
6992 case Intrinsic::loongarch_lasx_xbz_d:
6994 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
6997 case Intrinsic::loongarch_lsx_bz_v:
6998 case Intrinsic::loongarch_lasx_xbz_v:
7000 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7003 case Intrinsic::loongarch_lsx_bnz_b:
7004 case Intrinsic::loongarch_lsx_bnz_h:
7005 case Intrinsic::loongarch_lsx_bnz_w:
7006 case Intrinsic::loongarch_lsx_bnz_d:
7007 case Intrinsic::loongarch_lasx_xbnz_b:
7008 case Intrinsic::loongarch_lasx_xbnz_h:
7009 case Intrinsic::loongarch_lasx_xbnz_w:
7010 case Intrinsic::loongarch_lasx_xbnz_d:
7012 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7015 case Intrinsic::loongarch_lsx_bnz_v:
7016 case Intrinsic::loongarch_lasx_xbnz_v:
7018 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7021 case Intrinsic::loongarch_lasx_concat_128_s:
7022 case Intrinsic::loongarch_lasx_concat_128_d:
7023 case Intrinsic::loongarch_lasx_concat_128:
7025 N->getOperand(1),
N->getOperand(2));
7037 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
7049 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
7051 "Unexpected value type!");
7060 MVT VT =
N->getSimpleValueType(0);
7081 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
7094 APInt V =
C->getValueAPF().bitcastToAPInt();
7109 MVT VT =
N->getSimpleValueType(0);
7170 EVT VT =
N->getValueType(0);
7172 if (VT != MVT::f32 && VT != MVT::f64)
7174 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7176 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7199 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
7256 Subtarget.hasExtLASX() && N1.
hasOneUse())
7268 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
7278 EVT VT =
N.getValueType();
7295 switch (
N.getOpcode()) {
7311 EVT VT =
N->getValueType(0);
7326 EVT VT =
N->getValueType(0);
7328 if (VT.
isVector() &&
N->getNumOperands() == 2)
7338 switch (
N->getOpcode()) {
7357 case LoongArchISD::BITREV_W:
7359 case LoongArchISD::BR_CC:
7361 case LoongArchISD::SELECT_CC:
7365 case LoongArchISD::MOVGR2FR_W_LA64:
7367 case LoongArchISD::MOVFR2GR_S_LA64:
7369 case LoongArchISD::VMSKLTZ:
7370 case LoongArchISD::XVMSKLTZ:
7372 case LoongArchISD::SPLIT_PAIR_F64:
7374 case LoongArchISD::VANDN:
7378 case LoongArchISD::VPACKEV:
7404 MF->
insert(It, BreakMBB);
7408 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
7409 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
7421 MBB->addSuccessor(BreakMBB);
7422 MBB->addSuccessor(SinkMBB);
7428 BreakMBB->addSuccessor(SinkMBB);
7440 switch (
MI.getOpcode()) {
7443 case LoongArch::PseudoVBZ:
7444 CondOpc = LoongArch::VSETEQZ_V;
7446 case LoongArch::PseudoVBZ_B:
7447 CondOpc = LoongArch::VSETANYEQZ_B;
7449 case LoongArch::PseudoVBZ_H:
7450 CondOpc = LoongArch::VSETANYEQZ_H;
7452 case LoongArch::PseudoVBZ_W:
7453 CondOpc = LoongArch::VSETANYEQZ_W;
7455 case LoongArch::PseudoVBZ_D:
7456 CondOpc = LoongArch::VSETANYEQZ_D;
7458 case LoongArch::PseudoVBNZ:
7459 CondOpc = LoongArch::VSETNEZ_V;
7461 case LoongArch::PseudoVBNZ_B:
7462 CondOpc = LoongArch::VSETALLNEZ_B;
7464 case LoongArch::PseudoVBNZ_H:
7465 CondOpc = LoongArch::VSETALLNEZ_H;
7467 case LoongArch::PseudoVBNZ_W:
7468 CondOpc = LoongArch::VSETALLNEZ_W;
7470 case LoongArch::PseudoVBNZ_D:
7471 CondOpc = LoongArch::VSETALLNEZ_D;
7473 case LoongArch::PseudoXVBZ:
7474 CondOpc = LoongArch::XVSETEQZ_V;
7476 case LoongArch::PseudoXVBZ_B:
7477 CondOpc = LoongArch::XVSETANYEQZ_B;
7479 case LoongArch::PseudoXVBZ_H:
7480 CondOpc = LoongArch::XVSETANYEQZ_H;
7482 case LoongArch::PseudoXVBZ_W:
7483 CondOpc = LoongArch::XVSETANYEQZ_W;
7485 case LoongArch::PseudoXVBZ_D:
7486 CondOpc = LoongArch::XVSETANYEQZ_D;
7488 case LoongArch::PseudoXVBNZ:
7489 CondOpc = LoongArch::XVSETNEZ_V;
7491 case LoongArch::PseudoXVBNZ_B:
7492 CondOpc = LoongArch::XVSETALLNEZ_B;
7494 case LoongArch::PseudoXVBNZ_H:
7495 CondOpc = LoongArch::XVSETALLNEZ_H;
7497 case LoongArch::PseudoXVBNZ_W:
7498 CondOpc = LoongArch::XVSETALLNEZ_W;
7500 case LoongArch::PseudoXVBNZ_D:
7501 CondOpc = LoongArch::XVSETALLNEZ_D;
7516 F->insert(It, FalseBB);
7517 F->insert(It, TrueBB);
7518 F->insert(It, SinkBB);
7521 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
7550 MI.getOperand(0).getReg())
7557 MI.eraseFromParent();
7565 unsigned BroadcastOp;
7567 switch (
MI.getOpcode()) {
7570 case LoongArch::PseudoXVINSGR2VR_B:
7572 BroadcastOp = LoongArch::XVREPLGR2VR_B;
7573 InsOp = LoongArch::XVEXTRINS_B;
7575 case LoongArch::PseudoXVINSGR2VR_H:
7577 BroadcastOp = LoongArch::XVREPLGR2VR_H;
7578 InsOp = LoongArch::XVEXTRINS_H;
7590 unsigned Idx =
MI.getOperand(3).getImm();
7598 .
addReg(XSrc, {}, LoongArch::sub_128);
7600 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
7601 : LoongArch::VINSGR2VR_B),
7609 .
addImm(LoongArch::sub_128);
7616 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
7619 .
addImm(Idx >= HalfSize ? 48 : 18);
7624 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
7627 MI.eraseFromParent();
7634 assert(Subtarget.hasExtLSX());
7647 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
7648 : LoongArch::VINSGR2VR_W),
7655 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
7659 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
7660 : LoongArch::VPICKVE2GR_W),
7665 MI.eraseFromParent();
7679 unsigned EleBits = 8;
7680 unsigned NotOpc = 0;
7683 switch (
MI.getOpcode()) {
7686 case LoongArch::PseudoVMSKLTZ_B:
7687 MskOpc = LoongArch::VMSKLTZ_B;
7689 case LoongArch::PseudoVMSKLTZ_H:
7690 MskOpc = LoongArch::VMSKLTZ_H;
7693 case LoongArch::PseudoVMSKLTZ_W:
7694 MskOpc = LoongArch::VMSKLTZ_W;
7697 case LoongArch::PseudoVMSKLTZ_D:
7698 MskOpc = LoongArch::VMSKLTZ_D;
7701 case LoongArch::PseudoVMSKGEZ_B:
7702 MskOpc = LoongArch::VMSKGEZ_B;
7704 case LoongArch::PseudoVMSKEQZ_B:
7705 MskOpc = LoongArch::VMSKNZ_B;
7706 NotOpc = LoongArch::VNOR_V;
7708 case LoongArch::PseudoVMSKNEZ_B:
7709 MskOpc = LoongArch::VMSKNZ_B;
7711 case LoongArch::PseudoXVMSKLTZ_B:
7712 MskOpc = LoongArch::XVMSKLTZ_B;
7713 RC = &LoongArch::LASX256RegClass;
7715 case LoongArch::PseudoXVMSKLTZ_H:
7716 MskOpc = LoongArch::XVMSKLTZ_H;
7717 RC = &LoongArch::LASX256RegClass;
7720 case LoongArch::PseudoXVMSKLTZ_W:
7721 MskOpc = LoongArch::XVMSKLTZ_W;
7722 RC = &LoongArch::LASX256RegClass;
7725 case LoongArch::PseudoXVMSKLTZ_D:
7726 MskOpc = LoongArch::XVMSKLTZ_D;
7727 RC = &LoongArch::LASX256RegClass;
7730 case LoongArch::PseudoXVMSKGEZ_B:
7731 MskOpc = LoongArch::XVMSKGEZ_B;
7732 RC = &LoongArch::LASX256RegClass;
7734 case LoongArch::PseudoXVMSKEQZ_B:
7735 MskOpc = LoongArch::XVMSKNZ_B;
7736 NotOpc = LoongArch::XVNOR_V;
7737 RC = &LoongArch::LASX256RegClass;
7739 case LoongArch::PseudoXVMSKNEZ_B:
7740 MskOpc = LoongArch::XVMSKNZ_B;
7741 RC = &LoongArch::LASX256RegClass;
7756 if (
TRI->getRegSizeInBits(*RC) > 128) {
7766 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
7767 : LoongArch::BSTRINS_W),
7771 .
addImm(256 / EleBits - 1)
7779 MI.eraseFromParent();
7786 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
7787 "Unexpected instruction");
7799 MI.eraseFromParent();
7806 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
7807 "Unexpected instruction");
7823 MI.eraseFromParent();
7828 switch (
MI.getOpcode()) {
7831 case LoongArch::Select_GPR_Using_CC_GPR:
7867 if (
MI.getOperand(2).isReg())
7868 RHS =
MI.getOperand(2).getReg();
7869 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
7873 SelectDests.
insert(
MI.getOperand(0).getReg());
7877 SequenceMBBI !=
E; ++SequenceMBBI) {
7878 if (SequenceMBBI->isDebugInstr())
7881 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
7882 !SequenceMBBI->getOperand(2).isReg() ||
7883 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
7884 SequenceMBBI->getOperand(3).getImm() != CC ||
7885 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
7886 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
7888 LastSelectPseudo = &*SequenceMBBI;
7890 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
7893 if (SequenceMBBI->hasUnmodeledSideEffects() ||
7894 SequenceMBBI->mayLoadOrStore() ||
7895 SequenceMBBI->usesCustomInsertionHook())
7898 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
7913 F->insert(
I, IfFalseMBB);
7914 F->insert(
I, TailMBB);
7917 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
7923 TailMBB->
push_back(DebugInstr->removeFromParent());
7927 TailMBB->
splice(TailMBB->
end(), HeadMBB,
7937 if (
MI.getOperand(2).isImm())
7949 auto SelectMBBI =
MI.getIterator();
7950 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7952 while (SelectMBBI != SelectEnd) {
7953 auto Next = std::next(SelectMBBI);
7957 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7958 .
addReg(SelectMBBI->getOperand(4).getReg())
7960 .
addReg(SelectMBBI->getOperand(5).getReg())
7967 F->getProperties().resetNoPHIs();
7973 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7976 switch (
MI.getOpcode()) {
7979 case LoongArch::DIV_W:
7980 case LoongArch::DIV_WU:
7981 case LoongArch::MOD_W:
7982 case LoongArch::MOD_WU:
7983 case LoongArch::DIV_D:
7984 case LoongArch::DIV_DU:
7985 case LoongArch::MOD_D:
7986 case LoongArch::MOD_DU:
7989 case LoongArch::WRFCSR: {
7991 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7992 .
addReg(
MI.getOperand(1).getReg());
7993 MI.eraseFromParent();
7996 case LoongArch::RDFCSR: {
7997 MachineInstr *ReadFCSR =
7999 MI.getOperand(0).getReg())
8000 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
8002 MI.eraseFromParent();
8005 case LoongArch::Select_GPR_Using_CC_GPR:
8007 case LoongArch::BuildPairF64Pseudo:
8009 case LoongArch::SplitPairF64Pseudo:
8011 case LoongArch::PseudoVBZ:
8012 case LoongArch::PseudoVBZ_B:
8013 case LoongArch::PseudoVBZ_H:
8014 case LoongArch::PseudoVBZ_W:
8015 case LoongArch::PseudoVBZ_D:
8016 case LoongArch::PseudoVBNZ:
8017 case LoongArch::PseudoVBNZ_B:
8018 case LoongArch::PseudoVBNZ_H:
8019 case LoongArch::PseudoVBNZ_W:
8020 case LoongArch::PseudoVBNZ_D:
8021 case LoongArch::PseudoXVBZ:
8022 case LoongArch::PseudoXVBZ_B:
8023 case LoongArch::PseudoXVBZ_H:
8024 case LoongArch::PseudoXVBZ_W:
8025 case LoongArch::PseudoXVBZ_D:
8026 case LoongArch::PseudoXVBNZ:
8027 case LoongArch::PseudoXVBNZ_B:
8028 case LoongArch::PseudoXVBNZ_H:
8029 case LoongArch::PseudoXVBNZ_W:
8030 case LoongArch::PseudoXVBNZ_D:
8032 case LoongArch::PseudoXVINSGR2VR_B:
8033 case LoongArch::PseudoXVINSGR2VR_H:
8035 case LoongArch::PseudoCTPOP:
8037 case LoongArch::PseudoVMSKLTZ_B:
8038 case LoongArch::PseudoVMSKLTZ_H:
8039 case LoongArch::PseudoVMSKLTZ_W:
8040 case LoongArch::PseudoVMSKLTZ_D:
8041 case LoongArch::PseudoVMSKGEZ_B:
8042 case LoongArch::PseudoVMSKEQZ_B:
8043 case LoongArch::PseudoVMSKNEZ_B:
8044 case LoongArch::PseudoXVMSKLTZ_B:
8045 case LoongArch::PseudoXVMSKLTZ_H:
8046 case LoongArch::PseudoXVMSKLTZ_W:
8047 case LoongArch::PseudoXVMSKLTZ_D:
8048 case LoongArch::PseudoXVMSKGEZ_B:
8049 case LoongArch::PseudoXVMSKEQZ_B:
8050 case LoongArch::PseudoXVMSKNEZ_B:
8052 case TargetOpcode::STATEPOINT:
8058 MI.addOperand(*
MI.getMF(),
8060 LoongArch::R1,
true,
8063 if (!Subtarget.is64Bit())
8071 unsigned *
Fast)
const {
8072 if (!Subtarget.hasUAL())
8090 LoongArch::R7, LoongArch::R8, LoongArch::R9,
8091 LoongArch::R10, LoongArch::R11};
8106 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
8107 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
8108 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
8109 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
8110 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
8111 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
8117 LoongArch::F3, LoongArch::F4, LoongArch::F5,
8118 LoongArch::F6, LoongArch::F7};
8121 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
8122 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
8125 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
8126 LoongArch::VR6, LoongArch::VR7};
8129 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
8130 LoongArch::XR6, LoongArch::XR7};
8133 switch (State.getCallingConv()) {
8135 if (!State.isVarArg())
8139 return State.AllocateReg(
ArgGPRs);
8147 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
8149 unsigned GRLenInBytes = GRLen / 8;
8160 State.AllocateStack(GRLenInBytes, StackAlign),
8163 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8174 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8182 unsigned ValNo,
MVT ValVT,
8185 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
8186 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
8187 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
8192 if (IsRet && ValNo > 1)
8196 bool UseGPRForFloat =
true;
8206 UseGPRForFloat = ArgFlags.
isVarArg();
8219 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
8222 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
8223 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
8225 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
8231 State.getPendingArgFlags();
8234 "PendingLocs and PendingArgFlags out of sync");
8238 UseGPRForFloat =
true;
8240 if (UseGPRForFloat && ValVT == MVT::f32) {
8243 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
8246 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
8249 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
8291 PendingLocs.
size() <= 2) {
8292 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
8297 PendingLocs.
clear();
8298 PendingArgFlags.
clear();
8305 unsigned StoreSizeBytes = GRLen / 8;
8308 if (ValVT == MVT::f32 && !UseGPRForFloat) {
8310 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
8314 UseGPRForFloat =
false;
8315 StoreSizeBytes = 16;
8316 StackAlign =
Align(16);
8319 UseGPRForFloat =
false;
8320 StoreSizeBytes = 32;
8321 StackAlign =
Align(32);
8327 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
8331 if (!PendingLocs.
empty()) {
8333 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
8334 for (
auto &It : PendingLocs) {
8336 It.convertToReg(
Reg);
8341 PendingLocs.clear();
8342 PendingArgFlags.
clear();
8345 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
8346 "Expected an GRLenVT at this stage");
8363void LoongArchTargetLowering::analyzeInputArgs(
8366 LoongArchCCAssignFn Fn)
const {
8368 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
8369 MVT ArgVT = Ins[i].VT;
8370 Type *ArgTy =
nullptr;
8372 ArgTy = FType->getReturnType();
8373 else if (Ins[i].isOrigArg())
8374 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
8378 CCInfo, IsRet, ArgTy)) {
8379 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
8386void LoongArchTargetLowering::analyzeOutputArgs(
8389 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
8390 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8391 MVT ArgVT = Outs[i].VT;
8392 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
8396 CCInfo, IsRet, OrigTy)) {
8397 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
8416 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
8438 if (In.isOrigArg()) {
8443 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
8444 (
BitWidth < 32 && In.Flags.isZExt())) {
8494 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8507 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8511 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
8525 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
8537 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8541 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8542 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8543 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8550 if (LocVT == MVT::f32) {
8553 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
8554 LoongArch::F26, LoongArch::F27};
8561 if (LocVT == MVT::f64) {
8564 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
8565 LoongArch::F30_64, LoongArch::F31_64};
8596 "GHC calling convention requires the F and D extensions");
8600 MVT GRLenVT = Subtarget.getGRLenVT();
8601 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
8603 std::vector<SDValue> OutChains;
8612 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
8614 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
8631 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
8632 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
8633 assert(ArgPartOffset == 0);
8634 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
8636 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
8660 int VaArgOffset, VarArgsSaveSize;
8664 if (ArgRegs.
size() == Idx) {
8666 VarArgsSaveSize = 0;
8668 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
8669 VaArgOffset = -VarArgsSaveSize;
8675 LoongArchFI->setVarArgsFrameIndex(FI);
8683 VarArgsSaveSize += GRLenInBytes;
8688 for (
unsigned I = Idx;
I < ArgRegs.
size();
8689 ++
I, VaArgOffset += GRLenInBytes) {
8690 const Register Reg = RegInfo.createVirtualRegister(RC);
8691 RegInfo.addLiveIn(ArgRegs[
I], Reg);
8699 ->setValue((
Value *)
nullptr);
8700 OutChains.push_back(Store);
8702 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
8707 if (!OutChains.empty()) {
8708 OutChains.push_back(Chain);
8723 if (
N->getNumValues() != 1)
8725 if (!
N->hasNUsesOfValue(1, 0))
8728 SDNode *Copy = *
N->user_begin();
8734 if (Copy->getGluedNode())
8738 bool HasRet =
false;
8740 if (
Node->getOpcode() != LoongArchISD::RET)
8748 Chain = Copy->getOperand(0);
8753bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
8757 auto CalleeCC = CLI.CallConv;
8758 auto &Outs = CLI.Outs;
8760 auto CallerCC = Caller.getCallingConv();
8767 for (
auto &VA : ArgLocs)
8773 auto IsCallerStructRet = Caller.hasStructRetAttr();
8774 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
8775 if (IsCallerStructRet || IsCalleeStructRet)
8779 for (
auto &Arg : Outs)
8780 if (Arg.Flags.isByVal())
8785 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
8786 if (CalleeCC != CallerCC) {
8787 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
8788 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
8814 MVT GRLenVT = Subtarget.getGRLenVT();
8826 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
8830 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
8836 "site marked musttail");
8843 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8845 if (!Flags.isByVal())
8849 unsigned Size = Flags.getByValSize();
8850 Align Alignment = Flags.getNonZeroByValAlign();
8857 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
8859 false,
nullptr, std::nullopt,
8871 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8874 SDValue ArgValue = OutVals[OutIdx];
8882 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
8883 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8895 if (!StackPtr.getNode())
8907 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8922 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8923 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8924 assert(ArgPartOffset == 0);
8929 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8930 SDValue PartValue = OutVals[OutIdx + 1];
8931 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8946 for (
const auto &Part : Parts) {
8947 SDValue PartValue = Part.first;
8948 SDValue PartOffset = Part.second;
8955 ArgValue = SpillSlot;
8961 if (Flags.isByVal())
8962 ArgValue = ByValArgs[j++];
8969 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8970 "for passing parameters");
8973 if (!StackPtr.getNode())
8986 if (!MemOpChains.
empty())
8992 for (
auto &Reg : RegsToPass) {
8993 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
9015 Ops.push_back(Chain);
9016 Ops.push_back(Callee);
9020 for (
auto &Reg : RegsToPass)
9021 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
9026 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
9027 assert(Mask &&
"Missing call preserved mask for calling convention");
9033 Ops.push_back(Glue);
9042 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
9045 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
9048 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
9049 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
9071 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
9074 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
9075 auto &VA = RVLocs[i];
9083 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
9084 assert(VA.needsCustom());
9089 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
9090 RetValue, RetValue2);
9103 const Type *RetTy)
const {
9105 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
9107 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9111 Outs[i].Flags, CCInfo,
true,
nullptr))
9137 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
9138 SDValue Val = OutVals[OutIdx];
9147 DAG.
getVTList(MVT::i32, MVT::i32), Val);
9151 Register RegHi = RVLocs[++i].getLocReg();
9176 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
9184 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
9187 if (SplatBitSize == 16 && !(V & 0x00FF)) {
9189 RequiredImm = (0b10101 << 8) | (V >> 8);
9190 return {
true, RequiredImm};
9191 }
else if (SplatBitSize == 32) {
9193 if (!(V & 0xFFFF00FF)) {
9194 RequiredImm = (0b10001 << 8) | (V >> 8);
9195 return {
true, RequiredImm};
9198 if (!(V & 0xFF00FFFF)) {
9199 RequiredImm = (0b10010 << 8) | (V >> 16);
9200 return {
true, RequiredImm};
9203 if (!(V & 0x00FFFFFF)) {
9204 RequiredImm = (0b10011 << 8) | (V >> 24);
9205 return {
true, RequiredImm};
9208 if ((V & 0xFFFF00FF) == 0xFF) {
9209 RequiredImm = (0b10110 << 8) | (V >> 8);
9210 return {
true, RequiredImm};
9213 if ((V & 0xFF00FFFF) == 0xFFFF) {
9214 RequiredImm = (0b10111 << 8) | (V >> 16);
9215 return {
true, RequiredImm};
9218 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
9220 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9221 return {
true, RequiredImm};
9223 }
else if (SplatBitSize == 64) {
9225 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
9226 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
9228 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9229 return {
true, RequiredImm};
9232 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
9233 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
9235 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
9236 return {
true, RequiredImm};
9239 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
9241 for (
int i = 0; i < 8; ++i) {
9243 if (
byte == 0 ||
byte == 0xFF)
9244 res |= ((
byte & 1) << i);
9251 auto [IsSame, Suffix] = sameBitsPreByte(V);
9253 RequiredImm = (0b11001 << 8) | Suffix;
9254 return {
true, RequiredImm};
9257 return {
false, RequiredImm};
9262 if (!Subtarget.hasExtLSX())
9265 if (VT == MVT::f32) {
9266 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
9267 return (masked == 0x3e000000 || masked == 0x40000000);
9270 if (VT == MVT::f64) {
9271 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
9272 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
9278bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
9279 bool ForCodeSize)
const {
9281 if (VT == MVT::f32 && !Subtarget.hasBasicF())
9283 if (VT == MVT::f64 && !Subtarget.hasBasicD())
9285 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
9296bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
9306 Type *Ty =
I->getOperand(0)->getType();
9308 unsigned Size = Ty->getIntegerBitWidth();
9328 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
9333 if (Subtarget.hasExtLASX())
9335 else if (Subtarget.hasExtLSX())
9342 EVT VT =
Y.getValueType();
9345 return Subtarget.hasExtLSX() && VT.
isInteger();
9356 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
9357 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
9358 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
9359 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
9362 Info.memVT = MVT::i32;
9363 Info.ptrVal =
I.getArgOperand(0);
9365 Info.align =
Align(4);
9384 "Unable to expand");
9385 unsigned MinWordSize = 4;
9397 Value *AlignedAddr = Builder.CreateIntrinsic(
9398 Intrinsic::ptrmask, {PtrTy, IntTy},
9399 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
9402 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
9403 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
9404 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
9405 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
9406 Value *Mask = Builder.CreateShl(
9407 ConstantInt::get(WordType,
9410 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
9411 Value *ValOperand_Shifted =
9412 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
9413 ShiftAmt,
"ValOperand_Shifted");
9416 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
9418 NewOperand = ValOperand_Shifted;
9421 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
9424 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
9425 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
9445 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
9453 if (Subtarget.hasLAMCAS()) {
9475 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
9477 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
9479 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
9481 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
9483 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
9485 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
9487 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
9489 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
9499 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
9501 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
9503 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
9505 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
9507 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
9509 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
9511 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
9513 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
9525 if (Subtarget.hasLAMCAS())
9537 unsigned GRLen = Subtarget.getGRLen();
9539 Value *FailureOrdering =
9540 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9541 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9543 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9544 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9545 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9546 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9549 Value *Result = Builder.CreateIntrinsic(
9550 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
9552 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9568 Builder.CreateNot(Mask,
"Inv_Mask"),
9575 unsigned GRLen = Subtarget.getGRLen();
9584 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
9585 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9586 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
9602 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
9603 Result = Builder.CreateCall(LlwOpScwLoop,
9604 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
9607 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
9611 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9634 const Constant *PersonalityFn)
const {
9635 return LoongArch::R4;
9639 const Constant *PersonalityFn)
const {
9640 return LoongArch::R5;
9651 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
9652 return RefinementSteps;
9657 assert(Subtarget.hasFrecipe() &&
9658 "Reciprocal estimate queried on unsupported target");
9669 return Subtarget.hasBasicD();
9673 return Subtarget.hasExtLSX();
9677 return Subtarget.hasExtLASX();
9686 int &RefinementSteps,
9687 bool &UseOneConstNR,
9688 bool Reciprocal)
const {
9690 "Enabled should never be Disabled here");
9692 if (!Subtarget.hasFrecipe())
9707 UseOneConstNR =
false;
9713 if (Reciprocal || RefinementSteps > 0)
9723 int &RefinementSteps)
const {
9725 "Enabled should never be Disabled here");
9727 if (!Subtarget.hasFrecipe())
9741 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
9749LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
9769 if (Constraint.
size() == 1) {
9770 switch (Constraint[0]) {
9786 if (Constraint ==
"ZC" || Constraint ==
"ZB")
9795 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
9802std::pair<unsigned, const TargetRegisterClass *>
9803LoongArchTargetLowering::getRegForInlineAsmConstraint(
9807 if (Constraint.
size() == 1) {
9808 switch (Constraint[0]) {
9813 return std::make_pair(0U, &LoongArch::GPRRegClass);
9815 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
9817 if (Subtarget.hasBasicF() && VT == MVT::f32)
9818 return std::make_pair(0U, &LoongArch::FPR32RegClass);
9819 if (Subtarget.hasBasicD() && VT == MVT::f64)
9820 return std::make_pair(0U, &LoongArch::FPR64RegClass);
9821 if (Subtarget.hasExtLSX() &&
9822 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
9823 return std::make_pair(0U, &LoongArch::LSX128RegClass);
9824 if (Subtarget.hasExtLASX() &&
9825 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
9826 return std::make_pair(0U, &LoongArch::LASX256RegClass);
9846 bool IsFP = Constraint[2] ==
'f';
9847 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
9848 std::pair<unsigned, const TargetRegisterClass *>
R;
9853 unsigned RegNo =
R.first;
9854 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
9855 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
9856 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
9857 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
9867void LoongArchTargetLowering::LowerAsmOperandForConstraint(
9871 if (Constraint.
size() == 1) {
9872 switch (Constraint[0]) {
9876 uint64_t CVal =
C->getSExtValue();
9879 Subtarget.getGRLenVT()));
9885 uint64_t CVal =
C->getSExtValue();
9888 Subtarget.getGRLenVT()));
9894 if (
C->getZExtValue() == 0)
9901 uint64_t CVal =
C->getZExtValue();
9914#define GET_REGISTER_MATCHER
9915#include "LoongArchGenAsmMatcher.inc"
9921 std::string NewRegName = Name.second.str();
9927 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
9928 if (!ReservedRegs.
test(Reg))
9945 const APInt &Imm = ConstNode->getAPIntValue();
9947 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
9948 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
9951 if (ConstNode->hasOneUse() &&
9952 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
9953 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
9959 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
9960 unsigned Shifts = Imm.countr_zero();
9966 APInt ImmPop = Imm.ashr(Shifts);
9967 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
9971 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
9972 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
9973 (ImmSmall - Imm).isPowerOf2())
9983 Type *Ty,
unsigned AS,
10002 switch (AM.
Scale) {
10038 EVT MemVT = LD->getMemoryVT();
10039 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10050 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
10059 if (
Y.getValueType().isVector())
10071 Type *Ty,
bool IsSigned)
const {
10072 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
10081 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
10082 Type.getSizeInBits() < Subtarget.getGRLen()))
10092 Align &PrefAlign)
const {
10096 if (Subtarget.is64Bit()) {
10098 PrefAlign =
Align(8);
10101 PrefAlign =
Align(4);
10116bool LoongArchTargetLowering::splitValueIntoRegisterParts(
10118 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
10119 bool IsABIRegCopy = CC.has_value();
10122 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10123 PartVT == MVT::f32) {
10138SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
10140 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
10141 bool IsABIRegCopy = CC.has_value();
10143 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10144 PartVT == MVT::f32) {
10161 if (VT == MVT::f16 && Subtarget.hasBasicF())
10167unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
10170 if (VT == MVT::f16 && Subtarget.hasBasicF())
10179 unsigned Opc =
Op.getOpcode();
10184 case LoongArchISD::VPICK_ZEXT_ELT: {
10198 unsigned Depth)
const {
10199 EVT VT =
Op.getValueType();
10201 unsigned Opc =
Op.getOpcode();
10205 case LoongArchISD::VMSKLTZ:
10206 case LoongArchISD::XVMSKLTZ: {
10208 MVT SrcVT = Src.getSimpleValueType();
10213 if (OriginalDemandedBits.
countr_zero() >= NumElts)
10217 APInt KnownUndef, KnownZero;
10233 if (KnownSrc.
One[SrcBits - 1])
10235 else if (KnownSrc.
Zero[SrcBits - 1])
10240 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
10247 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
10270 unsigned Index)
const {
10279 unsigned Index)
const {
10283 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
static MCRegister MatchRegisterName(StringRef Name)
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 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
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)
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)
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 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_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 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 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 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 std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static 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 performSELECT_CCCombine(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 lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
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 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 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 SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
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)
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 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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - 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 Basic Block Representation.
bool test(unsigned Idx) const
size_type count() const
count - 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.
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.
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 addSExt32Register(Register Reg)
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.
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...
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.
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 getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
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.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
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).
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)
typename SuperClass::const_iterator const_iterator
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.
StringRef - 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
size - 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.
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.
@ 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.
@ 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...
@ 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 ...
@ 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 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 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)
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.
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 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 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)