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()) {
253 if (!Subtarget.hasBasicD()) {
255 if (Subtarget.is64Bit()) {
264 if (Subtarget.hasBasicD()) {
297 if (Subtarget.is64Bit()) {
305 if (Subtarget.hasExtLSX()) {
320 for (
MVT VT : LSXVTs) {
334 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
359 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
361 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
363 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
367 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
392 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
393 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
408 if (Subtarget.hasExtLASX()) {
409 for (
MVT VT : LASXVTs) {
424 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
450 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
452 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
454 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
458 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
487 if (Subtarget.hasExtLSX()) {
494 if (Subtarget.hasExtLASX())
517 if (Subtarget.hasLAMCAS())
520 if (Subtarget.hasSCQ()) {
537 switch (
Op.getOpcode()) {
538 case ISD::ATOMIC_FENCE:
539 return lowerATOMIC_FENCE(
Op, DAG);
541 return lowerEH_DWARF_CFA(
Op, DAG);
543 return lowerGlobalAddress(
Op, DAG);
545 return lowerGlobalTLSAddress(
Op, DAG);
547 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
549 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
551 return lowerINTRINSIC_VOID(
Op, DAG);
553 return lowerBlockAddress(
Op, DAG);
555 return lowerJumpTable(
Op, DAG);
557 return lowerShiftLeftParts(
Op, DAG);
559 return lowerShiftRightParts(
Op, DAG,
true);
561 return lowerShiftRightParts(
Op, DAG,
false);
563 return lowerConstantPool(
Op, DAG);
565 return lowerFP_TO_SINT(
Op, DAG);
567 return lowerBITCAST(
Op, DAG);
569 return lowerUINT_TO_FP(
Op, DAG);
571 return lowerSINT_TO_FP(
Op, DAG);
573 return lowerVASTART(
Op, DAG);
575 return lowerFRAMEADDR(
Op, DAG);
577 return lowerRETURNADDR(
Op, DAG);
579 return lowerWRITE_REGISTER(
Op, DAG);
581 return lowerINSERT_VECTOR_ELT(
Op, DAG);
583 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
585 return lowerBUILD_VECTOR(
Op, DAG);
587 return lowerCONCAT_VECTORS(
Op, DAG);
589 return lowerVECTOR_SHUFFLE(
Op, DAG);
591 return lowerBITREVERSE(
Op, DAG);
593 return lowerSCALAR_TO_VECTOR(
Op, DAG);
595 return lowerPREFETCH(
Op, DAG);
597 return lowerSELECT(
Op, DAG);
599 return lowerBRCOND(
Op, DAG);
600 case ISD::FP_TO_FP16:
601 return lowerFP_TO_FP16(
Op, DAG);
602 case ISD::FP16_TO_FP:
603 return lowerFP16_TO_FP(
Op, DAG);
604 case ISD::FP_TO_BF16:
605 return lowerFP_TO_BF16(
Op, DAG);
606 case ISD::BF16_TO_FP:
607 return lowerBF16_TO_FP(
Op, DAG);
608 case ISD::VECREDUCE_ADD:
609 return lowerVECREDUCE_ADD(
Op, DAG);
612 return lowerRotate(
Op, DAG);
613 case ISD::VECREDUCE_AND:
614 case ISD::VECREDUCE_OR:
615 case ISD::VECREDUCE_XOR:
616 case ISD::VECREDUCE_SMAX:
617 case ISD::VECREDUCE_SMIN:
618 case ISD::VECREDUCE_UMAX:
619 case ISD::VECREDUCE_UMIN:
620 return lowerVECREDUCE(
Op, DAG);
622 return lowerConstantFP(
Op, DAG);
624 return lowerVectorSRL(
Op, DAG);
634 while (
Op.getOpcode() == ISD::BITCAST)
635 Op =
Op.getOperand(0);
637 APInt SplatBits, SplatUndef;
638 unsigned SplatBitSize;
641 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
643 SplatBitSize > ElementBits)
651 EVT VT =
Op.getValueType();
655 if (!
Op.getOperand(1).getValueType().isVector())
658 MVT GRLenVT = Subtarget.getGRLenVT();
661 if (
getVShiftAmt(
Op.getOperand(1), EltSize, Amt) && Amt >= 0 && Amt < EltSize)
662 return DAG.
getNode(LoongArchISD::VSRLI,
DL, VT,
Op.getOperand(0),
664 return DAG.
getNode(LoongArchISD::VSRL,
DL, VT,
Op.getOperand(0),
672 EVT VT = V.getValueType();
678 return V.getOperand(0);
682 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
684 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
694 if (!V->isOnlyUserOf(SplatValue.getNode()))
698 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
706 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
723 EVT VT =
Op.getValueType();
728 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
729 (VT == MVT::f64 && Subtarget.hasBasicD()));
746 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
756 if (Subtarget.is64Bit())
758 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
759 : LoongArchISD::MOVGR2FR_W,
763 if (Subtarget.is64Bit()) {
765 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
769 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
788 MVT OpVT =
Op.getSimpleValueType();
795 unsigned LegalVecSize = 128;
796 bool isLASX256Vector =
806 if (isLASX256Vector) {
811 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
814 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
817 if (isLASX256Vector) {
843 MVT OpVT =
Op.getSimpleValueType();
856 MVT GRLenVT = Subtarget.getGRLenVT();
858 for (
int i = NumEles; i > 1; i /= 2) {
861 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
870 unsigned IsData =
Op.getConstantOperandVal(4);
875 return Op.getOperand(0);
882 MVT VT =
Op.getSimpleValueType();
888 unsigned Opcode =
Op.getOpcode();
891 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
897 CstSplatValue =
C->getAPIntValue();
906 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
910 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
926 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
942 if (
LHS == LHS2 &&
RHS == RHS2) {
947 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
963 MVT VT =
N->getSimpleValueType(0);
994 if (~TrueVal == FalseVal) {
1034 unsigned SelOpNo = 0;
1044 unsigned ConstSelOpNo = 1;
1045 unsigned OtherSelOpNo = 2;
1052 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1057 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1063 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1065 std::swap(NewConstOps[0], NewConstOps[1]);
1077 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1079 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1082 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1083 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1103 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1117 int64_t
C = RHSC->getSExtValue();
1160 MVT VT =
Op.getSimpleValueType();
1161 MVT GRLenVT = Subtarget.getGRLenVT();
1166 if (
Op.hasOneUse()) {
1167 unsigned UseOpc =
Op->user_begin()->getOpcode();
1169 SDNode *BinOp = *
Op->user_begin();
1176 return lowerSELECT(NewSel, DAG);
1193 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1216 if (TrueVal - 1 == FalseVal)
1218 if (TrueVal + 1 == FalseVal)
1225 RHS == TrueV &&
LHS == FalseV) {
1250 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1257 MVT GRLenVT = Subtarget.getGRLenVT();
1268 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1269 Op.getOperand(0),
LHS,
RHS, TargetCC,
1272 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1273 Op.getOperand(0), CondV,
Op.getOperand(2));
1277 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1283LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1286 MVT OpVT =
Op.getSimpleValueType();
1297 EVT ResTy =
Op->getValueType(0);
1302 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1312 for (
unsigned int i = 0; i < NewEltNum; i++) {
1315 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1316 ? (
unsigned)LoongArchISD::BITREV_8B
1334 for (
unsigned int i = 0; i < NewEltNum; i++)
1335 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1336 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1354 if (EltBits > 32 || EltBits == 1)
1382 int MaskOffset,
const APInt &Zeroable) {
1383 int Size = Mask.size();
1384 unsigned SizeInBits =
Size * ScalarSizeInBits;
1386 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1387 for (
int i = 0; i <
Size; i += Scale)
1388 for (
int j = 0; j < Shift; ++j)
1389 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1397 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1398 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1403 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1404 for (
int i = 0; i !=
Size; i += Scale) {
1405 unsigned Pos =
Left ? i + Shift : i;
1406 unsigned Low =
Left ? i : i + Shift;
1407 unsigned Len = Scale - Shift;
1412 int ShiftEltBits = ScalarSizeInBits * Scale;
1413 bool ByteShift = ShiftEltBits > 64;
1414 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1415 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1416 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1420 Scale = ByteShift ? Scale / 2 : Scale;
1426 return (
int)ShiftAmt;
1429 unsigned MaxWidth = 128;
1430 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1431 for (
int Shift = 1; Shift != Scale; ++Shift)
1432 for (
bool Left : {
true,
false})
1433 if (CheckZeros(Shift, Scale,
Left)) {
1434 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1459 const APInt &Zeroable) {
1460 int Size = Mask.size();
1474 Mask,
Size, Zeroable);
1482 "Illegal integer vector type");
1491template <
typename ValType>
1494 unsigned CheckStride,
1496 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1500 if (*
I != -1 && *
I != ExpectedIndex)
1502 ExpectedIndex += ExpectedIndexStride;
1506 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1518 int Size = Mask.size();
1528 int ScalarSizeInBits = VectorSizeInBits /
Size;
1529 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1530 (void)ScalarSizeInBits;
1532 for (
int i = 0; i <
Size; ++i) {
1538 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1555 RepeatedMask.
assign(LaneSize, -1);
1556 int Size = Mask.size();
1557 for (
int i = 0; i <
Size; ++i) {
1558 assert(Mask[i] == -1 || Mask[i] >= 0);
1561 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1568 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1569 if (RepeatedMask[i % LaneSize] < 0)
1571 RepeatedMask[i % LaneSize] = LocalM;
1572 else if (RepeatedMask[i % LaneSize] != LocalM)
1589 int NumElts = RepeatedMask.
size();
1591 int Scale = 16 / NumElts;
1593 for (
int i = 0; i < NumElts; ++i) {
1594 int M = RepeatedMask[i];
1595 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1596 "Unexpected mask index.");
1601 int StartIdx = i - (M % NumElts);
1608 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1611 Rotation = CandidateRotation;
1612 else if (Rotation != CandidateRotation)
1616 SDValue MaskV = M < NumElts ? V1 : V2;
1627 else if (TargetV != MaskV)
1632 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1633 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1642 return Rotation * Scale;
1661 if (ByteRotation <= 0)
1668 int LoByteShift = 16 - ByteRotation;
1669 int HiByteShift = ByteRotation;
1692 const APInt &Zeroable) {
1706 for (
int i = 0; i < NumElements; i++) {
1710 if (i % Scale != 0) {
1721 SDValue V = M < NumElements ? V1 : V2;
1722 M = M % NumElements;
1725 Offset = M - (i / Scale);
1728 if (
Offset % (NumElements / Scale))
1730 }
else if (InputV != V)
1733 if (M != (
Offset + (i / Scale)))
1743 unsigned VilVLoHi = LoongArchISD::VILVL;
1744 if (
Offset >= (NumElements / 2)) {
1745 VilVLoHi = LoongArchISD::VILVH;
1746 Offset -= (NumElements / 2);
1753 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1757 }
while (Scale > 1);
1763 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1764 NumExtElements *= 2) {
1784 int SplatIndex = -1;
1785 for (
const auto &M : Mask) {
1792 if (SplatIndex == -1)
1795 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1797 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
1827 unsigned SubVecSize = 4;
1828 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1831 int SubMask[4] = {-1, -1, -1, -1};
1832 for (
unsigned i = 0; i < SubVecSize; ++i) {
1833 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1839 M -= 4 * (j / SubVecSize);
1840 if (M < 0 || M >= 4)
1846 if (SubMask[i] == -1)
1850 else if (M != -1 && M != SubMask[i])
1857 for (
int i = SubVecSize - 1; i >= 0; --i) {
1870 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1871 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
1874 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
1892 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
1901 for (
int i = 0; i < WidenNumElts; ++i)
1902 WidenMask[i] = WidenNumElts - 1 - i;
1910 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
1934 const auto &Begin = Mask.begin();
1935 const auto &End = Mask.end();
1936 SDValue OriV1 = V1, OriV2 = V2;
1952 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
1974 const auto &Begin = Mask.begin();
1975 const auto &End = Mask.end();
1976 SDValue OriV1 = V1, OriV2 = V2;
1992 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2015 const auto &Begin = Mask.begin();
2016 const auto &End = Mask.end();
2017 unsigned HalfSize = Mask.size() / 2;
2018 SDValue OriV1 = V1, OriV2 = V2;
2035 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2058 const auto &Begin = Mask.begin();
2059 const auto &End = Mask.end();
2060 SDValue OriV1 = V1, OriV2 = V2;
2076 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2098 const auto &Begin = Mask.begin();
2099 const auto &Mid = Mask.begin() + Mask.size() / 2;
2100 const auto &End = Mask.end();
2101 SDValue OriV1 = V1, OriV2 = V2;
2118 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2140 const auto &Begin = Mask.begin();
2141 const auto &Mid = Mask.begin() + Mask.size() / 2;
2142 const auto &End = Mask.end();
2143 SDValue OriV1 = V1, OriV2 = V2;
2159 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2185 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2198 "Vector type is unsupported for lsx!");
2200 "Two operands have different types!");
2202 "Unexpected mask size for shuffle!");
2203 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2205 APInt KnownUndef, KnownZero;
2207 APInt Zeroable = KnownUndef | KnownZero;
2274 int SplatIndex = -1;
2275 for (
const auto &M : Mask) {
2282 if (SplatIndex == -1)
2285 const auto &Begin = Mask.begin();
2286 const auto &End = Mask.end();
2287 int HalfSize = Mask.size() / 2;
2289 if (SplatIndex >= HalfSize)
2292 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2296 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2310 if (Mask.size() <= 4)
2321 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2324 unsigned MaskImm = 0;
2325 for (
unsigned i = 0; i < Mask.size(); ++i) {
2328 MaskImm |= Mask[i] << (i * 2);
2331 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2340 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2344 unsigned HalfSize = NumElts / 2;
2345 bool FrontLo =
true, FrontHi =
true;
2346 bool BackLo =
true, BackHi =
true;
2348 auto inRange = [](
int val,
int low,
int high) {
2349 return (val == -1) || (val >= low && val < high);
2352 for (
unsigned i = 0; i < HalfSize; ++i) {
2353 int Fronti = Mask[i];
2354 int Backi = Mask[i + HalfSize];
2356 FrontLo &=
inRange(Fronti, 0, HalfSize);
2357 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2358 BackLo &=
inRange(Backi, 0, HalfSize);
2359 BackHi &=
inRange(Backi, HalfSize, NumElts);
2365 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2370 for (
unsigned i = 0; i < NumElts; ++i)
2375 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2397 const auto &Begin = Mask.begin();
2398 const auto &End = Mask.end();
2399 unsigned HalfSize = Mask.size() / 2;
2400 unsigned LeftSize = HalfSize / 2;
2401 SDValue OriV1 = V1, OriV2 = V2;
2408 Mask.size() + HalfSize - LeftSize, 1) &&
2410 Mask.size() + HalfSize + LeftSize, 1))
2421 Mask.size() + HalfSize - LeftSize, 1) &&
2423 Mask.size() + HalfSize + LeftSize, 1))
2428 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2436 const auto &Begin = Mask.begin();
2437 const auto &End = Mask.end();
2438 unsigned HalfSize = Mask.size() / 2;
2439 SDValue OriV1 = V1, OriV2 = V2;
2446 Mask.size() + HalfSize, 1))
2457 Mask.size() + HalfSize, 1))
2462 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2470 const auto &Begin = Mask.begin();
2471 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2472 const auto &Mid = Mask.begin() + Mask.size() / 2;
2473 const auto &RightMid = Mask.end() - Mask.size() / 4;
2474 const auto &End = Mask.end();
2475 unsigned HalfSize = Mask.size() / 2;
2476 SDValue OriV1 = V1, OriV2 = V2;
2497 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2505 const auto &Begin = Mask.begin();
2506 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2507 const auto &Mid = Mask.begin() + Mask.size() / 2;
2508 const auto &RightMid = Mask.end() - Mask.size() / 4;
2509 const auto &End = Mask.end();
2510 unsigned HalfSize = Mask.size() / 2;
2511 SDValue OriV1 = V1, OriV2 = V2;
2533 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2542 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2547 int MaskSize = Mask.size();
2553 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2555 for (
int i = 0; i < MaskSize; ++i) {
2556 if (Mask[i] ==
Base + i || Mask[i] == -1)
2558 if (Mask[i] != Replaced)
2569 int Idx = checkReplaceOne(0, MaskSize);
2571 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
2575 Idx = checkReplaceOne(MaskSize, 0);
2577 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
2588 int MaskSize = Mask.size();
2589 int HalfSize = Mask.size() / 2;
2590 const auto &Begin = Mask.begin();
2591 const auto &Mid = Mask.begin() + HalfSize;
2592 const auto &End = Mask.end();
2604 for (
auto it = Begin; it < Mid; it++) {
2607 else if ((*it >= 0 && *it < HalfSize) ||
2608 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2609 int M = *it < HalfSize ? *it : *it - HalfSize;
2614 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2616 for (
auto it = Mid; it < End; it++) {
2619 else if ((*it >= HalfSize && *it < MaskSize) ||
2620 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2621 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2626 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2630 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2658 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2660 int MaskSize = Mask.size();
2661 int HalfSize = Mask.size() / 2;
2664 HalfMaskType preMask =
None, postMask =
None;
2666 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2667 return M < 0 || (M >= 0 && M < HalfSize) ||
2668 (M >= MaskSize && M < MaskSize + HalfSize);
2670 preMask = HighLaneTy;
2671 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2672 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2673 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2675 preMask = LowLaneTy;
2677 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2678 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2679 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2681 postMask = LowLaneTy;
2682 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2683 return M < 0 || (M >= 0 && M < HalfSize) ||
2684 (M >= MaskSize && M < MaskSize + HalfSize);
2686 postMask = HighLaneTy;
2694 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2697 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2699 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2705 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2710 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2711 *it = *it < 0 ? *it : *it - HalfSize;
2713 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2714 *it = *it < 0 ? *it : *it + HalfSize;
2716 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2718 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2724 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2729 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2730 *it = *it < 0 ? *it : *it - HalfSize;
2732 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2734 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2740 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2745 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2746 *it = *it < 0 ? *it : *it + HalfSize;
2771 int Size = Mask.size();
2772 int LaneSize =
Size / 2;
2774 bool LaneCrossing[2] = {
false,
false};
2775 for (
int i = 0; i <
Size; ++i)
2776 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2777 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2780 if (!LaneCrossing[0] && !LaneCrossing[1])
2784 InLaneMask.
assign(Mask.begin(), Mask.end());
2785 for (
int i = 0; i <
Size; ++i) {
2786 int &M = InLaneMask[i];
2789 if (((M %
Size) / LaneSize) != (i / LaneSize))
2790 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2795 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2810 "Vector type is unsupported for lasx!");
2812 "Two operands have different types!");
2814 "Unexpected mask size for shuffle!");
2815 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2816 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2818 APInt KnownUndef, KnownZero;
2820 APInt Zeroable = KnownUndef | KnownZero;
2897 ArrayRef<int> OrigMask = SVOp->
getMask();
2900 MVT VT =
Op.getSimpleValueType();
2904 bool V1IsUndef = V1.
isUndef();
2905 bool V2IsUndef = V2.
isUndef();
2906 if (V1IsUndef && V2IsUndef)
2919 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2920 SmallVector<int, 8> NewMask(OrigMask);
2921 for (
int &M : NewMask)
2922 if (M >= NumElements)
2928 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2929 (void)MaskUpperLimit;
2931 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2932 "Out of bounds shuffle index");
2954 std::tie(Res, Chain) =
2955 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2956 if (Subtarget.is64Bit())
2957 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
2969 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
2973 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2974 CallOptions,
DL, Chain);
2980 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2986 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2987 if (Subtarget.is64Bit())
2988 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
2994 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2995 MVT VT =
Op.getSimpleValueType();
3000 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3004 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
3021 "Unsupported vector type for broadcast.");
3024 bool IsIdeneity =
true;
3026 for (
int i = 0; i !=
NumOps; i++) {
3028 if (
Op.getOpcode() != ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3040 auto ExtType = LN->getExtensionType();
3045 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3050 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3068 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3082 EVT ResTy,
unsigned first) {
3085 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3088 Node->op_begin() + first + NumElts);
3097 MVT VT =
Node->getSimpleValueType(0);
3098 EVT ResTy =
Op->getValueType(0);
3101 APInt SplatValue, SplatUndef;
3102 unsigned SplatBitSize;
3105 bool UseSameConstant =
true;
3110 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3111 (!Subtarget.hasExtLASX() || !Is256Vec))
3117 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3119 SplatBitSize <= 64) {
3121 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3125 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3132 if ((Is128Vec && ResTy == MVT::v4i32) ||
3133 (Is256Vec && ResTy == MVT::v8i32))
3139 switch (SplatBitSize) {
3143 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3146 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3149 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3152 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3160 if (ViaVecTy != ResTy)
3161 Result = DAG.
getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
3169 for (
unsigned i = 0; i < NumElts; ++i) {
3174 ConstantValue = Opi;
3175 else if (ConstantValue != Opi)
3176 UseSameConstant =
false;
3181 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3183 for (
unsigned i = 0; i < NumElts; ++i) {
3201 BitVector UndefElements;
3202 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3203 UndefElements.
count() == 0) {
3207 EVT FillTy = Is256Vec
3213 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3216 unsigned SplatLen = NumElts / SeqLen;
3222 if (SplatEltTy == MVT::i128)
3223 SplatTy = MVT::v4i64;
3231 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3232 : LoongArchISD::XVREPLVE0,
3233 DL, SplatTy, SrcVec);
3235 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3248 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3249 ResTy == MVT::v4f64) {
3250 unsigned NonUndefCount = 0;
3251 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3252 if (!
Node->getOperand(i).isUndef()) {
3254 if (NonUndefCount > 1)
3258 if (NonUndefCount == 1)
3271 VecTy, NumElts / 2);
3282 MVT ResVT =
Op.getSimpleValueType();
3286 unsigned NumFreezeUndef = 0;
3287 unsigned NumZero = 0;
3288 unsigned NumNonZero = 0;
3289 unsigned NonZeros = 0;
3290 SmallSet<SDValue, 4> Undefs;
3291 for (
unsigned i = 0; i != NumOperands; ++i) {
3306 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3313 if (NumNonZero > 2) {
3317 Ops.slice(0, NumOperands / 2));
3319 Ops.slice(NumOperands / 2));
3332 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3334 for (
unsigned i = 0; i != NumOperands; ++i) {
3335 if ((NonZeros & (1 << i)) == 0)
3346LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3348 MVT EltVT =
Op.getSimpleValueType();
3353 MVT GRLenVT = Subtarget.getGRLenVT();
3381 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3385 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3387 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3396 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3405LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3407 MVT VT =
Op.getSimpleValueType();
3430 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3432 for (
unsigned i = 0; i < NumElts; ++i) {
3440 for (
unsigned i = 0; i < NumElts; ++i) {
3449 for (
unsigned i = 0; i < NumElts; ++i)
3473 return DAG.
getNode(ISD::MEMBARRIER,
DL, MVT::Other,
Op.getOperand(0));
3481 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3483 "On LA64, only 64-bit registers can be written.");
3484 return Op.getOperand(0);
3487 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3489 "On LA32, only 32-bit registers can be written.");
3490 return Op.getOperand(0);
3500 "be a constant integer");
3506 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3507 EVT VT =
Op.getValueType();
3510 unsigned Depth =
Op.getConstantOperandVal(0);
3511 int GRLenInBytes = Subtarget.getGRLen() / 8;
3514 int Offset = -(GRLenInBytes * 2);
3526 if (
Op.getConstantOperandVal(0) != 0) {
3528 "return address can only be determined for the current frame");
3534 MVT GRLenVT = Subtarget.getGRLenVT();
3546 auto Size = Subtarget.getGRLen() / 8;
3554 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3564 MachinePointerInfo(SV));
3569 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3570 !Subtarget.hasBasicD() &&
"unexpected target features");
3576 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3580 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
3590 EVT RetVT =
Op.getValueType();
3596 std::tie(Result, Chain) =
3603 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3604 !Subtarget.hasBasicD() &&
"unexpected target features");
3615 EVT RetVT =
Op.getValueType();
3621 std::tie(Result, Chain) =
3630 EVT VT =
Op.getValueType();
3634 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3635 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3637 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
3639 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3642 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
3654 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
3656 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3657 !Subtarget.hasBasicD()) {
3659 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
3664 return DAG.
getNode(ISD::BITCAST,
DL,
Op.getValueType(), Trunc);
3681 N->getOffset(), Flags);
3689template <
class NodeTy>
3692 bool IsLocal)
const {
3703 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3774 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3776 const GlobalValue *GV =
N->getGlobal();
3788 unsigned Opc,
bool UseGOT,
3792 MVT GRLenVT = Subtarget.getGRLenVT();
3806 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3844 Args.emplace_back(Load, CallTy);
3847 TargetLowering::CallLoweringInfo CLI(DAG);
3862 const GlobalValue *GV =
N->getGlobal();
3876LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3883 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3886 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3899 return getDynamicTLSAddr(
N, DAG,
3900 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3901 : LoongArch::PseudoLA_TLS_GD,
3908 return getDynamicTLSAddr(
N, DAG,
3909 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3910 : LoongArch::PseudoLA_TLS_LD,
3915 return getStaticTLSAddr(
N, DAG,
3916 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3917 : LoongArch::PseudoLA_TLS_IE,
3924 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3928 return getTLSDescAddr(
N, DAG,
3929 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3930 : LoongArch::PseudoLA_TLS_DESC,
3934template <
unsigned N>
3939 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
3940 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
3942 ": argument out of range.");
3949LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3951 switch (
Op.getConstantOperandVal(0)) {
3954 case Intrinsic::thread_pointer: {
3958 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3959 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3960 case Intrinsic::loongarch_lsx_vreplvei_d:
3961 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3963 case Intrinsic::loongarch_lsx_vreplvei_w:
3964 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3965 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3966 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3967 case Intrinsic::loongarch_lasx_xvpickve_d:
3968 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3970 case Intrinsic::loongarch_lasx_xvinsve0_d:
3972 case Intrinsic::loongarch_lsx_vsat_b:
3973 case Intrinsic::loongarch_lsx_vsat_bu:
3974 case Intrinsic::loongarch_lsx_vrotri_b:
3975 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3976 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3977 case Intrinsic::loongarch_lsx_vsrlri_b:
3978 case Intrinsic::loongarch_lsx_vsrari_b:
3979 case Intrinsic::loongarch_lsx_vreplvei_h:
3980 case Intrinsic::loongarch_lasx_xvsat_b:
3981 case Intrinsic::loongarch_lasx_xvsat_bu:
3982 case Intrinsic::loongarch_lasx_xvrotri_b:
3983 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3984 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3985 case Intrinsic::loongarch_lasx_xvsrlri_b:
3986 case Intrinsic::loongarch_lasx_xvsrari_b:
3987 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3988 case Intrinsic::loongarch_lasx_xvpickve_w:
3989 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3991 case Intrinsic::loongarch_lasx_xvinsve0_w:
3993 case Intrinsic::loongarch_lsx_vsat_h:
3994 case Intrinsic::loongarch_lsx_vsat_hu:
3995 case Intrinsic::loongarch_lsx_vrotri_h:
3996 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3997 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3998 case Intrinsic::loongarch_lsx_vsrlri_h:
3999 case Intrinsic::loongarch_lsx_vsrari_h:
4000 case Intrinsic::loongarch_lsx_vreplvei_b:
4001 case Intrinsic::loongarch_lasx_xvsat_h:
4002 case Intrinsic::loongarch_lasx_xvsat_hu:
4003 case Intrinsic::loongarch_lasx_xvrotri_h:
4004 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4005 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4006 case Intrinsic::loongarch_lasx_xvsrlri_h:
4007 case Intrinsic::loongarch_lasx_xvsrari_h:
4008 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4010 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4011 case Intrinsic::loongarch_lsx_vsrani_b_h:
4012 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4013 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4014 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4015 case Intrinsic::loongarch_lsx_vssrani_b_h:
4016 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4017 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4018 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4019 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4020 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4021 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4022 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4023 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4024 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4025 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4026 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4027 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4028 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4029 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4030 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4031 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4032 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4033 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4035 case Intrinsic::loongarch_lsx_vsat_w:
4036 case Intrinsic::loongarch_lsx_vsat_wu:
4037 case Intrinsic::loongarch_lsx_vrotri_w:
4038 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4039 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4040 case Intrinsic::loongarch_lsx_vsrlri_w:
4041 case Intrinsic::loongarch_lsx_vsrari_w:
4042 case Intrinsic::loongarch_lsx_vslei_bu:
4043 case Intrinsic::loongarch_lsx_vslei_hu:
4044 case Intrinsic::loongarch_lsx_vslei_wu:
4045 case Intrinsic::loongarch_lsx_vslei_du:
4046 case Intrinsic::loongarch_lsx_vslti_bu:
4047 case Intrinsic::loongarch_lsx_vslti_hu:
4048 case Intrinsic::loongarch_lsx_vslti_wu:
4049 case Intrinsic::loongarch_lsx_vslti_du:
4050 case Intrinsic::loongarch_lsx_vbsll_v:
4051 case Intrinsic::loongarch_lsx_vbsrl_v:
4052 case Intrinsic::loongarch_lasx_xvsat_w:
4053 case Intrinsic::loongarch_lasx_xvsat_wu:
4054 case Intrinsic::loongarch_lasx_xvrotri_w:
4055 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4056 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4057 case Intrinsic::loongarch_lasx_xvsrlri_w:
4058 case Intrinsic::loongarch_lasx_xvsrari_w:
4059 case Intrinsic::loongarch_lasx_xvslei_bu:
4060 case Intrinsic::loongarch_lasx_xvslei_hu:
4061 case Intrinsic::loongarch_lasx_xvslei_wu:
4062 case Intrinsic::loongarch_lasx_xvslei_du:
4063 case Intrinsic::loongarch_lasx_xvslti_bu:
4064 case Intrinsic::loongarch_lasx_xvslti_hu:
4065 case Intrinsic::loongarch_lasx_xvslti_wu:
4066 case Intrinsic::loongarch_lasx_xvslti_du:
4067 case Intrinsic::loongarch_lasx_xvbsll_v:
4068 case Intrinsic::loongarch_lasx_xvbsrl_v:
4070 case Intrinsic::loongarch_lsx_vseqi_b:
4071 case Intrinsic::loongarch_lsx_vseqi_h:
4072 case Intrinsic::loongarch_lsx_vseqi_w:
4073 case Intrinsic::loongarch_lsx_vseqi_d:
4074 case Intrinsic::loongarch_lsx_vslei_b:
4075 case Intrinsic::loongarch_lsx_vslei_h:
4076 case Intrinsic::loongarch_lsx_vslei_w:
4077 case Intrinsic::loongarch_lsx_vslei_d:
4078 case Intrinsic::loongarch_lsx_vslti_b:
4079 case Intrinsic::loongarch_lsx_vslti_h:
4080 case Intrinsic::loongarch_lsx_vslti_w:
4081 case Intrinsic::loongarch_lsx_vslti_d:
4082 case Intrinsic::loongarch_lasx_xvseqi_b:
4083 case Intrinsic::loongarch_lasx_xvseqi_h:
4084 case Intrinsic::loongarch_lasx_xvseqi_w:
4085 case Intrinsic::loongarch_lasx_xvseqi_d:
4086 case Intrinsic::loongarch_lasx_xvslei_b:
4087 case Intrinsic::loongarch_lasx_xvslei_h:
4088 case Intrinsic::loongarch_lasx_xvslei_w:
4089 case Intrinsic::loongarch_lasx_xvslei_d:
4090 case Intrinsic::loongarch_lasx_xvslti_b:
4091 case Intrinsic::loongarch_lasx_xvslti_h:
4092 case Intrinsic::loongarch_lasx_xvslti_w:
4093 case Intrinsic::loongarch_lasx_xvslti_d:
4095 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4096 case Intrinsic::loongarch_lsx_vsrani_h_w:
4097 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4098 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4099 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4100 case Intrinsic::loongarch_lsx_vssrani_h_w:
4101 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4102 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4103 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4104 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4105 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4106 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4107 case Intrinsic::loongarch_lsx_vfrstpi_b:
4108 case Intrinsic::loongarch_lsx_vfrstpi_h:
4109 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4110 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4111 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4112 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4113 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4114 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4115 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4116 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4117 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4118 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4119 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4120 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4121 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4122 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4124 case Intrinsic::loongarch_lsx_vsat_d:
4125 case Intrinsic::loongarch_lsx_vsat_du:
4126 case Intrinsic::loongarch_lsx_vrotri_d:
4127 case Intrinsic::loongarch_lsx_vsrlri_d:
4128 case Intrinsic::loongarch_lsx_vsrari_d:
4129 case Intrinsic::loongarch_lasx_xvsat_d:
4130 case Intrinsic::loongarch_lasx_xvsat_du:
4131 case Intrinsic::loongarch_lasx_xvrotri_d:
4132 case Intrinsic::loongarch_lasx_xvsrlri_d:
4133 case Intrinsic::loongarch_lasx_xvsrari_d:
4135 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4136 case Intrinsic::loongarch_lsx_vsrani_w_d:
4137 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4138 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4139 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4140 case Intrinsic::loongarch_lsx_vssrani_w_d:
4141 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4142 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4143 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4144 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4145 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4146 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4147 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4148 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4149 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4150 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4151 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4152 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4153 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4154 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4155 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4156 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4157 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4158 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4160 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4161 case Intrinsic::loongarch_lsx_vsrani_d_q:
4162 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4163 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4164 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4165 case Intrinsic::loongarch_lsx_vssrani_d_q:
4166 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4167 case Intrinsic::loongarch_lsx_vssrani_du_q:
4168 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4169 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4170 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4171 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4172 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4173 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4174 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4175 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4176 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4177 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4178 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4179 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4180 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4181 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4182 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4183 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4185 case Intrinsic::loongarch_lsx_vnori_b:
4186 case Intrinsic::loongarch_lsx_vshuf4i_b:
4187 case Intrinsic::loongarch_lsx_vshuf4i_h:
4188 case Intrinsic::loongarch_lsx_vshuf4i_w:
4189 case Intrinsic::loongarch_lasx_xvnori_b:
4190 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4191 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4192 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4193 case Intrinsic::loongarch_lasx_xvpermi_d:
4195 case Intrinsic::loongarch_lsx_vshuf4i_d:
4196 case Intrinsic::loongarch_lsx_vpermi_w:
4197 case Intrinsic::loongarch_lsx_vbitseli_b:
4198 case Intrinsic::loongarch_lsx_vextrins_b:
4199 case Intrinsic::loongarch_lsx_vextrins_h:
4200 case Intrinsic::loongarch_lsx_vextrins_w:
4201 case Intrinsic::loongarch_lsx_vextrins_d:
4202 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4203 case Intrinsic::loongarch_lasx_xvpermi_w:
4204 case Intrinsic::loongarch_lasx_xvpermi_q:
4205 case Intrinsic::loongarch_lasx_xvbitseli_b:
4206 case Intrinsic::loongarch_lasx_xvextrins_b:
4207 case Intrinsic::loongarch_lasx_xvextrins_h:
4208 case Intrinsic::loongarch_lasx_xvextrins_w:
4209 case Intrinsic::loongarch_lasx_xvextrins_d:
4211 case Intrinsic::loongarch_lsx_vrepli_b:
4212 case Intrinsic::loongarch_lsx_vrepli_h:
4213 case Intrinsic::loongarch_lsx_vrepli_w:
4214 case Intrinsic::loongarch_lsx_vrepli_d:
4215 case Intrinsic::loongarch_lasx_xvrepli_b:
4216 case Intrinsic::loongarch_lasx_xvrepli_h:
4217 case Intrinsic::loongarch_lasx_xvrepli_w:
4218 case Intrinsic::loongarch_lasx_xvrepli_d:
4220 case Intrinsic::loongarch_lsx_vldi:
4221 case Intrinsic::loongarch_lasx_xvldi:
4237LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4240 MVT GRLenVT = Subtarget.getGRLenVT();
4241 EVT VT =
Op.getValueType();
4243 const StringRef ErrorMsgOOR =
"argument out of range";
4244 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4245 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4247 switch (
Op.getConstantOperandVal(1)) {
4250 case Intrinsic::loongarch_crc_w_b_w:
4251 case Intrinsic::loongarch_crc_w_h_w:
4252 case Intrinsic::loongarch_crc_w_w_w:
4253 case Intrinsic::loongarch_crc_w_d_w:
4254 case Intrinsic::loongarch_crcc_w_b_w:
4255 case Intrinsic::loongarch_crcc_w_h_w:
4256 case Intrinsic::loongarch_crcc_w_w_w:
4257 case Intrinsic::loongarch_crcc_w_d_w:
4259 case Intrinsic::loongarch_csrrd_w:
4260 case Intrinsic::loongarch_csrrd_d: {
4261 unsigned Imm =
Op.getConstantOperandVal(2);
4264 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4267 case Intrinsic::loongarch_csrwr_w:
4268 case Intrinsic::loongarch_csrwr_d: {
4269 unsigned Imm =
Op.getConstantOperandVal(3);
4272 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4273 {Chain,
Op.getOperand(2),
4276 case Intrinsic::loongarch_csrxchg_w:
4277 case Intrinsic::loongarch_csrxchg_d: {
4278 unsigned Imm =
Op.getConstantOperandVal(4);
4281 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4282 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4285 case Intrinsic::loongarch_iocsrrd_d: {
4287 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4290#define IOCSRRD_CASE(NAME, NODE) \
4291 case Intrinsic::loongarch_##NAME: { \
4292 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4293 {Chain, Op.getOperand(2)}); \
4299 case Intrinsic::loongarch_cpucfg: {
4300 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4301 {Chain,
Op.getOperand(2)});
4303 case Intrinsic::loongarch_lddir_d: {
4304 unsigned Imm =
Op.getConstantOperandVal(3);
4309 case Intrinsic::loongarch_movfcsr2gr: {
4310 if (!Subtarget.hasBasicF())
4312 unsigned Imm =
Op.getConstantOperandVal(2);
4315 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4318 case Intrinsic::loongarch_lsx_vld:
4319 case Intrinsic::loongarch_lsx_vldrepl_b:
4320 case Intrinsic::loongarch_lasx_xvld:
4321 case Intrinsic::loongarch_lasx_xvldrepl_b:
4325 case Intrinsic::loongarch_lsx_vldrepl_h:
4326 case Intrinsic::loongarch_lasx_xvldrepl_h:
4330 Op,
"argument out of range or not a multiple of 2", DAG)
4332 case Intrinsic::loongarch_lsx_vldrepl_w:
4333 case Intrinsic::loongarch_lasx_xvldrepl_w:
4337 Op,
"argument out of range or not a multiple of 4", DAG)
4339 case Intrinsic::loongarch_lsx_vldrepl_d:
4340 case Intrinsic::loongarch_lasx_xvldrepl_d:
4344 Op,
"argument out of range or not a multiple of 8", DAG)
4355 return Op.getOperand(0);
4361 MVT GRLenVT = Subtarget.getGRLenVT();
4363 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4365 const StringRef ErrorMsgOOR =
"argument out of range";
4366 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4367 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4368 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4370 switch (IntrinsicEnum) {
4374 case Intrinsic::loongarch_cacop_d:
4375 case Intrinsic::loongarch_cacop_w: {
4376 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4378 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4387 case Intrinsic::loongarch_dbar: {
4394 case Intrinsic::loongarch_ibar: {
4401 case Intrinsic::loongarch_break: {
4408 case Intrinsic::loongarch_movgr2fcsr: {
4409 if (!Subtarget.hasBasicF())
4419 case Intrinsic::loongarch_syscall: {
4426#define IOCSRWR_CASE(NAME, NODE) \
4427 case Intrinsic::loongarch_##NAME: { \
4428 SDValue Op3 = Op.getOperand(3); \
4429 return Subtarget.is64Bit() \
4430 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4431 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4432 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4433 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4440 case Intrinsic::loongarch_iocsrwr_d: {
4441 return !Subtarget.is64Bit()
4448#define ASRT_LE_GT_CASE(NAME) \
4449 case Intrinsic::loongarch_##NAME: { \
4450 return !Subtarget.is64Bit() \
4451 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4456#undef ASRT_LE_GT_CASE
4457 case Intrinsic::loongarch_ldpte_d: {
4458 unsigned Imm =
Op.getConstantOperandVal(3);
4459 return !Subtarget.is64Bit()
4464 case Intrinsic::loongarch_lsx_vst:
4465 case Intrinsic::loongarch_lasx_xvst:
4469 case Intrinsic::loongarch_lasx_xvstelm_b:
4474 case Intrinsic::loongarch_lsx_vstelm_b:
4479 case Intrinsic::loongarch_lasx_xvstelm_h:
4484 Op,
"argument out of range or not a multiple of 2", DAG)
4486 case Intrinsic::loongarch_lsx_vstelm_h:
4491 Op,
"argument out of range or not a multiple of 2", DAG)
4493 case Intrinsic::loongarch_lasx_xvstelm_w:
4498 Op,
"argument out of range or not a multiple of 4", DAG)
4500 case Intrinsic::loongarch_lsx_vstelm_w:
4505 Op,
"argument out of range or not a multiple of 4", DAG)
4507 case Intrinsic::loongarch_lasx_xvstelm_d:
4512 Op,
"argument out of range or not a multiple of 8", DAG)
4514 case Intrinsic::loongarch_lsx_vstelm_d:
4519 Op,
"argument out of range or not a multiple of 8", DAG)
4530 EVT VT =
Lo.getValueType();
4571 EVT VT =
Lo.getValueType();
4625 return LoongArchISD::DIV_W;
4627 return LoongArchISD::DIV_WU;
4629 return LoongArchISD::MOD_W;
4631 return LoongArchISD::MOD_WU;
4633 return LoongArchISD::SLL_W;
4635 return LoongArchISD::SRA_W;
4637 return LoongArchISD::SRL_W;
4640 return LoongArchISD::ROTR_W;
4642 return LoongArchISD::CTZ_W;
4644 return LoongArchISD::CLZ_W;
4663 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4664 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4668 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4674 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4701 StringRef ErrorMsg,
bool WithChain =
true) {
4706 Results.push_back(
N->getOperand(0));
4709template <
unsigned N>
4714 const StringRef ErrorMsgOOR =
"argument out of range";
4715 unsigned Imm =
Node->getConstantOperandVal(2);
4749 switch (
N->getConstantOperandVal(0)) {
4752 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4754 LoongArchISD::VPICK_SEXT_ELT);
4756 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4757 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4759 LoongArchISD::VPICK_SEXT_ELT);
4761 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4763 LoongArchISD::VPICK_SEXT_ELT);
4765 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4767 LoongArchISD::VPICK_ZEXT_ELT);
4769 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4770 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4772 LoongArchISD::VPICK_ZEXT_ELT);
4774 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4776 LoongArchISD::VPICK_ZEXT_ELT);
4778 case Intrinsic::loongarch_lsx_bz_b:
4779 case Intrinsic::loongarch_lsx_bz_h:
4780 case Intrinsic::loongarch_lsx_bz_w:
4781 case Intrinsic::loongarch_lsx_bz_d:
4782 case Intrinsic::loongarch_lasx_xbz_b:
4783 case Intrinsic::loongarch_lasx_xbz_h:
4784 case Intrinsic::loongarch_lasx_xbz_w:
4785 case Intrinsic::loongarch_lasx_xbz_d:
4787 LoongArchISD::VALL_ZERO);
4789 case Intrinsic::loongarch_lsx_bz_v:
4790 case Intrinsic::loongarch_lasx_xbz_v:
4792 LoongArchISD::VANY_ZERO);
4794 case Intrinsic::loongarch_lsx_bnz_b:
4795 case Intrinsic::loongarch_lsx_bnz_h:
4796 case Intrinsic::loongarch_lsx_bnz_w:
4797 case Intrinsic::loongarch_lsx_bnz_d:
4798 case Intrinsic::loongarch_lasx_xbnz_b:
4799 case Intrinsic::loongarch_lasx_xbnz_h:
4800 case Intrinsic::loongarch_lasx_xbnz_w:
4801 case Intrinsic::loongarch_lasx_xbnz_d:
4803 LoongArchISD::VALL_NONZERO);
4805 case Intrinsic::loongarch_lsx_bnz_v:
4806 case Intrinsic::loongarch_lasx_xbnz_v:
4808 LoongArchISD::VANY_NONZERO);
4816 assert(
N->getValueType(0) == MVT::i128 &&
4817 "AtomicCmpSwap on types less than 128 should be legal");
4821 switch (
MemOp->getMergedOrdering()) {
4825 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4829 Opcode = LoongArch::PseudoCmpXchg128;
4836 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4837 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4838 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4839 NewVal.first, NewVal.second,
N->getOperand(0)};
4842 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4853 EVT VT =
N->getValueType(0);
4854 switch (
N->getOpcode()) {
4859 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4860 "Unexpected custom legalisation");
4867 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4868 "Unexpected custom legalisation");
4870 Subtarget.hasDiv32() && VT == MVT::i32
4877 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4878 "Unexpected custom legalisation");
4886 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4887 "Unexpected custom legalisation");
4891 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4892 "Unexpected custom legalisation");
4899 if (Src.getValueType() == MVT::f16)
4900 Src = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Src);
4910 EVT OpVT = Src.getValueType();
4914 std::tie(Result, Chain) =
4919 case ISD::BITCAST: {
4921 EVT SrcVT = Src.getValueType();
4922 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
4923 Subtarget.hasBasicF()) {
4925 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
4927 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
4929 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4937 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4938 "Unexpected custom legalisation");
4941 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4947 assert((VT == MVT::i16 || VT == MVT::i32) &&
4948 "Unexpected custom legalization");
4949 MVT GRLenVT = Subtarget.getGRLenVT();
4956 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
4961 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
4969 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
4970 "Unexpected custom legalization");
4971 MVT GRLenVT = Subtarget.getGRLenVT();
4978 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
4981 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
4989 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4990 "Unexpected custom legalisation");
4997 MVT GRLenVT = Subtarget.getGRLenVT();
4998 const StringRef ErrorMsgOOR =
"argument out of range";
4999 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5000 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5002 switch (
N->getConstantOperandVal(1)) {
5005 case Intrinsic::loongarch_movfcsr2gr: {
5006 if (!Subtarget.hasBasicF()) {
5016 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5023#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5024 case Intrinsic::loongarch_##NAME: { \
5025 SDValue NODE = DAG.getNode( \
5026 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5027 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5028 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5029 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5030 Results.push_back(NODE.getValue(1)); \
5039#undef CRC_CASE_EXT_BINARYOP
5041#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5042 case Intrinsic::loongarch_##NAME: { \
5043 SDValue NODE = DAG.getNode( \
5044 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5046 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5047 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5048 Results.push_back(NODE.getValue(1)); \
5053#undef CRC_CASE_EXT_UNARYOP
5054#define CSR_CASE(ID) \
5055 case Intrinsic::loongarch_##ID: { \
5056 if (!Subtarget.is64Bit()) \
5057 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5065 case Intrinsic::loongarch_csrrd_w: {
5072 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5079 case Intrinsic::loongarch_csrwr_w: {
5080 unsigned Imm =
N->getConstantOperandVal(3);
5086 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5094 case Intrinsic::loongarch_csrxchg_w: {
5095 unsigned Imm =
N->getConstantOperandVal(4);
5101 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5110#define IOCSRRD_CASE(NAME, NODE) \
5111 case Intrinsic::loongarch_##NAME: { \
5112 SDValue IOCSRRDResults = \
5113 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5114 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5115 Results.push_back( \
5116 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5117 Results.push_back(IOCSRRDResults.getValue(1)); \
5124 case Intrinsic::loongarch_cpucfg: {
5126 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5133 case Intrinsic::loongarch_lddir_d: {
5134 if (!Subtarget.is64Bit()) {
5144 if (Subtarget.is64Bit())
5146 "On LA64, only 64-bit registers can be read.");
5149 "On LA32, only 32-bit registers can be read.");
5151 Results.push_back(
N->getOperand(0));
5162 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5170 case ISD::ATOMIC_CMP_SWAP: {
5175 MVT VT =
N->getSimpleValueType(0);
5181 EVT InVT = In.getValueType();
5192 for (
unsigned I = 0;
I < MinElts; ++
I)
5193 TruncMask[
I] = Scale *
I;
5195 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5196 MVT SVT = In.getSimpleValueType().getScalarType();
5202 "Illegal vector type in truncation");
5218 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5220 MVT VT =
N->getSimpleValueType(0);
5239 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5248 SDValue FirstOperand =
N->getOperand(0);
5249 SDValue SecondOperand =
N->getOperand(1);
5250 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5251 EVT ValTy =
N->getValueType(0);
5254 unsigned SMIdx, SMLen;
5263 if (!Subtarget.has32S())
5285 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
5300 if (SMIdx + SMLen > ValTy.getSizeInBits())
5319 NewOperand = FirstOperand;
5322 msb = lsb + SMLen - 1;
5326 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5339 if (!Subtarget.has32S())
5351 SDValue FirstOperand =
N->getOperand(0);
5353 EVT ValTy =
N->getValueType(0);
5356 unsigned MaskIdx, MaskLen;
5371 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5372 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
5387 switch (Src.getOpcode()) {
5390 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5400 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5413 switch (Src.getOpcode()) {
5423 Src.getOpcode(),
DL, SExtVT,
5429 DL, SExtVT, Src.getOperand(0),
5441 EVT VT =
N->getValueType(0);
5443 EVT SrcVT = Src.getValueType();
5445 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5450 EVT CmpVT = Src.getOperand(0).getValueType();
5455 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5468 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
5473 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5478 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5483 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5485 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5490 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5492 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5497 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
5514 EVT VT =
N->getValueType(0);
5516 EVT SrcVT = Src.getValueType();
5533 bool UseLASX =
false;
5534 bool PropagateSExt =
false;
5536 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5537 EVT CmpVT = Src.getOperand(0).getValueType();
5546 SExtVT = MVT::v2i64;
5549 SExtVT = MVT::v4i32;
5551 SExtVT = MVT::v4i64;
5553 PropagateSExt =
true;
5557 SExtVT = MVT::v8i16;
5559 SExtVT = MVT::v8i32;
5561 PropagateSExt =
true;
5565 SExtVT = MVT::v16i8;
5567 SExtVT = MVT::v16i16;
5569 PropagateSExt =
true;
5573 SExtVT = MVT::v32i8;
5581 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5582 if (Src.getSimpleValueType() == MVT::v32i8) {
5590 }
else if (UseLASX) {
5596 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5609 EVT ValTy =
N->getValueType(0);
5610 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5613 unsigned ValBits = ValTy.getSizeInBits();
5614 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5616 bool SwapAndRetried =
false;
5619 if (!Subtarget.has32S())
5625 if (ValBits != 32 && ValBits != 64)
5640 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5643 (MaskIdx0 + MaskLen0 <= ValBits)) {
5664 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5665 (MaskIdx0 + MaskLen0 <= ValBits)) {
5682 (MaskIdx0 + MaskLen0 <= 64) &&
5690 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5691 : (MaskIdx0 + MaskLen0 - 1),
5707 (MaskIdx0 + MaskLen0 <= ValBits)) {
5730 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5731 : (MaskIdx0 + MaskLen0 - 1),
5746 unsigned MaskIdx, MaskLen;
5747 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5756 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5774 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5780 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5788 if (!SwapAndRetried) {
5790 SwapAndRetried =
true;
5794 SwapAndRetried =
false;
5811 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5820 if (!SwapAndRetried) {
5822 SwapAndRetried =
true;
5832 switch (V.getNode()->getOpcode()) {
5844 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5852 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5929 SDNode *AndNode =
N->getOperand(0).getNode();
5937 SDValue CmpInputValue =
N->getOperand(1);
5948 AndInputValue1 = AndInputValue1.
getOperand(0);
5952 if (AndInputValue2 != CmpInputValue)
5985 TruncInputValue1, TruncInputValue2);
5987 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6000 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6003 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6028 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6056 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6089 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6090 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6106 EVT VT =
N->getValueType(0);
6109 if (TrueV == FalseV)
6140 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6141 {LHS, RHS, CC, TrueV, FalseV});
6146template <
unsigned N>
6150 bool IsSigned =
false) {
6154 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6155 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6157 ": argument out of range.");
6163template <
unsigned N>
6167 EVT ResTy =
Node->getValueType(0);
6171 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6172 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6174 ": argument out of range.");
6179 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6185 EVT ResTy =
Node->getValueType(0);
6193 EVT ResTy =
Node->getValueType(0);
6202template <
unsigned N>
6205 EVT ResTy =
Node->getValueType(0);
6210 ": argument out of range.");
6220template <
unsigned N>
6223 EVT ResTy =
Node->getValueType(0);
6228 ": argument out of range.");
6237template <
unsigned N>
6240 EVT ResTy =
Node->getValueType(0);
6245 ": argument out of range.");
6254template <
unsigned W>
6257 unsigned Imm =
N->getConstantOperandVal(2);
6259 const StringRef ErrorMsg =
"argument out of range";
6261 return DAG.
getUNDEF(
N->getValueType(0));
6267 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6275 switch (
N->getConstantOperandVal(0)) {
6278 case Intrinsic::loongarch_lsx_vadd_b:
6279 case Intrinsic::loongarch_lsx_vadd_h:
6280 case Intrinsic::loongarch_lsx_vadd_w:
6281 case Intrinsic::loongarch_lsx_vadd_d:
6282 case Intrinsic::loongarch_lasx_xvadd_b:
6283 case Intrinsic::loongarch_lasx_xvadd_h:
6284 case Intrinsic::loongarch_lasx_xvadd_w:
6285 case Intrinsic::loongarch_lasx_xvadd_d:
6288 case Intrinsic::loongarch_lsx_vaddi_bu:
6289 case Intrinsic::loongarch_lsx_vaddi_hu:
6290 case Intrinsic::loongarch_lsx_vaddi_wu:
6291 case Intrinsic::loongarch_lsx_vaddi_du:
6292 case Intrinsic::loongarch_lasx_xvaddi_bu:
6293 case Intrinsic::loongarch_lasx_xvaddi_hu:
6294 case Intrinsic::loongarch_lasx_xvaddi_wu:
6295 case Intrinsic::loongarch_lasx_xvaddi_du:
6298 case Intrinsic::loongarch_lsx_vsub_b:
6299 case Intrinsic::loongarch_lsx_vsub_h:
6300 case Intrinsic::loongarch_lsx_vsub_w:
6301 case Intrinsic::loongarch_lsx_vsub_d:
6302 case Intrinsic::loongarch_lasx_xvsub_b:
6303 case Intrinsic::loongarch_lasx_xvsub_h:
6304 case Intrinsic::loongarch_lasx_xvsub_w:
6305 case Intrinsic::loongarch_lasx_xvsub_d:
6308 case Intrinsic::loongarch_lsx_vsubi_bu:
6309 case Intrinsic::loongarch_lsx_vsubi_hu:
6310 case Intrinsic::loongarch_lsx_vsubi_wu:
6311 case Intrinsic::loongarch_lsx_vsubi_du:
6312 case Intrinsic::loongarch_lasx_xvsubi_bu:
6313 case Intrinsic::loongarch_lasx_xvsubi_hu:
6314 case Intrinsic::loongarch_lasx_xvsubi_wu:
6315 case Intrinsic::loongarch_lasx_xvsubi_du:
6318 case Intrinsic::loongarch_lsx_vneg_b:
6319 case Intrinsic::loongarch_lsx_vneg_h:
6320 case Intrinsic::loongarch_lsx_vneg_w:
6321 case Intrinsic::loongarch_lsx_vneg_d:
6322 case Intrinsic::loongarch_lasx_xvneg_b:
6323 case Intrinsic::loongarch_lasx_xvneg_h:
6324 case Intrinsic::loongarch_lasx_xvneg_w:
6325 case Intrinsic::loongarch_lasx_xvneg_d:
6329 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6331 SDLoc(
N),
N->getValueType(0)),
6333 case Intrinsic::loongarch_lsx_vmax_b:
6334 case Intrinsic::loongarch_lsx_vmax_h:
6335 case Intrinsic::loongarch_lsx_vmax_w:
6336 case Intrinsic::loongarch_lsx_vmax_d:
6337 case Intrinsic::loongarch_lasx_xvmax_b:
6338 case Intrinsic::loongarch_lasx_xvmax_h:
6339 case Intrinsic::loongarch_lasx_xvmax_w:
6340 case Intrinsic::loongarch_lasx_xvmax_d:
6343 case Intrinsic::loongarch_lsx_vmax_bu:
6344 case Intrinsic::loongarch_lsx_vmax_hu:
6345 case Intrinsic::loongarch_lsx_vmax_wu:
6346 case Intrinsic::loongarch_lsx_vmax_du:
6347 case Intrinsic::loongarch_lasx_xvmax_bu:
6348 case Intrinsic::loongarch_lasx_xvmax_hu:
6349 case Intrinsic::loongarch_lasx_xvmax_wu:
6350 case Intrinsic::loongarch_lasx_xvmax_du:
6353 case Intrinsic::loongarch_lsx_vmaxi_b:
6354 case Intrinsic::loongarch_lsx_vmaxi_h:
6355 case Intrinsic::loongarch_lsx_vmaxi_w:
6356 case Intrinsic::loongarch_lsx_vmaxi_d:
6357 case Intrinsic::loongarch_lasx_xvmaxi_b:
6358 case Intrinsic::loongarch_lasx_xvmaxi_h:
6359 case Intrinsic::loongarch_lasx_xvmaxi_w:
6360 case Intrinsic::loongarch_lasx_xvmaxi_d:
6363 case Intrinsic::loongarch_lsx_vmaxi_bu:
6364 case Intrinsic::loongarch_lsx_vmaxi_hu:
6365 case Intrinsic::loongarch_lsx_vmaxi_wu:
6366 case Intrinsic::loongarch_lsx_vmaxi_du:
6367 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6368 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6369 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6370 case Intrinsic::loongarch_lasx_xvmaxi_du:
6373 case Intrinsic::loongarch_lsx_vmin_b:
6374 case Intrinsic::loongarch_lsx_vmin_h:
6375 case Intrinsic::loongarch_lsx_vmin_w:
6376 case Intrinsic::loongarch_lsx_vmin_d:
6377 case Intrinsic::loongarch_lasx_xvmin_b:
6378 case Intrinsic::loongarch_lasx_xvmin_h:
6379 case Intrinsic::loongarch_lasx_xvmin_w:
6380 case Intrinsic::loongarch_lasx_xvmin_d:
6383 case Intrinsic::loongarch_lsx_vmin_bu:
6384 case Intrinsic::loongarch_lsx_vmin_hu:
6385 case Intrinsic::loongarch_lsx_vmin_wu:
6386 case Intrinsic::loongarch_lsx_vmin_du:
6387 case Intrinsic::loongarch_lasx_xvmin_bu:
6388 case Intrinsic::loongarch_lasx_xvmin_hu:
6389 case Intrinsic::loongarch_lasx_xvmin_wu:
6390 case Intrinsic::loongarch_lasx_xvmin_du:
6393 case Intrinsic::loongarch_lsx_vmini_b:
6394 case Intrinsic::loongarch_lsx_vmini_h:
6395 case Intrinsic::loongarch_lsx_vmini_w:
6396 case Intrinsic::loongarch_lsx_vmini_d:
6397 case Intrinsic::loongarch_lasx_xvmini_b:
6398 case Intrinsic::loongarch_lasx_xvmini_h:
6399 case Intrinsic::loongarch_lasx_xvmini_w:
6400 case Intrinsic::loongarch_lasx_xvmini_d:
6403 case Intrinsic::loongarch_lsx_vmini_bu:
6404 case Intrinsic::loongarch_lsx_vmini_hu:
6405 case Intrinsic::loongarch_lsx_vmini_wu:
6406 case Intrinsic::loongarch_lsx_vmini_du:
6407 case Intrinsic::loongarch_lasx_xvmini_bu:
6408 case Intrinsic::loongarch_lasx_xvmini_hu:
6409 case Intrinsic::loongarch_lasx_xvmini_wu:
6410 case Intrinsic::loongarch_lasx_xvmini_du:
6413 case Intrinsic::loongarch_lsx_vmul_b:
6414 case Intrinsic::loongarch_lsx_vmul_h:
6415 case Intrinsic::loongarch_lsx_vmul_w:
6416 case Intrinsic::loongarch_lsx_vmul_d:
6417 case Intrinsic::loongarch_lasx_xvmul_b:
6418 case Intrinsic::loongarch_lasx_xvmul_h:
6419 case Intrinsic::loongarch_lasx_xvmul_w:
6420 case Intrinsic::loongarch_lasx_xvmul_d:
6423 case Intrinsic::loongarch_lsx_vmadd_b:
6424 case Intrinsic::loongarch_lsx_vmadd_h:
6425 case Intrinsic::loongarch_lsx_vmadd_w:
6426 case Intrinsic::loongarch_lsx_vmadd_d:
6427 case Intrinsic::loongarch_lasx_xvmadd_b:
6428 case Intrinsic::loongarch_lasx_xvmadd_h:
6429 case Intrinsic::loongarch_lasx_xvmadd_w:
6430 case Intrinsic::loongarch_lasx_xvmadd_d: {
6431 EVT ResTy =
N->getValueType(0);
6436 case Intrinsic::loongarch_lsx_vmsub_b:
6437 case Intrinsic::loongarch_lsx_vmsub_h:
6438 case Intrinsic::loongarch_lsx_vmsub_w:
6439 case Intrinsic::loongarch_lsx_vmsub_d:
6440 case Intrinsic::loongarch_lasx_xvmsub_b:
6441 case Intrinsic::loongarch_lasx_xvmsub_h:
6442 case Intrinsic::loongarch_lasx_xvmsub_w:
6443 case Intrinsic::loongarch_lasx_xvmsub_d: {
6444 EVT ResTy =
N->getValueType(0);
6449 case Intrinsic::loongarch_lsx_vdiv_b:
6450 case Intrinsic::loongarch_lsx_vdiv_h:
6451 case Intrinsic::loongarch_lsx_vdiv_w:
6452 case Intrinsic::loongarch_lsx_vdiv_d:
6453 case Intrinsic::loongarch_lasx_xvdiv_b:
6454 case Intrinsic::loongarch_lasx_xvdiv_h:
6455 case Intrinsic::loongarch_lasx_xvdiv_w:
6456 case Intrinsic::loongarch_lasx_xvdiv_d:
6459 case Intrinsic::loongarch_lsx_vdiv_bu:
6460 case Intrinsic::loongarch_lsx_vdiv_hu:
6461 case Intrinsic::loongarch_lsx_vdiv_wu:
6462 case Intrinsic::loongarch_lsx_vdiv_du:
6463 case Intrinsic::loongarch_lasx_xvdiv_bu:
6464 case Intrinsic::loongarch_lasx_xvdiv_hu:
6465 case Intrinsic::loongarch_lasx_xvdiv_wu:
6466 case Intrinsic::loongarch_lasx_xvdiv_du:
6469 case Intrinsic::loongarch_lsx_vmod_b:
6470 case Intrinsic::loongarch_lsx_vmod_h:
6471 case Intrinsic::loongarch_lsx_vmod_w:
6472 case Intrinsic::loongarch_lsx_vmod_d:
6473 case Intrinsic::loongarch_lasx_xvmod_b:
6474 case Intrinsic::loongarch_lasx_xvmod_h:
6475 case Intrinsic::loongarch_lasx_xvmod_w:
6476 case Intrinsic::loongarch_lasx_xvmod_d:
6479 case Intrinsic::loongarch_lsx_vmod_bu:
6480 case Intrinsic::loongarch_lsx_vmod_hu:
6481 case Intrinsic::loongarch_lsx_vmod_wu:
6482 case Intrinsic::loongarch_lsx_vmod_du:
6483 case Intrinsic::loongarch_lasx_xvmod_bu:
6484 case Intrinsic::loongarch_lasx_xvmod_hu:
6485 case Intrinsic::loongarch_lasx_xvmod_wu:
6486 case Intrinsic::loongarch_lasx_xvmod_du:
6489 case Intrinsic::loongarch_lsx_vand_v:
6490 case Intrinsic::loongarch_lasx_xvand_v:
6493 case Intrinsic::loongarch_lsx_vor_v:
6494 case Intrinsic::loongarch_lasx_xvor_v:
6497 case Intrinsic::loongarch_lsx_vxor_v:
6498 case Intrinsic::loongarch_lasx_xvxor_v:
6501 case Intrinsic::loongarch_lsx_vnor_v:
6502 case Intrinsic::loongarch_lasx_xvnor_v: {
6507 case Intrinsic::loongarch_lsx_vandi_b:
6508 case Intrinsic::loongarch_lasx_xvandi_b:
6511 case Intrinsic::loongarch_lsx_vori_b:
6512 case Intrinsic::loongarch_lasx_xvori_b:
6515 case Intrinsic::loongarch_lsx_vxori_b:
6516 case Intrinsic::loongarch_lasx_xvxori_b:
6519 case Intrinsic::loongarch_lsx_vsll_b:
6520 case Intrinsic::loongarch_lsx_vsll_h:
6521 case Intrinsic::loongarch_lsx_vsll_w:
6522 case Intrinsic::loongarch_lsx_vsll_d:
6523 case Intrinsic::loongarch_lasx_xvsll_b:
6524 case Intrinsic::loongarch_lasx_xvsll_h:
6525 case Intrinsic::loongarch_lasx_xvsll_w:
6526 case Intrinsic::loongarch_lasx_xvsll_d:
6529 case Intrinsic::loongarch_lsx_vslli_b:
6530 case Intrinsic::loongarch_lasx_xvslli_b:
6533 case Intrinsic::loongarch_lsx_vslli_h:
6534 case Intrinsic::loongarch_lasx_xvslli_h:
6537 case Intrinsic::loongarch_lsx_vslli_w:
6538 case Intrinsic::loongarch_lasx_xvslli_w:
6541 case Intrinsic::loongarch_lsx_vslli_d:
6542 case Intrinsic::loongarch_lasx_xvslli_d:
6545 case Intrinsic::loongarch_lsx_vsrl_b:
6546 case Intrinsic::loongarch_lsx_vsrl_h:
6547 case Intrinsic::loongarch_lsx_vsrl_w:
6548 case Intrinsic::loongarch_lsx_vsrl_d:
6549 case Intrinsic::loongarch_lasx_xvsrl_b:
6550 case Intrinsic::loongarch_lasx_xvsrl_h:
6551 case Intrinsic::loongarch_lasx_xvsrl_w:
6552 case Intrinsic::loongarch_lasx_xvsrl_d:
6555 case Intrinsic::loongarch_lsx_vsrli_b:
6556 case Intrinsic::loongarch_lasx_xvsrli_b:
6559 case Intrinsic::loongarch_lsx_vsrli_h:
6560 case Intrinsic::loongarch_lasx_xvsrli_h:
6563 case Intrinsic::loongarch_lsx_vsrli_w:
6564 case Intrinsic::loongarch_lasx_xvsrli_w:
6567 case Intrinsic::loongarch_lsx_vsrli_d:
6568 case Intrinsic::loongarch_lasx_xvsrli_d:
6571 case Intrinsic::loongarch_lsx_vsra_b:
6572 case Intrinsic::loongarch_lsx_vsra_h:
6573 case Intrinsic::loongarch_lsx_vsra_w:
6574 case Intrinsic::loongarch_lsx_vsra_d:
6575 case Intrinsic::loongarch_lasx_xvsra_b:
6576 case Intrinsic::loongarch_lasx_xvsra_h:
6577 case Intrinsic::loongarch_lasx_xvsra_w:
6578 case Intrinsic::loongarch_lasx_xvsra_d:
6581 case Intrinsic::loongarch_lsx_vsrai_b:
6582 case Intrinsic::loongarch_lasx_xvsrai_b:
6585 case Intrinsic::loongarch_lsx_vsrai_h:
6586 case Intrinsic::loongarch_lasx_xvsrai_h:
6589 case Intrinsic::loongarch_lsx_vsrai_w:
6590 case Intrinsic::loongarch_lasx_xvsrai_w:
6593 case Intrinsic::loongarch_lsx_vsrai_d:
6594 case Intrinsic::loongarch_lasx_xvsrai_d:
6597 case Intrinsic::loongarch_lsx_vclz_b:
6598 case Intrinsic::loongarch_lsx_vclz_h:
6599 case Intrinsic::loongarch_lsx_vclz_w:
6600 case Intrinsic::loongarch_lsx_vclz_d:
6601 case Intrinsic::loongarch_lasx_xvclz_b:
6602 case Intrinsic::loongarch_lasx_xvclz_h:
6603 case Intrinsic::loongarch_lasx_xvclz_w:
6604 case Intrinsic::loongarch_lasx_xvclz_d:
6606 case Intrinsic::loongarch_lsx_vpcnt_b:
6607 case Intrinsic::loongarch_lsx_vpcnt_h:
6608 case Intrinsic::loongarch_lsx_vpcnt_w:
6609 case Intrinsic::loongarch_lsx_vpcnt_d:
6610 case Intrinsic::loongarch_lasx_xvpcnt_b:
6611 case Intrinsic::loongarch_lasx_xvpcnt_h:
6612 case Intrinsic::loongarch_lasx_xvpcnt_w:
6613 case Intrinsic::loongarch_lasx_xvpcnt_d:
6615 case Intrinsic::loongarch_lsx_vbitclr_b:
6616 case Intrinsic::loongarch_lsx_vbitclr_h:
6617 case Intrinsic::loongarch_lsx_vbitclr_w:
6618 case Intrinsic::loongarch_lsx_vbitclr_d:
6619 case Intrinsic::loongarch_lasx_xvbitclr_b:
6620 case Intrinsic::loongarch_lasx_xvbitclr_h:
6621 case Intrinsic::loongarch_lasx_xvbitclr_w:
6622 case Intrinsic::loongarch_lasx_xvbitclr_d:
6624 case Intrinsic::loongarch_lsx_vbitclri_b:
6625 case Intrinsic::loongarch_lasx_xvbitclri_b:
6627 case Intrinsic::loongarch_lsx_vbitclri_h:
6628 case Intrinsic::loongarch_lasx_xvbitclri_h:
6630 case Intrinsic::loongarch_lsx_vbitclri_w:
6631 case Intrinsic::loongarch_lasx_xvbitclri_w:
6633 case Intrinsic::loongarch_lsx_vbitclri_d:
6634 case Intrinsic::loongarch_lasx_xvbitclri_d:
6636 case Intrinsic::loongarch_lsx_vbitset_b:
6637 case Intrinsic::loongarch_lsx_vbitset_h:
6638 case Intrinsic::loongarch_lsx_vbitset_w:
6639 case Intrinsic::loongarch_lsx_vbitset_d:
6640 case Intrinsic::loongarch_lasx_xvbitset_b:
6641 case Intrinsic::loongarch_lasx_xvbitset_h:
6642 case Intrinsic::loongarch_lasx_xvbitset_w:
6643 case Intrinsic::loongarch_lasx_xvbitset_d: {
6644 EVT VecTy =
N->getValueType(0);
6650 case Intrinsic::loongarch_lsx_vbitseti_b:
6651 case Intrinsic::loongarch_lasx_xvbitseti_b:
6653 case Intrinsic::loongarch_lsx_vbitseti_h:
6654 case Intrinsic::loongarch_lasx_xvbitseti_h:
6656 case Intrinsic::loongarch_lsx_vbitseti_w:
6657 case Intrinsic::loongarch_lasx_xvbitseti_w:
6659 case Intrinsic::loongarch_lsx_vbitseti_d:
6660 case Intrinsic::loongarch_lasx_xvbitseti_d:
6662 case Intrinsic::loongarch_lsx_vbitrev_b:
6663 case Intrinsic::loongarch_lsx_vbitrev_h:
6664 case Intrinsic::loongarch_lsx_vbitrev_w:
6665 case Intrinsic::loongarch_lsx_vbitrev_d:
6666 case Intrinsic::loongarch_lasx_xvbitrev_b:
6667 case Intrinsic::loongarch_lasx_xvbitrev_h:
6668 case Intrinsic::loongarch_lasx_xvbitrev_w:
6669 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6670 EVT VecTy =
N->getValueType(0);
6676 case Intrinsic::loongarch_lsx_vbitrevi_b:
6677 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6679 case Intrinsic::loongarch_lsx_vbitrevi_h:
6680 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6682 case Intrinsic::loongarch_lsx_vbitrevi_w:
6683 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6685 case Intrinsic::loongarch_lsx_vbitrevi_d:
6686 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6688 case Intrinsic::loongarch_lsx_vfadd_s:
6689 case Intrinsic::loongarch_lsx_vfadd_d:
6690 case Intrinsic::loongarch_lasx_xvfadd_s:
6691 case Intrinsic::loongarch_lasx_xvfadd_d:
6694 case Intrinsic::loongarch_lsx_vfsub_s:
6695 case Intrinsic::loongarch_lsx_vfsub_d:
6696 case Intrinsic::loongarch_lasx_xvfsub_s:
6697 case Intrinsic::loongarch_lasx_xvfsub_d:
6700 case Intrinsic::loongarch_lsx_vfmul_s:
6701 case Intrinsic::loongarch_lsx_vfmul_d:
6702 case Intrinsic::loongarch_lasx_xvfmul_s:
6703 case Intrinsic::loongarch_lasx_xvfmul_d:
6706 case Intrinsic::loongarch_lsx_vfdiv_s:
6707 case Intrinsic::loongarch_lsx_vfdiv_d:
6708 case Intrinsic::loongarch_lasx_xvfdiv_s:
6709 case Intrinsic::loongarch_lasx_xvfdiv_d:
6712 case Intrinsic::loongarch_lsx_vfmadd_s:
6713 case Intrinsic::loongarch_lsx_vfmadd_d:
6714 case Intrinsic::loongarch_lasx_xvfmadd_s:
6715 case Intrinsic::loongarch_lasx_xvfmadd_d:
6717 N->getOperand(2),
N->getOperand(3));
6718 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6720 N->getOperand(1),
N->getOperand(2),
6722 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6723 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6725 N->getOperand(1),
N->getOperand(2),
6727 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6728 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6730 N->getOperand(1),
N->getOperand(2),
6732 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6734 N->getOperand(1),
N->getOperand(2),
6736 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6737 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6738 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6739 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6740 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6741 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6742 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6743 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6744 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
6747 case Intrinsic::loongarch_lsx_vreplve_b:
6748 case Intrinsic::loongarch_lsx_vreplve_h:
6749 case Intrinsic::loongarch_lsx_vreplve_w:
6750 case Intrinsic::loongarch_lsx_vreplve_d:
6751 case Intrinsic::loongarch_lasx_xvreplve_b:
6752 case Intrinsic::loongarch_lasx_xvreplve_h:
6753 case Intrinsic::loongarch_lasx_xvreplve_w:
6754 case Intrinsic::loongarch_lasx_xvreplve_d:
6755 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
6759 case Intrinsic::loongarch_lsx_vpickve2gr_b:
6763 case Intrinsic::loongarch_lsx_vpickve2gr_h:
6764 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
6768 case Intrinsic::loongarch_lsx_vpickve2gr_w:
6772 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
6776 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
6777 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
6781 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
6785 case Intrinsic::loongarch_lsx_bz_b:
6786 case Intrinsic::loongarch_lsx_bz_h:
6787 case Intrinsic::loongarch_lsx_bz_w:
6788 case Intrinsic::loongarch_lsx_bz_d:
6789 case Intrinsic::loongarch_lasx_xbz_b:
6790 case Intrinsic::loongarch_lasx_xbz_h:
6791 case Intrinsic::loongarch_lasx_xbz_w:
6792 case Intrinsic::loongarch_lasx_xbz_d:
6794 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
6797 case Intrinsic::loongarch_lsx_bz_v:
6798 case Intrinsic::loongarch_lasx_xbz_v:
6800 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
6803 case Intrinsic::loongarch_lsx_bnz_b:
6804 case Intrinsic::loongarch_lsx_bnz_h:
6805 case Intrinsic::loongarch_lsx_bnz_w:
6806 case Intrinsic::loongarch_lsx_bnz_d:
6807 case Intrinsic::loongarch_lasx_xbnz_b:
6808 case Intrinsic::loongarch_lasx_xbnz_h:
6809 case Intrinsic::loongarch_lasx_xbnz_w:
6810 case Intrinsic::loongarch_lasx_xbnz_d:
6812 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
6815 case Intrinsic::loongarch_lsx_bnz_v:
6816 case Intrinsic::loongarch_lasx_xbnz_v:
6818 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
6821 case Intrinsic::loongarch_lasx_concat_128_s:
6822 case Intrinsic::loongarch_lasx_concat_128_d:
6823 case Intrinsic::loongarch_lasx_concat_128:
6825 N->getOperand(1),
N->getOperand(2));
6837 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
6849 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
6851 "Unexpected value type!");
6860 MVT VT =
N->getSimpleValueType(0);
6881 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
6894 APInt V =
C->getValueAPF().bitcastToAPInt();
6910 MVT EltVT =
N->getSimpleValueType(0);
6945 MVT VT =
N->getSimpleValueType(0);
7005 switch (
N->getOpcode()) {
7018 case LoongArchISD::BITREV_W:
7020 case LoongArchISD::BR_CC:
7022 case LoongArchISD::SELECT_CC:
7026 case LoongArchISD::MOVGR2FR_W_LA64:
7028 case LoongArchISD::MOVFR2GR_S_LA64:
7030 case LoongArchISD::VMSKLTZ:
7031 case LoongArchISD::XVMSKLTZ:
7033 case LoongArchISD::SPLIT_PAIR_F64:
7037 case LoongArchISD::VANDN:
7061 MF->
insert(It, BreakMBB);
7065 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
7066 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
7078 MBB->addSuccessor(BreakMBB);
7079 MBB->addSuccessor(SinkMBB);
7085 BreakMBB->addSuccessor(SinkMBB);
7097 switch (
MI.getOpcode()) {
7100 case LoongArch::PseudoVBZ:
7101 CondOpc = LoongArch::VSETEQZ_V;
7103 case LoongArch::PseudoVBZ_B:
7104 CondOpc = LoongArch::VSETANYEQZ_B;
7106 case LoongArch::PseudoVBZ_H:
7107 CondOpc = LoongArch::VSETANYEQZ_H;
7109 case LoongArch::PseudoVBZ_W:
7110 CondOpc = LoongArch::VSETANYEQZ_W;
7112 case LoongArch::PseudoVBZ_D:
7113 CondOpc = LoongArch::VSETANYEQZ_D;
7115 case LoongArch::PseudoVBNZ:
7116 CondOpc = LoongArch::VSETNEZ_V;
7118 case LoongArch::PseudoVBNZ_B:
7119 CondOpc = LoongArch::VSETALLNEZ_B;
7121 case LoongArch::PseudoVBNZ_H:
7122 CondOpc = LoongArch::VSETALLNEZ_H;
7124 case LoongArch::PseudoVBNZ_W:
7125 CondOpc = LoongArch::VSETALLNEZ_W;
7127 case LoongArch::PseudoVBNZ_D:
7128 CondOpc = LoongArch::VSETALLNEZ_D;
7130 case LoongArch::PseudoXVBZ:
7131 CondOpc = LoongArch::XVSETEQZ_V;
7133 case LoongArch::PseudoXVBZ_B:
7134 CondOpc = LoongArch::XVSETANYEQZ_B;
7136 case LoongArch::PseudoXVBZ_H:
7137 CondOpc = LoongArch::XVSETANYEQZ_H;
7139 case LoongArch::PseudoXVBZ_W:
7140 CondOpc = LoongArch::XVSETANYEQZ_W;
7142 case LoongArch::PseudoXVBZ_D:
7143 CondOpc = LoongArch::XVSETANYEQZ_D;
7145 case LoongArch::PseudoXVBNZ:
7146 CondOpc = LoongArch::XVSETNEZ_V;
7148 case LoongArch::PseudoXVBNZ_B:
7149 CondOpc = LoongArch::XVSETALLNEZ_B;
7151 case LoongArch::PseudoXVBNZ_H:
7152 CondOpc = LoongArch::XVSETALLNEZ_H;
7154 case LoongArch::PseudoXVBNZ_W:
7155 CondOpc = LoongArch::XVSETALLNEZ_W;
7157 case LoongArch::PseudoXVBNZ_D:
7158 CondOpc = LoongArch::XVSETALLNEZ_D;
7173 F->insert(It, FalseBB);
7174 F->insert(It, TrueBB);
7175 F->insert(It, SinkBB);
7178 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
7182 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
7191 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7199 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7207 MI.getOperand(0).getReg())
7214 MI.eraseFromParent();
7222 unsigned BroadcastOp;
7224 switch (
MI.getOpcode()) {
7227 case LoongArch::PseudoXVINSGR2VR_B:
7229 BroadcastOp = LoongArch::XVREPLGR2VR_B;
7230 InsOp = LoongArch::XVEXTRINS_B;
7232 case LoongArch::PseudoXVINSGR2VR_H:
7234 BroadcastOp = LoongArch::XVREPLGR2VR_H;
7235 InsOp = LoongArch::XVEXTRINS_H;
7247 unsigned Idx =
MI.getOperand(3).getImm();
7249 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
7251 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
7252 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
7255 .
addReg(XSrc, 0, LoongArch::sub_128);
7257 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
7258 : LoongArch::VINSGR2VR_B),
7267 .
addImm(LoongArch::sub_128);
7269 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7270 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7274 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
7277 .
addImm(Idx >= HalfSize ? 48 : 18);
7282 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
7285 MI.eraseFromParent();
7292 assert(Subtarget.hasExtLSX());
7299 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7300 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7301 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
7305 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
7306 : LoongArch::VINSGR2VR_W),
7313 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
7317 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
7318 : LoongArch::VPICKVE2GR_W),
7323 MI.eraseFromParent();
7337 unsigned EleBits = 8;
7338 unsigned NotOpc = 0;
7341 switch (
MI.getOpcode()) {
7344 case LoongArch::PseudoVMSKLTZ_B:
7345 MskOpc = LoongArch::VMSKLTZ_B;
7347 case LoongArch::PseudoVMSKLTZ_H:
7348 MskOpc = LoongArch::VMSKLTZ_H;
7351 case LoongArch::PseudoVMSKLTZ_W:
7352 MskOpc = LoongArch::VMSKLTZ_W;
7355 case LoongArch::PseudoVMSKLTZ_D:
7356 MskOpc = LoongArch::VMSKLTZ_D;
7359 case LoongArch::PseudoVMSKGEZ_B:
7360 MskOpc = LoongArch::VMSKGEZ_B;
7362 case LoongArch::PseudoVMSKEQZ_B:
7363 MskOpc = LoongArch::VMSKNZ_B;
7364 NotOpc = LoongArch::VNOR_V;
7366 case LoongArch::PseudoVMSKNEZ_B:
7367 MskOpc = LoongArch::VMSKNZ_B;
7369 case LoongArch::PseudoXVMSKLTZ_B:
7370 MskOpc = LoongArch::XVMSKLTZ_B;
7371 RC = &LoongArch::LASX256RegClass;
7373 case LoongArch::PseudoXVMSKLTZ_H:
7374 MskOpc = LoongArch::XVMSKLTZ_H;
7375 RC = &LoongArch::LASX256RegClass;
7378 case LoongArch::PseudoXVMSKLTZ_W:
7379 MskOpc = LoongArch::XVMSKLTZ_W;
7380 RC = &LoongArch::LASX256RegClass;
7383 case LoongArch::PseudoXVMSKLTZ_D:
7384 MskOpc = LoongArch::XVMSKLTZ_D;
7385 RC = &LoongArch::LASX256RegClass;
7388 case LoongArch::PseudoXVMSKGEZ_B:
7389 MskOpc = LoongArch::XVMSKGEZ_B;
7390 RC = &LoongArch::LASX256RegClass;
7392 case LoongArch::PseudoXVMSKEQZ_B:
7393 MskOpc = LoongArch::XVMSKNZ_B;
7394 NotOpc = LoongArch::XVNOR_V;
7395 RC = &LoongArch::LASX256RegClass;
7397 case LoongArch::PseudoXVMSKNEZ_B:
7398 MskOpc = LoongArch::XVMSKNZ_B;
7399 RC = &LoongArch::LASX256RegClass;
7414 if (
TRI->getRegSizeInBits(*RC) > 128) {
7415 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7416 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7424 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
7425 : LoongArch::BSTRINS_W),
7429 .
addImm(256 / EleBits - 1)
7437 MI.eraseFromParent();
7444 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
7445 "Unexpected instruction");
7457 MI.eraseFromParent();
7464 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
7465 "Unexpected instruction");
7471 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
7481 MI.eraseFromParent();
7486 switch (
MI.getOpcode()) {
7489 case LoongArch::Select_GPR_Using_CC_GPR:
7525 if (
MI.getOperand(2).isReg())
7526 RHS =
MI.getOperand(2).getReg();
7527 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
7531 SelectDests.
insert(
MI.getOperand(0).getReg());
7535 SequenceMBBI !=
E; ++SequenceMBBI) {
7536 if (SequenceMBBI->isDebugInstr())
7539 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
7540 !SequenceMBBI->getOperand(2).isReg() ||
7541 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
7542 SequenceMBBI->getOperand(3).getImm() != CC ||
7543 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
7544 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
7546 LastSelectPseudo = &*SequenceMBBI;
7548 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
7551 if (SequenceMBBI->hasUnmodeledSideEffects() ||
7552 SequenceMBBI->mayLoadOrStore() ||
7553 SequenceMBBI->usesCustomInsertionHook())
7556 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
7571 F->insert(
I, IfFalseMBB);
7572 F->insert(
I, TailMBB);
7575 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
7581 TailMBB->
push_back(DebugInstr->removeFromParent());
7585 TailMBB->
splice(TailMBB->
end(), HeadMBB,
7595 if (
MI.getOperand(2).isImm())
7607 auto SelectMBBI =
MI.getIterator();
7608 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7610 while (SelectMBBI != SelectEnd) {
7611 auto Next = std::next(SelectMBBI);
7615 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7616 .
addReg(SelectMBBI->getOperand(4).getReg())
7618 .
addReg(SelectMBBI->getOperand(5).getReg())
7625 F->getProperties().resetNoPHIs();
7631 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7634 switch (
MI.getOpcode()) {
7637 case LoongArch::DIV_W:
7638 case LoongArch::DIV_WU:
7639 case LoongArch::MOD_W:
7640 case LoongArch::MOD_WU:
7641 case LoongArch::DIV_D:
7642 case LoongArch::DIV_DU:
7643 case LoongArch::MOD_D:
7644 case LoongArch::MOD_DU:
7647 case LoongArch::WRFCSR: {
7649 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7650 .
addReg(
MI.getOperand(1).getReg());
7651 MI.eraseFromParent();
7654 case LoongArch::RDFCSR: {
7655 MachineInstr *ReadFCSR =
7657 MI.getOperand(0).getReg())
7658 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
7660 MI.eraseFromParent();
7663 case LoongArch::Select_GPR_Using_CC_GPR:
7665 case LoongArch::BuildPairF64Pseudo:
7667 case LoongArch::SplitPairF64Pseudo:
7669 case LoongArch::PseudoVBZ:
7670 case LoongArch::PseudoVBZ_B:
7671 case LoongArch::PseudoVBZ_H:
7672 case LoongArch::PseudoVBZ_W:
7673 case LoongArch::PseudoVBZ_D:
7674 case LoongArch::PseudoVBNZ:
7675 case LoongArch::PseudoVBNZ_B:
7676 case LoongArch::PseudoVBNZ_H:
7677 case LoongArch::PseudoVBNZ_W:
7678 case LoongArch::PseudoVBNZ_D:
7679 case LoongArch::PseudoXVBZ:
7680 case LoongArch::PseudoXVBZ_B:
7681 case LoongArch::PseudoXVBZ_H:
7682 case LoongArch::PseudoXVBZ_W:
7683 case LoongArch::PseudoXVBZ_D:
7684 case LoongArch::PseudoXVBNZ:
7685 case LoongArch::PseudoXVBNZ_B:
7686 case LoongArch::PseudoXVBNZ_H:
7687 case LoongArch::PseudoXVBNZ_W:
7688 case LoongArch::PseudoXVBNZ_D:
7690 case LoongArch::PseudoXVINSGR2VR_B:
7691 case LoongArch::PseudoXVINSGR2VR_H:
7693 case LoongArch::PseudoCTPOP:
7695 case LoongArch::PseudoVMSKLTZ_B:
7696 case LoongArch::PseudoVMSKLTZ_H:
7697 case LoongArch::PseudoVMSKLTZ_W:
7698 case LoongArch::PseudoVMSKLTZ_D:
7699 case LoongArch::PseudoVMSKGEZ_B:
7700 case LoongArch::PseudoVMSKEQZ_B:
7701 case LoongArch::PseudoVMSKNEZ_B:
7702 case LoongArch::PseudoXVMSKLTZ_B:
7703 case LoongArch::PseudoXVMSKLTZ_H:
7704 case LoongArch::PseudoXVMSKLTZ_W:
7705 case LoongArch::PseudoXVMSKLTZ_D:
7706 case LoongArch::PseudoXVMSKGEZ_B:
7707 case LoongArch::PseudoXVMSKEQZ_B:
7708 case LoongArch::PseudoXVMSKNEZ_B:
7710 case TargetOpcode::STATEPOINT:
7716 MI.addOperand(*
MI.getMF(),
7718 LoongArch::R1,
true,
7721 if (!Subtarget.is64Bit())
7729 unsigned *
Fast)
const {
7730 if (!Subtarget.hasUAL())
7748 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7749 LoongArch::R10, LoongArch::R11};
7753 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7754 LoongArch::F6, LoongArch::F7};
7757 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7758 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7761 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7762 LoongArch::VR6, LoongArch::VR7};
7765 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7766 LoongArch::XR6, LoongArch::XR7};
7772 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7774 unsigned GRLenInBytes = GRLen / 8;
7785 State.AllocateStack(GRLenInBytes, StackAlign),
7788 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7799 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7807 unsigned ValNo,
MVT ValVT,
7810 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7811 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7812 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7817 if (IsRet && ValNo > 1)
7821 bool UseGPRForFloat =
true;
7831 UseGPRForFloat = ArgFlags.
isVarArg();
7844 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7847 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7848 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
7850 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7856 State.getPendingArgFlags();
7859 "PendingLocs and PendingArgFlags out of sync");
7863 UseGPRForFloat =
true;
7865 if (UseGPRForFloat && ValVT == MVT::f32) {
7868 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7871 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7874 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7916 PendingLocs.
size() <= 2) {
7917 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7922 PendingLocs.
clear();
7923 PendingArgFlags.
clear();
7930 unsigned StoreSizeBytes = GRLen / 8;
7933 if (ValVT == MVT::f32 && !UseGPRForFloat) {
7935 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
7939 UseGPRForFloat =
false;
7940 StoreSizeBytes = 16;
7941 StackAlign =
Align(16);
7944 UseGPRForFloat =
false;
7945 StoreSizeBytes = 32;
7946 StackAlign =
Align(32);
7952 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
7956 if (!PendingLocs.
empty()) {
7958 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7959 for (
auto &It : PendingLocs) {
7961 It.convertToReg(
Reg);
7966 PendingLocs.clear();
7967 PendingArgFlags.
clear();
7970 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7971 "Expected an GRLenVT at this stage");
7988void LoongArchTargetLowering::analyzeInputArgs(
7991 LoongArchCCAssignFn Fn)
const {
7993 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
7994 MVT ArgVT = Ins[i].VT;
7995 Type *ArgTy =
nullptr;
7997 ArgTy = FType->getReturnType();
7998 else if (Ins[i].isOrigArg())
7999 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
8003 CCInfo, IsRet, ArgTy)) {
8004 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
8011void LoongArchTargetLowering::analyzeOutputArgs(
8014 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
8015 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8016 MVT ArgVT = Outs[i].VT;
8017 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
8021 CCInfo, IsRet, OrigTy)) {
8022 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
8041 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
8063 if (In.isOrigArg()) {
8068 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
8069 (
BitWidth < 32 && In.Flags.isZExt())) {
8119 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8132 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8136 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
8150 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
8152 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
8162 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8166 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8167 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8168 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8175 if (LocVT == MVT::f32) {
8178 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
8179 LoongArch::F26, LoongArch::F27};
8186 if (LocVT == MVT::f64) {
8189 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
8190 LoongArch::F30_64, LoongArch::F31_64};
8220 "GHC calling convention requires the F and D extensions");
8224 MVT GRLenVT = Subtarget.getGRLenVT();
8225 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
8227 std::vector<SDValue> OutChains;
8236 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
8238 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
8255 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
8256 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
8257 assert(ArgPartOffset == 0);
8258 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
8260 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
8284 int VaArgOffset, VarArgsSaveSize;
8288 if (ArgRegs.
size() == Idx) {
8290 VarArgsSaveSize = 0;
8292 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
8293 VaArgOffset = -VarArgsSaveSize;
8299 LoongArchFI->setVarArgsFrameIndex(FI);
8307 VarArgsSaveSize += GRLenInBytes;
8312 for (
unsigned I = Idx;
I < ArgRegs.
size();
8313 ++
I, VaArgOffset += GRLenInBytes) {
8314 const Register Reg = RegInfo.createVirtualRegister(RC);
8315 RegInfo.addLiveIn(ArgRegs[
I], Reg);
8323 ->setValue((
Value *)
nullptr);
8324 OutChains.push_back(Store);
8326 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
8331 if (!OutChains.empty()) {
8332 OutChains.push_back(Chain);
8347 if (
N->getNumValues() != 1)
8349 if (!
N->hasNUsesOfValue(1, 0))
8352 SDNode *Copy = *
N->user_begin();
8358 if (Copy->getGluedNode())
8362 bool HasRet =
false;
8364 if (
Node->getOpcode() != LoongArchISD::RET)
8372 Chain = Copy->getOperand(0);
8377bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
8381 auto CalleeCC = CLI.CallConv;
8382 auto &Outs = CLI.Outs;
8384 auto CallerCC = Caller.getCallingConv();
8391 for (
auto &VA : ArgLocs)
8397 auto IsCallerStructRet = Caller.hasStructRetAttr();
8398 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
8399 if (IsCallerStructRet || IsCalleeStructRet)
8403 for (
auto &Arg : Outs)
8404 if (Arg.Flags.isByVal())
8409 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
8410 if (CalleeCC != CallerCC) {
8411 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
8412 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
8438 MVT GRLenVT = Subtarget.getGRLenVT();
8450 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
8454 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
8460 "site marked musttail");
8467 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8469 if (!Flags.isByVal())
8473 unsigned Size = Flags.getByValSize();
8474 Align Alignment = Flags.getNonZeroByValAlign();
8481 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
8483 false,
nullptr, std::nullopt,
8495 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8498 SDValue ArgValue = OutVals[OutIdx];
8506 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
8507 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8519 if (!StackPtr.getNode())
8531 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8546 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8547 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8548 assert(ArgPartOffset == 0);
8553 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8554 SDValue PartValue = OutVals[OutIdx + 1];
8555 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8570 for (
const auto &Part : Parts) {
8571 SDValue PartValue = Part.first;
8572 SDValue PartOffset = Part.second;
8579 ArgValue = SpillSlot;
8585 if (Flags.isByVal())
8586 ArgValue = ByValArgs[j++];
8593 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8594 "for passing parameters");
8597 if (!StackPtr.getNode())
8610 if (!MemOpChains.
empty())
8616 for (
auto &Reg : RegsToPass) {
8617 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8639 Ops.push_back(Chain);
8640 Ops.push_back(Callee);
8644 for (
auto &Reg : RegsToPass)
8645 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8650 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8651 assert(Mask &&
"Missing call preserved mask for calling convention");
8657 Ops.push_back(Glue);
8666 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
8669 assert(Subtarget.is64Bit() &&
"Medium code model requires LA64");
8670 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
8673 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8674 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
8696 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8699 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8700 auto &VA = RVLocs[i];
8708 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8709 assert(VA.needsCustom());
8714 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
8715 RetValue, RetValue2);
8728 const Type *RetTy)
const {
8730 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8732 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8736 Outs[i].Flags, CCInfo,
true,
nullptr))
8762 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8763 SDValue Val = OutVals[OutIdx];
8772 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8776 Register RegHi = RVLocs[++i].getLocReg();
8801 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
8809 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
8812 if (SplatBitSize == 16 && !(V & 0x00FF)) {
8814 RequiredImm = (0b10101 << 8) | (V >> 8);
8815 return {
true, RequiredImm};
8816 }
else if (SplatBitSize == 32) {
8818 if (!(V & 0xFFFF00FF)) {
8819 RequiredImm = (0b10001 << 8) | (V >> 8);
8820 return {
true, RequiredImm};
8823 if (!(V & 0xFF00FFFF)) {
8824 RequiredImm = (0b10010 << 8) | (V >> 16);
8825 return {
true, RequiredImm};
8828 if (!(V & 0x00FFFFFF)) {
8829 RequiredImm = (0b10011 << 8) | (V >> 24);
8830 return {
true, RequiredImm};
8833 if ((V & 0xFFFF00FF) == 0xFF) {
8834 RequiredImm = (0b10110 << 8) | (V >> 8);
8835 return {
true, RequiredImm};
8838 if ((V & 0xFF00FFFF) == 0xFFFF) {
8839 RequiredImm = (0b10111 << 8) | (V >> 16);
8840 return {
true, RequiredImm};
8843 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
8845 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8846 return {
true, RequiredImm};
8848 }
else if (SplatBitSize == 64) {
8850 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
8851 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
8853 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8854 return {
true, RequiredImm};
8857 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
8858 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
8860 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
8861 return {
true, RequiredImm};
8864 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
8866 for (
int i = 0; i < 8; ++i) {
8868 if (
byte == 0 ||
byte == 0xFF)
8869 res |= ((
byte & 1) << i);
8876 auto [IsSame, Suffix] = sameBitsPreByte(V);
8878 RequiredImm = (0b11001 << 8) | Suffix;
8879 return {
true, RequiredImm};
8882 return {
false, RequiredImm};
8887 if (!Subtarget.hasExtLSX())
8890 if (VT == MVT::f32) {
8891 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8892 return (masked == 0x3e000000 || masked == 0x40000000);
8895 if (VT == MVT::f64) {
8896 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8897 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8903bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8904 bool ForCodeSize)
const {
8906 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8908 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8910 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8921bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8931 Type *Ty =
I->getOperand(0)->getType();
8933 unsigned Size = Ty->getIntegerBitWidth();
8949 EVT VT =
Y.getValueType();
8952 return Subtarget.hasExtLSX() && VT.
isInteger();
8964 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8965 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8966 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8967 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8969 Info.memVT = MVT::i32;
8970 Info.ptrVal =
I.getArgOperand(0);
8972 Info.align =
Align(4);
8989 "Unable to expand");
8990 unsigned MinWordSize = 4;
9002 Value *AlignedAddr = Builder.CreateIntrinsic(
9003 Intrinsic::ptrmask, {PtrTy, IntTy},
9004 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
9007 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
9008 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
9009 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
9010 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
9011 Value *Mask = Builder.CreateShl(
9012 ConstantInt::get(WordType,
9015 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
9016 Value *ValOperand_Shifted =
9017 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
9018 ShiftAmt,
"ValOperand_Shifted");
9021 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
9023 NewOperand = ValOperand_Shifted;
9026 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
9029 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
9030 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
9049 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
9057 if (Subtarget.hasLAMCAS()) {
9079 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
9081 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
9083 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
9085 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
9087 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
9089 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
9091 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
9093 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
9103 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
9105 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
9107 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
9109 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
9111 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
9113 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
9115 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
9117 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
9129 if (Subtarget.hasLAMCAS())
9141 unsigned GRLen = Subtarget.getGRLen();
9143 Value *FailureOrdering =
9144 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9145 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9147 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9148 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9149 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9150 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9153 Value *Result = Builder.CreateIntrinsic(
9154 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
9156 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9172 Builder.CreateNot(Mask,
"Inv_Mask"),
9179 unsigned GRLen = Subtarget.getGRLen();
9188 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
9189 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9190 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
9206 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
9207 Result = Builder.CreateCall(LlwOpScwLoop,
9208 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
9211 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
9215 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9238 const Constant *PersonalityFn)
const {
9239 return LoongArch::R4;
9243 const Constant *PersonalityFn)
const {
9244 return LoongArch::R5;
9255 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
9256 return RefinementSteps;
9261 int &RefinementSteps,
9262 bool &UseOneConstNR,
9263 bool Reciprocal)
const {
9264 if (Subtarget.hasFrecipe()) {
9268 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9269 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9270 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9271 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9272 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9291 int &RefinementSteps)
const {
9292 if (Subtarget.hasFrecipe()) {
9296 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9297 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9298 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9299 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9300 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9305 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
9317LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
9337 if (Constraint.
size() == 1) {
9338 switch (Constraint[0]) {
9354 if (Constraint ==
"ZC" || Constraint ==
"ZB")
9363 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
9370std::pair<unsigned, const TargetRegisterClass *>
9371LoongArchTargetLowering::getRegForInlineAsmConstraint(
9375 if (Constraint.
size() == 1) {
9376 switch (Constraint[0]) {
9381 return std::make_pair(0U, &LoongArch::GPRRegClass);
9383 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
9385 if (Subtarget.hasBasicF() && VT == MVT::f32)
9386 return std::make_pair(0U, &LoongArch::FPR32RegClass);
9387 if (Subtarget.hasBasicD() && VT == MVT::f64)
9388 return std::make_pair(0U, &LoongArch::FPR64RegClass);
9389 if (Subtarget.hasExtLSX() &&
9390 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
9391 return std::make_pair(0U, &LoongArch::LSX128RegClass);
9392 if (Subtarget.hasExtLASX() &&
9393 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
9394 return std::make_pair(0U, &LoongArch::LASX256RegClass);
9414 bool IsFP = Constraint[2] ==
'f';
9415 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
9416 std::pair<unsigned, const TargetRegisterClass *>
R;
9421 unsigned RegNo =
R.first;
9422 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
9423 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
9424 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
9425 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
9435void LoongArchTargetLowering::LowerAsmOperandForConstraint(
9439 if (Constraint.
size() == 1) {
9440 switch (Constraint[0]) {
9444 uint64_t CVal =
C->getSExtValue();
9447 Subtarget.getGRLenVT()));
9453 uint64_t CVal =
C->getSExtValue();
9456 Subtarget.getGRLenVT()));
9462 if (
C->getZExtValue() == 0)
9469 uint64_t CVal =
C->getZExtValue();
9482#define GET_REGISTER_MATCHER
9483#include "LoongArchGenAsmMatcher.inc"
9489 std::string NewRegName = Name.second.str();
9495 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
9496 if (!ReservedRegs.
test(Reg))
9513 const APInt &Imm = ConstNode->getAPIntValue();
9515 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
9516 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
9519 if (ConstNode->hasOneUse() &&
9520 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
9521 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
9527 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
9528 unsigned Shifts = Imm.countr_zero();
9534 APInt ImmPop = Imm.ashr(Shifts);
9535 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
9539 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
9540 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
9541 (ImmSmall - Imm).isPowerOf2())
9551 Type *Ty,
unsigned AS,
9606 EVT MemVT = LD->getMemoryVT();
9607 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
9618 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
9627 if (
Y.getValueType().isVector())
9639 Type *Ty,
bool IsSigned)
const {
9640 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
9649 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
9650 Type.getSizeInBits() < Subtarget.getGRLen()))
9660 Align &PrefAlign)
const {
9664 if (Subtarget.is64Bit()) {
9666 PrefAlign =
Align(8);
9669 PrefAlign =
Align(4);
9684bool LoongArchTargetLowering::splitValueIntoRegisterParts(
9686 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
9687 bool IsABIRegCopy = CC.has_value();
9690 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9691 PartVT == MVT::f32) {
9694 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
9698 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f32, Val);
9706SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
9708 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
9709 bool IsABIRegCopy = CC.has_value();
9711 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9712 PartVT == MVT::f32) {
9716 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
9718 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
9729 if (VT == MVT::f16 && Subtarget.hasBasicF())
9735unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
9738 if (VT == MVT::f16 && Subtarget.hasBasicF())
9747 unsigned Depth)
const {
9748 EVT VT =
Op.getValueType();
9750 unsigned Opc =
Op.getOpcode();
9754 case LoongArchISD::VMSKLTZ:
9755 case LoongArchISD::XVMSKLTZ: {
9757 MVT SrcVT = Src.getSimpleValueType();
9762 if (OriginalDemandedBits.
countr_zero() >= NumElts)
9766 APInt KnownUndef, KnownZero;
9782 if (KnownSrc.
One[SrcBits - 1])
9784 else if (KnownSrc.
Zero[SrcBits - 1])
9789 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
9796 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
9819 unsigned Index)
const {
9828 unsigned Index)
const {
9832 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
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 bool getVShiftAmt(SDValue Op, unsigned ElementBits, int64_t &Amt)
getVShiftAmt - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
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 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 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 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 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)
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue performEXTRACT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
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 bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, 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 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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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.
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.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
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
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.
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 getTgtMemIntrinsic(IntrinsicInfo &Info, 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 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(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.
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.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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...
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.
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 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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
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.
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,...
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.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
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.
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.
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)
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.
@ 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.
@ 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.
@ ADD
Simple integer binary arithmetic operators.
@ 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.
@ 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...
@ 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.
@ 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.
@ 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.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ 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.
@ 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),...
@ 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.
@ 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.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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,...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
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 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 * > Tys={})
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.
@ Kill
The last use of a register.
@ 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.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
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.
unsigned getKillRegState(bool B)
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 isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo 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
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)