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}) {
358 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
360 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
362 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
366 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
391 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
392 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
407 if (Subtarget.hasExtLASX()) {
408 for (
MVT VT : LASXVTs) {
423 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
448 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
450 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
452 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
456 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
485 if (Subtarget.hasExtLSX()) {
492 if (Subtarget.hasExtLASX())
515 if (Subtarget.hasLAMCAS())
518 if (Subtarget.hasSCQ()) {
535 switch (
Op.getOpcode()) {
536 case ISD::ATOMIC_FENCE:
537 return lowerATOMIC_FENCE(
Op, DAG);
539 return lowerEH_DWARF_CFA(
Op, DAG);
541 return lowerGlobalAddress(
Op, DAG);
543 return lowerGlobalTLSAddress(
Op, DAG);
545 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
547 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
549 return lowerINTRINSIC_VOID(
Op, DAG);
551 return lowerBlockAddress(
Op, DAG);
553 return lowerJumpTable(
Op, DAG);
555 return lowerShiftLeftParts(
Op, DAG);
557 return lowerShiftRightParts(
Op, DAG,
true);
559 return lowerShiftRightParts(
Op, DAG,
false);
561 return lowerConstantPool(
Op, DAG);
563 return lowerFP_TO_SINT(
Op, DAG);
565 return lowerBITCAST(
Op, DAG);
567 return lowerUINT_TO_FP(
Op, DAG);
569 return lowerSINT_TO_FP(
Op, DAG);
571 return lowerVASTART(
Op, DAG);
573 return lowerFRAMEADDR(
Op, DAG);
575 return lowerRETURNADDR(
Op, DAG);
577 return lowerWRITE_REGISTER(
Op, DAG);
579 return lowerINSERT_VECTOR_ELT(
Op, DAG);
581 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
583 return lowerBUILD_VECTOR(
Op, DAG);
585 return lowerCONCAT_VECTORS(
Op, DAG);
587 return lowerVECTOR_SHUFFLE(
Op, DAG);
589 return lowerBITREVERSE(
Op, DAG);
591 return lowerSCALAR_TO_VECTOR(
Op, DAG);
593 return lowerPREFETCH(
Op, DAG);
595 return lowerSELECT(
Op, DAG);
597 return lowerBRCOND(
Op, DAG);
598 case ISD::FP_TO_FP16:
599 return lowerFP_TO_FP16(
Op, DAG);
600 case ISD::FP16_TO_FP:
601 return lowerFP16_TO_FP(
Op, DAG);
602 case ISD::FP_TO_BF16:
603 return lowerFP_TO_BF16(
Op, DAG);
604 case ISD::BF16_TO_FP:
605 return lowerBF16_TO_FP(
Op, DAG);
606 case ISD::VECREDUCE_ADD:
607 return lowerVECREDUCE_ADD(
Op, DAG);
610 return lowerRotate(
Op, DAG);
611 case ISD::VECREDUCE_AND:
612 case ISD::VECREDUCE_OR:
613 case ISD::VECREDUCE_XOR:
614 case ISD::VECREDUCE_SMAX:
615 case ISD::VECREDUCE_SMIN:
616 case ISD::VECREDUCE_UMAX:
617 case ISD::VECREDUCE_UMIN:
618 return lowerVECREDUCE(
Op, DAG);
620 return lowerConstantFP(
Op, DAG);
629 EVT VT = V.getValueType();
635 return V.getOperand(0);
639 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
641 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
651 if (!V->isOnlyUserOf(SplatValue.getNode()))
655 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
663 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
680 EVT VT =
Op.getValueType();
685 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
686 (VT == MVT::f64 && Subtarget.hasBasicD()));
703 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
713 if (Subtarget.is64Bit())
715 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
716 : LoongArchISD::MOVGR2FR_W,
720 if (Subtarget.is64Bit()) {
722 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
726 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
745 MVT OpVT =
Op.getSimpleValueType();
752 unsigned LegalVecSize = 128;
753 bool isLASX256Vector =
763 if (isLASX256Vector) {
768 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
771 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
774 if (isLASX256Vector) {
800 MVT OpVT =
Op.getSimpleValueType();
813 MVT GRLenVT = Subtarget.getGRLenVT();
815 for (
int i = NumEles; i > 1; i /= 2) {
818 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
827 unsigned IsData =
Op.getConstantOperandVal(4);
832 return Op.getOperand(0);
839 MVT VT =
Op.getSimpleValueType();
845 unsigned Opcode =
Op.getOpcode();
848 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
854 CstSplatValue =
C->getAPIntValue();
863 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
867 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
883 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
899 if (
LHS == LHS2 &&
RHS == RHS2) {
904 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
920 MVT VT =
N->getSimpleValueType(0);
951 if (~TrueVal == FalseVal) {
991 unsigned SelOpNo = 0;
1001 unsigned ConstSelOpNo = 1;
1002 unsigned OtherSelOpNo = 2;
1009 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1014 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1020 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1022 std::swap(NewConstOps[0], NewConstOps[1]);
1034 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1036 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1039 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1040 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1060 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1074 int64_t
C = RHSC->getSExtValue();
1117 MVT VT =
Op.getSimpleValueType();
1118 MVT GRLenVT = Subtarget.getGRLenVT();
1123 if (
Op.hasOneUse()) {
1124 unsigned UseOpc =
Op->user_begin()->getOpcode();
1126 SDNode *BinOp = *
Op->user_begin();
1133 return lowerSELECT(NewSel, DAG);
1150 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1173 if (TrueVal - 1 == FalseVal)
1175 if (TrueVal + 1 == FalseVal)
1182 RHS == TrueV &&
LHS == FalseV) {
1207 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1214 MVT GRLenVT = Subtarget.getGRLenVT();
1225 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1226 Op.getOperand(0),
LHS,
RHS, TargetCC,
1229 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1230 Op.getOperand(0), CondV,
Op.getOperand(2));
1234 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1240LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1243 MVT OpVT =
Op.getSimpleValueType();
1254 EVT ResTy =
Op->getValueType(0);
1259 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1269 for (
unsigned int i = 0; i < NewEltNum; i++) {
1272 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1273 ? (
unsigned)LoongArchISD::BITREV_8B
1291 for (
unsigned int i = 0; i < NewEltNum; i++)
1292 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1293 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1311 if (EltBits > 32 || EltBits == 1)
1339 int MaskOffset,
const APInt &Zeroable) {
1340 int Size = Mask.size();
1341 unsigned SizeInBits =
Size * ScalarSizeInBits;
1343 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1344 for (
int i = 0; i <
Size; i += Scale)
1345 for (
int j = 0; j < Shift; ++j)
1346 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1354 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1355 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1360 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1361 for (
int i = 0; i !=
Size; i += Scale) {
1362 unsigned Pos =
Left ? i + Shift : i;
1363 unsigned Low =
Left ? i : i + Shift;
1364 unsigned Len = Scale - Shift;
1369 int ShiftEltBits = ScalarSizeInBits * Scale;
1370 bool ByteShift = ShiftEltBits > 64;
1371 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1372 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1373 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1377 Scale = ByteShift ? Scale / 2 : Scale;
1383 return (
int)ShiftAmt;
1386 unsigned MaxWidth = 128;
1387 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1388 for (
int Shift = 1; Shift != Scale; ++Shift)
1389 for (
bool Left : {
true,
false})
1390 if (CheckZeros(Shift, Scale,
Left)) {
1391 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1416 const APInt &Zeroable) {
1417 int Size = Mask.size();
1431 Mask,
Size, Zeroable);
1439 "Illegal integer vector type");
1448template <
typename ValType>
1451 unsigned CheckStride,
1453 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1457 if (*
I != -1 && *
I != ExpectedIndex)
1459 ExpectedIndex += ExpectedIndexStride;
1463 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1475 int Size = Mask.size();
1485 int ScalarSizeInBits = VectorSizeInBits /
Size;
1486 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1487 (void)ScalarSizeInBits;
1489 for (
int i = 0; i <
Size; ++i) {
1495 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1512 RepeatedMask.
assign(LaneSize, -1);
1513 int Size = Mask.size();
1514 for (
int i = 0; i <
Size; ++i) {
1515 assert(Mask[i] == -1 || Mask[i] >= 0);
1518 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1525 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1526 if (RepeatedMask[i % LaneSize] < 0)
1528 RepeatedMask[i % LaneSize] = LocalM;
1529 else if (RepeatedMask[i % LaneSize] != LocalM)
1546 int NumElts = RepeatedMask.
size();
1548 int Scale = 16 / NumElts;
1550 for (
int i = 0; i < NumElts; ++i) {
1551 int M = RepeatedMask[i];
1552 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1553 "Unexpected mask index.");
1558 int StartIdx = i - (M % NumElts);
1565 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1568 Rotation = CandidateRotation;
1569 else if (Rotation != CandidateRotation)
1573 SDValue MaskV = M < NumElts ? V1 : V2;
1584 else if (TargetV != MaskV)
1589 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1590 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1599 return Rotation * Scale;
1618 if (ByteRotation <= 0)
1625 int LoByteShift = 16 - ByteRotation;
1626 int HiByteShift = ByteRotation;
1649 const APInt &Zeroable) {
1663 for (
int i = 0; i < NumElements; i++) {
1667 if (i % Scale != 0) {
1678 SDValue V = M < NumElements ? V1 : V2;
1679 M = M % NumElements;
1682 Offset = M - (i / Scale);
1685 if (
Offset % (NumElements / Scale))
1687 }
else if (InputV != V)
1690 if (M != (
Offset + (i / Scale)))
1700 unsigned VilVLoHi = LoongArchISD::VILVL;
1701 if (
Offset >= (NumElements / 2)) {
1702 VilVLoHi = LoongArchISD::VILVH;
1703 Offset -= (NumElements / 2);
1710 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1714 }
while (Scale > 1);
1720 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1721 NumExtElements *= 2) {
1741 int SplatIndex = -1;
1742 for (
const auto &M : Mask) {
1749 if (SplatIndex == -1)
1752 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1754 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
1784 unsigned SubVecSize = 4;
1785 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1788 int SubMask[4] = {-1, -1, -1, -1};
1789 for (
unsigned i = 0; i < SubVecSize; ++i) {
1790 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1796 M -= 4 * (j / SubVecSize);
1797 if (M < 0 || M >= 4)
1803 if (SubMask[i] == -1)
1807 else if (M != -1 && M != SubMask[i])
1814 for (
int i = SubVecSize - 1; i >= 0; --i) {
1827 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1828 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
1831 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
1849 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
1858 for (
int i = 0; i < WidenNumElts; ++i)
1859 WidenMask[i] = WidenNumElts - 1 - i;
1867 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
1891 const auto &Begin = Mask.begin();
1892 const auto &End = Mask.end();
1893 SDValue OriV1 = V1, OriV2 = V2;
1909 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
1931 const auto &Begin = Mask.begin();
1932 const auto &End = Mask.end();
1933 SDValue OriV1 = V1, OriV2 = V2;
1949 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
1972 const auto &Begin = Mask.begin();
1973 const auto &End = Mask.end();
1974 unsigned HalfSize = Mask.size() / 2;
1975 SDValue OriV1 = V1, OriV2 = V2;
1992 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2015 const auto &Begin = Mask.begin();
2016 const auto &End = Mask.end();
2017 SDValue OriV1 = V1, OriV2 = V2;
2033 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2055 const auto &Begin = Mask.begin();
2056 const auto &Mid = Mask.begin() + Mask.size() / 2;
2057 const auto &End = Mask.end();
2058 SDValue OriV1 = V1, OriV2 = V2;
2075 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2097 const auto &Begin = Mask.begin();
2098 const auto &Mid = Mask.begin() + Mask.size() / 2;
2099 const auto &End = Mask.end();
2100 SDValue OriV1 = V1, OriV2 = V2;
2116 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2142 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2155 "Vector type is unsupported for lsx!");
2157 "Two operands have different types!");
2159 "Unexpected mask size for shuffle!");
2160 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2162 APInt KnownUndef, KnownZero;
2164 APInt Zeroable = KnownUndef | KnownZero;
2231 int SplatIndex = -1;
2232 for (
const auto &M : Mask) {
2239 if (SplatIndex == -1)
2242 const auto &Begin = Mask.begin();
2243 const auto &End = Mask.end();
2244 int HalfSize = Mask.size() / 2;
2246 if (SplatIndex >= HalfSize)
2249 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2253 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2267 if (Mask.size() <= 4)
2278 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2281 unsigned MaskImm = 0;
2282 for (
unsigned i = 0; i < Mask.size(); ++i) {
2285 MaskImm |= Mask[i] << (i * 2);
2288 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2297 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2301 unsigned HalfSize = NumElts / 2;
2302 bool FrontLo =
true, FrontHi =
true;
2303 bool BackLo =
true, BackHi =
true;
2305 auto inRange = [](
int val,
int low,
int high) {
2306 return (val == -1) || (val >= low && val < high);
2309 for (
unsigned i = 0; i < HalfSize; ++i) {
2310 int Fronti = Mask[i];
2311 int Backi = Mask[i + HalfSize];
2313 FrontLo &=
inRange(Fronti, 0, HalfSize);
2314 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2315 BackLo &=
inRange(Backi, 0, HalfSize);
2316 BackHi &=
inRange(Backi, HalfSize, NumElts);
2322 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2327 for (
unsigned i = 0; i < NumElts; ++i)
2332 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2354 const auto &Begin = Mask.begin();
2355 const auto &End = Mask.end();
2356 unsigned HalfSize = Mask.size() / 2;
2357 unsigned LeftSize = HalfSize / 2;
2358 SDValue OriV1 = V1, OriV2 = V2;
2365 Mask.size() + HalfSize - LeftSize, 1) &&
2367 Mask.size() + HalfSize + LeftSize, 1))
2378 Mask.size() + HalfSize - LeftSize, 1) &&
2380 Mask.size() + HalfSize + LeftSize, 1))
2385 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2393 const auto &Begin = Mask.begin();
2394 const auto &End = Mask.end();
2395 unsigned HalfSize = Mask.size() / 2;
2396 SDValue OriV1 = V1, OriV2 = V2;
2403 Mask.size() + HalfSize, 1))
2414 Mask.size() + HalfSize, 1))
2419 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2427 const auto &Begin = Mask.begin();
2428 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2429 const auto &Mid = Mask.begin() + Mask.size() / 2;
2430 const auto &RightMid = Mask.end() - Mask.size() / 4;
2431 const auto &End = Mask.end();
2432 unsigned HalfSize = Mask.size() / 2;
2433 SDValue OriV1 = V1, OriV2 = V2;
2454 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2462 const auto &Begin = Mask.begin();
2463 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2464 const auto &Mid = Mask.begin() + Mask.size() / 2;
2465 const auto &RightMid = Mask.end() - Mask.size() / 4;
2466 const auto &End = Mask.end();
2467 unsigned HalfSize = Mask.size() / 2;
2468 SDValue OriV1 = V1, OriV2 = V2;
2490 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2499 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2504 int MaskSize = Mask.size();
2510 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2512 for (
int i = 0; i < MaskSize; ++i) {
2513 if (Mask[i] ==
Base + i || Mask[i] == -1)
2515 if (Mask[i] != Replaced)
2526 int Idx = checkReplaceOne(0, MaskSize);
2528 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
2532 Idx = checkReplaceOne(MaskSize, 0);
2534 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
2545 int MaskSize = Mask.size();
2546 int HalfSize = Mask.size() / 2;
2547 const auto &Begin = Mask.begin();
2548 const auto &Mid = Mask.begin() + HalfSize;
2549 const auto &End = Mask.end();
2561 for (
auto it = Begin; it < Mid; it++) {
2564 else if ((*it >= 0 && *it < HalfSize) ||
2565 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2566 int M = *it < HalfSize ? *it : *it - HalfSize;
2571 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2573 for (
auto it = Mid; it < End; it++) {
2576 else if ((*it >= HalfSize && *it < MaskSize) ||
2577 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2578 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2583 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2587 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2615 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2617 int MaskSize = Mask.size();
2618 int HalfSize = Mask.size() / 2;
2621 HalfMaskType preMask =
None, postMask =
None;
2623 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2624 return M < 0 || (M >= 0 && M < HalfSize) ||
2625 (M >= MaskSize && M < MaskSize + HalfSize);
2627 preMask = HighLaneTy;
2628 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2629 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2630 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2632 preMask = LowLaneTy;
2634 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2635 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2636 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2638 postMask = LowLaneTy;
2639 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2640 return M < 0 || (M >= 0 && M < HalfSize) ||
2641 (M >= MaskSize && M < MaskSize + HalfSize);
2643 postMask = HighLaneTy;
2651 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2654 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2656 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2662 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2667 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2668 *it = *it < 0 ? *it : *it - HalfSize;
2670 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2671 *it = *it < 0 ? *it : *it + HalfSize;
2673 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2675 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2681 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2686 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2687 *it = *it < 0 ? *it : *it - HalfSize;
2689 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2691 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2697 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2702 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2703 *it = *it < 0 ? *it : *it + HalfSize;
2728 int Size = Mask.size();
2729 int LaneSize =
Size / 2;
2731 bool LaneCrossing[2] = {
false,
false};
2732 for (
int i = 0; i <
Size; ++i)
2733 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2734 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2737 if (!LaneCrossing[0] && !LaneCrossing[1])
2741 InLaneMask.
assign(Mask.begin(), Mask.end());
2742 for (
int i = 0; i <
Size; ++i) {
2743 int &M = InLaneMask[i];
2746 if (((M %
Size) / LaneSize) != (i / LaneSize))
2747 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2752 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2767 "Vector type is unsupported for lasx!");
2769 "Two operands have different types!");
2771 "Unexpected mask size for shuffle!");
2772 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2773 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2775 APInt KnownUndef, KnownZero;
2777 APInt Zeroable = KnownUndef | KnownZero;
2854 ArrayRef<int> OrigMask = SVOp->
getMask();
2857 MVT VT =
Op.getSimpleValueType();
2861 bool V1IsUndef = V1.
isUndef();
2862 bool V2IsUndef = V2.
isUndef();
2863 if (V1IsUndef && V2IsUndef)
2876 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2877 SmallVector<int, 8> NewMask(OrigMask);
2878 for (
int &M : NewMask)
2879 if (M >= NumElements)
2885 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2886 (void)MaskUpperLimit;
2888 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2889 "Out of bounds shuffle index");
2911 std::tie(Res, Chain) =
2912 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2913 if (Subtarget.is64Bit())
2914 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
2926 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
2930 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2931 CallOptions,
DL, Chain);
2937 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2943 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2944 if (Subtarget.is64Bit())
2945 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
2951 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2952 MVT VT =
Op.getSimpleValueType();
2957 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
2961 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
2978 "Unsupported vector type for broadcast.");
2981 bool IsIdeneity =
true;
2983 for (
int i = 0; i !=
NumOps; i++) {
2985 if (
Op.getOpcode() != ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2997 auto ExtType = LN->getExtensionType();
3002 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3007 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3025 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3039 EVT ResTy,
unsigned first) {
3042 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3045 Node->op_begin() + first + NumElts);
3054 MVT VT =
Node->getSimpleValueType(0);
3055 EVT ResTy =
Op->getValueType(0);
3058 APInt SplatValue, SplatUndef;
3059 unsigned SplatBitSize;
3062 bool UseSameConstant =
true;
3067 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3068 (!Subtarget.hasExtLASX() || !Is256Vec))
3074 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3076 SplatBitSize <= 64) {
3078 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3082 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3089 if ((Is128Vec && ResTy == MVT::v4i32) ||
3090 (Is256Vec && ResTy == MVT::v8i32))
3096 switch (SplatBitSize) {
3100 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3103 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3106 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3109 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3117 if (ViaVecTy != ResTy)
3118 Result = DAG.
getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
3126 for (
unsigned i = 0; i < NumElts; ++i) {
3131 ConstantValue = Opi;
3132 else if (ConstantValue != Opi)
3133 UseSameConstant =
false;
3138 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3140 for (
unsigned i = 0; i < NumElts; ++i) {
3158 BitVector UndefElements;
3159 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3160 UndefElements.
count() == 0) {
3164 EVT FillTy = Is256Vec
3170 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3173 unsigned SplatLen = NumElts / SeqLen;
3179 if (SplatEltTy == MVT::i128)
3180 SplatTy = MVT::v4i64;
3188 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3189 : LoongArchISD::XVREPLVE0,
3190 DL, SplatTy, SrcVec);
3192 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3205 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3206 ResTy == MVT::v4f64) {
3207 unsigned NonUndefCount = 0;
3208 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3209 if (!
Node->getOperand(i).isUndef()) {
3211 if (NonUndefCount > 1)
3215 if (NonUndefCount == 1)
3228 VecTy, NumElts / 2);
3239 MVT ResVT =
Op.getSimpleValueType();
3243 unsigned NumFreezeUndef = 0;
3244 unsigned NumZero = 0;
3245 unsigned NumNonZero = 0;
3246 unsigned NonZeros = 0;
3247 SmallSet<SDValue, 4> Undefs;
3248 for (
unsigned i = 0; i != NumOperands; ++i) {
3263 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3270 if (NumNonZero > 2) {
3274 Ops.slice(0, NumOperands / 2));
3276 Ops.slice(NumOperands / 2));
3289 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3291 for (
unsigned i = 0; i != NumOperands; ++i) {
3292 if ((NonZeros & (1 << i)) == 0)
3303LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3305 MVT EltVT =
Op.getSimpleValueType();
3310 MVT GRLenVT = Subtarget.getGRLenVT();
3338 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3342 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3344 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3353 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3362LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3364 MVT VT =
Op.getSimpleValueType();
3387 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3389 for (
unsigned i = 0; i < NumElts; ++i) {
3397 for (
unsigned i = 0; i < NumElts; ++i) {
3406 for (
unsigned i = 0; i < NumElts; ++i)
3430 return DAG.
getNode(ISD::MEMBARRIER,
DL, MVT::Other,
Op.getOperand(0));
3438 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3440 "On LA64, only 64-bit registers can be written.");
3441 return Op.getOperand(0);
3444 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3446 "On LA32, only 32-bit registers can be written.");
3447 return Op.getOperand(0);
3457 "be a constant integer");
3463 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3464 EVT VT =
Op.getValueType();
3467 unsigned Depth =
Op.getConstantOperandVal(0);
3468 int GRLenInBytes = Subtarget.getGRLen() / 8;
3471 int Offset = -(GRLenInBytes * 2);
3483 if (
Op.getConstantOperandVal(0) != 0) {
3485 "return address can only be determined for the current frame");
3491 MVT GRLenVT = Subtarget.getGRLenVT();
3503 auto Size = Subtarget.getGRLen() / 8;
3511 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3521 MachinePointerInfo(SV));
3526 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3527 !Subtarget.hasBasicD() &&
"unexpected target features");
3533 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3537 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
3547 EVT RetVT =
Op.getValueType();
3553 std::tie(Result, Chain) =
3560 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3561 !Subtarget.hasBasicD() &&
"unexpected target features");
3572 EVT RetVT =
Op.getValueType();
3578 std::tie(Result, Chain) =
3587 EVT VT =
Op.getValueType();
3591 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3592 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3594 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
3596 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3599 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
3611 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
3613 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3614 !Subtarget.hasBasicD()) {
3616 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
3621 return DAG.
getNode(ISD::BITCAST,
DL,
Op.getValueType(), Trunc);
3638 N->getOffset(), Flags);
3646template <
class NodeTy>
3649 bool IsLocal)
const {
3660 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3731 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3733 const GlobalValue *GV =
N->getGlobal();
3745 unsigned Opc,
bool UseGOT,
3749 MVT GRLenVT = Subtarget.getGRLenVT();
3763 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3801 Args.emplace_back(Load, CallTy);
3804 TargetLowering::CallLoweringInfo CLI(DAG);
3819 const GlobalValue *GV =
N->getGlobal();
3833LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3840 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3843 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3856 return getDynamicTLSAddr(
N, DAG,
3857 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3858 : LoongArch::PseudoLA_TLS_GD,
3865 return getDynamicTLSAddr(
N, DAG,
3866 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3867 : LoongArch::PseudoLA_TLS_LD,
3872 return getStaticTLSAddr(
N, DAG,
3873 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3874 : LoongArch::PseudoLA_TLS_IE,
3881 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3885 return getTLSDescAddr(
N, DAG,
3886 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3887 : LoongArch::PseudoLA_TLS_DESC,
3891template <
unsigned N>
3896 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
3897 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
3899 ": argument out of range.");
3906LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3908 switch (
Op.getConstantOperandVal(0)) {
3911 case Intrinsic::thread_pointer: {
3915 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3916 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3917 case Intrinsic::loongarch_lsx_vreplvei_d:
3918 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3920 case Intrinsic::loongarch_lsx_vreplvei_w:
3921 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3922 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3923 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3924 case Intrinsic::loongarch_lasx_xvpickve_d:
3925 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3927 case Intrinsic::loongarch_lasx_xvinsve0_d:
3929 case Intrinsic::loongarch_lsx_vsat_b:
3930 case Intrinsic::loongarch_lsx_vsat_bu:
3931 case Intrinsic::loongarch_lsx_vrotri_b:
3932 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3933 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3934 case Intrinsic::loongarch_lsx_vsrlri_b:
3935 case Intrinsic::loongarch_lsx_vsrari_b:
3936 case Intrinsic::loongarch_lsx_vreplvei_h:
3937 case Intrinsic::loongarch_lasx_xvsat_b:
3938 case Intrinsic::loongarch_lasx_xvsat_bu:
3939 case Intrinsic::loongarch_lasx_xvrotri_b:
3940 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3941 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3942 case Intrinsic::loongarch_lasx_xvsrlri_b:
3943 case Intrinsic::loongarch_lasx_xvsrari_b:
3944 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3945 case Intrinsic::loongarch_lasx_xvpickve_w:
3946 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3948 case Intrinsic::loongarch_lasx_xvinsve0_w:
3950 case Intrinsic::loongarch_lsx_vsat_h:
3951 case Intrinsic::loongarch_lsx_vsat_hu:
3952 case Intrinsic::loongarch_lsx_vrotri_h:
3953 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3954 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3955 case Intrinsic::loongarch_lsx_vsrlri_h:
3956 case Intrinsic::loongarch_lsx_vsrari_h:
3957 case Intrinsic::loongarch_lsx_vreplvei_b:
3958 case Intrinsic::loongarch_lasx_xvsat_h:
3959 case Intrinsic::loongarch_lasx_xvsat_hu:
3960 case Intrinsic::loongarch_lasx_xvrotri_h:
3961 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3962 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3963 case Intrinsic::loongarch_lasx_xvsrlri_h:
3964 case Intrinsic::loongarch_lasx_xvsrari_h:
3965 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3967 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3968 case Intrinsic::loongarch_lsx_vsrani_b_h:
3969 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3970 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3971 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3972 case Intrinsic::loongarch_lsx_vssrani_b_h:
3973 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3974 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3975 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3976 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3977 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3978 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3979 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3980 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3981 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3982 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3983 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3984 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3985 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3986 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3987 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3988 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3989 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3990 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3992 case Intrinsic::loongarch_lsx_vsat_w:
3993 case Intrinsic::loongarch_lsx_vsat_wu:
3994 case Intrinsic::loongarch_lsx_vrotri_w:
3995 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3996 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3997 case Intrinsic::loongarch_lsx_vsrlri_w:
3998 case Intrinsic::loongarch_lsx_vsrari_w:
3999 case Intrinsic::loongarch_lsx_vslei_bu:
4000 case Intrinsic::loongarch_lsx_vslei_hu:
4001 case Intrinsic::loongarch_lsx_vslei_wu:
4002 case Intrinsic::loongarch_lsx_vslei_du:
4003 case Intrinsic::loongarch_lsx_vslti_bu:
4004 case Intrinsic::loongarch_lsx_vslti_hu:
4005 case Intrinsic::loongarch_lsx_vslti_wu:
4006 case Intrinsic::loongarch_lsx_vslti_du:
4007 case Intrinsic::loongarch_lsx_vbsll_v:
4008 case Intrinsic::loongarch_lsx_vbsrl_v:
4009 case Intrinsic::loongarch_lasx_xvsat_w:
4010 case Intrinsic::loongarch_lasx_xvsat_wu:
4011 case Intrinsic::loongarch_lasx_xvrotri_w:
4012 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4013 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4014 case Intrinsic::loongarch_lasx_xvsrlri_w:
4015 case Intrinsic::loongarch_lasx_xvsrari_w:
4016 case Intrinsic::loongarch_lasx_xvslei_bu:
4017 case Intrinsic::loongarch_lasx_xvslei_hu:
4018 case Intrinsic::loongarch_lasx_xvslei_wu:
4019 case Intrinsic::loongarch_lasx_xvslei_du:
4020 case Intrinsic::loongarch_lasx_xvslti_bu:
4021 case Intrinsic::loongarch_lasx_xvslti_hu:
4022 case Intrinsic::loongarch_lasx_xvslti_wu:
4023 case Intrinsic::loongarch_lasx_xvslti_du:
4024 case Intrinsic::loongarch_lasx_xvbsll_v:
4025 case Intrinsic::loongarch_lasx_xvbsrl_v:
4027 case Intrinsic::loongarch_lsx_vseqi_b:
4028 case Intrinsic::loongarch_lsx_vseqi_h:
4029 case Intrinsic::loongarch_lsx_vseqi_w:
4030 case Intrinsic::loongarch_lsx_vseqi_d:
4031 case Intrinsic::loongarch_lsx_vslei_b:
4032 case Intrinsic::loongarch_lsx_vslei_h:
4033 case Intrinsic::loongarch_lsx_vslei_w:
4034 case Intrinsic::loongarch_lsx_vslei_d:
4035 case Intrinsic::loongarch_lsx_vslti_b:
4036 case Intrinsic::loongarch_lsx_vslti_h:
4037 case Intrinsic::loongarch_lsx_vslti_w:
4038 case Intrinsic::loongarch_lsx_vslti_d:
4039 case Intrinsic::loongarch_lasx_xvseqi_b:
4040 case Intrinsic::loongarch_lasx_xvseqi_h:
4041 case Intrinsic::loongarch_lasx_xvseqi_w:
4042 case Intrinsic::loongarch_lasx_xvseqi_d:
4043 case Intrinsic::loongarch_lasx_xvslei_b:
4044 case Intrinsic::loongarch_lasx_xvslei_h:
4045 case Intrinsic::loongarch_lasx_xvslei_w:
4046 case Intrinsic::loongarch_lasx_xvslei_d:
4047 case Intrinsic::loongarch_lasx_xvslti_b:
4048 case Intrinsic::loongarch_lasx_xvslti_h:
4049 case Intrinsic::loongarch_lasx_xvslti_w:
4050 case Intrinsic::loongarch_lasx_xvslti_d:
4052 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4053 case Intrinsic::loongarch_lsx_vsrani_h_w:
4054 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4055 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4056 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4057 case Intrinsic::loongarch_lsx_vssrani_h_w:
4058 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4059 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4060 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4061 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4062 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4063 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4064 case Intrinsic::loongarch_lsx_vfrstpi_b:
4065 case Intrinsic::loongarch_lsx_vfrstpi_h:
4066 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4067 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4068 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4069 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4070 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4071 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4072 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4073 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4074 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4075 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4076 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4077 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4078 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4079 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4081 case Intrinsic::loongarch_lsx_vsat_d:
4082 case Intrinsic::loongarch_lsx_vsat_du:
4083 case Intrinsic::loongarch_lsx_vrotri_d:
4084 case Intrinsic::loongarch_lsx_vsrlri_d:
4085 case Intrinsic::loongarch_lsx_vsrari_d:
4086 case Intrinsic::loongarch_lasx_xvsat_d:
4087 case Intrinsic::loongarch_lasx_xvsat_du:
4088 case Intrinsic::loongarch_lasx_xvrotri_d:
4089 case Intrinsic::loongarch_lasx_xvsrlri_d:
4090 case Intrinsic::loongarch_lasx_xvsrari_d:
4092 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4093 case Intrinsic::loongarch_lsx_vsrani_w_d:
4094 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4095 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4096 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4097 case Intrinsic::loongarch_lsx_vssrani_w_d:
4098 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4099 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4100 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4101 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4102 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4103 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4104 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4105 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4106 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4107 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4108 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4109 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4110 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4111 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4112 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4113 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4114 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4115 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4117 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4118 case Intrinsic::loongarch_lsx_vsrani_d_q:
4119 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4120 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4121 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4122 case Intrinsic::loongarch_lsx_vssrani_d_q:
4123 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4124 case Intrinsic::loongarch_lsx_vssrani_du_q:
4125 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4126 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4127 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4128 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4129 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4130 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4131 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4132 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4133 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4134 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4135 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4136 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4137 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4138 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4139 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4140 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4142 case Intrinsic::loongarch_lsx_vnori_b:
4143 case Intrinsic::loongarch_lsx_vshuf4i_b:
4144 case Intrinsic::loongarch_lsx_vshuf4i_h:
4145 case Intrinsic::loongarch_lsx_vshuf4i_w:
4146 case Intrinsic::loongarch_lasx_xvnori_b:
4147 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4148 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4149 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4150 case Intrinsic::loongarch_lasx_xvpermi_d:
4152 case Intrinsic::loongarch_lsx_vshuf4i_d:
4153 case Intrinsic::loongarch_lsx_vpermi_w:
4154 case Intrinsic::loongarch_lsx_vbitseli_b:
4155 case Intrinsic::loongarch_lsx_vextrins_b:
4156 case Intrinsic::loongarch_lsx_vextrins_h:
4157 case Intrinsic::loongarch_lsx_vextrins_w:
4158 case Intrinsic::loongarch_lsx_vextrins_d:
4159 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4160 case Intrinsic::loongarch_lasx_xvpermi_w:
4161 case Intrinsic::loongarch_lasx_xvpermi_q:
4162 case Intrinsic::loongarch_lasx_xvbitseli_b:
4163 case Intrinsic::loongarch_lasx_xvextrins_b:
4164 case Intrinsic::loongarch_lasx_xvextrins_h:
4165 case Intrinsic::loongarch_lasx_xvextrins_w:
4166 case Intrinsic::loongarch_lasx_xvextrins_d:
4168 case Intrinsic::loongarch_lsx_vrepli_b:
4169 case Intrinsic::loongarch_lsx_vrepli_h:
4170 case Intrinsic::loongarch_lsx_vrepli_w:
4171 case Intrinsic::loongarch_lsx_vrepli_d:
4172 case Intrinsic::loongarch_lasx_xvrepli_b:
4173 case Intrinsic::loongarch_lasx_xvrepli_h:
4174 case Intrinsic::loongarch_lasx_xvrepli_w:
4175 case Intrinsic::loongarch_lasx_xvrepli_d:
4177 case Intrinsic::loongarch_lsx_vldi:
4178 case Intrinsic::loongarch_lasx_xvldi:
4194LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4197 MVT GRLenVT = Subtarget.getGRLenVT();
4198 EVT VT =
Op.getValueType();
4200 const StringRef ErrorMsgOOR =
"argument out of range";
4201 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4202 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4204 switch (
Op.getConstantOperandVal(1)) {
4207 case Intrinsic::loongarch_crc_w_b_w:
4208 case Intrinsic::loongarch_crc_w_h_w:
4209 case Intrinsic::loongarch_crc_w_w_w:
4210 case Intrinsic::loongarch_crc_w_d_w:
4211 case Intrinsic::loongarch_crcc_w_b_w:
4212 case Intrinsic::loongarch_crcc_w_h_w:
4213 case Intrinsic::loongarch_crcc_w_w_w:
4214 case Intrinsic::loongarch_crcc_w_d_w:
4216 case Intrinsic::loongarch_csrrd_w:
4217 case Intrinsic::loongarch_csrrd_d: {
4218 unsigned Imm =
Op.getConstantOperandVal(2);
4221 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4224 case Intrinsic::loongarch_csrwr_w:
4225 case Intrinsic::loongarch_csrwr_d: {
4226 unsigned Imm =
Op.getConstantOperandVal(3);
4229 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4230 {Chain,
Op.getOperand(2),
4233 case Intrinsic::loongarch_csrxchg_w:
4234 case Intrinsic::loongarch_csrxchg_d: {
4235 unsigned Imm =
Op.getConstantOperandVal(4);
4238 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4239 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4242 case Intrinsic::loongarch_iocsrrd_d: {
4244 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4247#define IOCSRRD_CASE(NAME, NODE) \
4248 case Intrinsic::loongarch_##NAME: { \
4249 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4250 {Chain, Op.getOperand(2)}); \
4256 case Intrinsic::loongarch_cpucfg: {
4257 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4258 {Chain,
Op.getOperand(2)});
4260 case Intrinsic::loongarch_lddir_d: {
4261 unsigned Imm =
Op.getConstantOperandVal(3);
4266 case Intrinsic::loongarch_movfcsr2gr: {
4267 if (!Subtarget.hasBasicF())
4269 unsigned Imm =
Op.getConstantOperandVal(2);
4272 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4275 case Intrinsic::loongarch_lsx_vld:
4276 case Intrinsic::loongarch_lsx_vldrepl_b:
4277 case Intrinsic::loongarch_lasx_xvld:
4278 case Intrinsic::loongarch_lasx_xvldrepl_b:
4282 case Intrinsic::loongarch_lsx_vldrepl_h:
4283 case Intrinsic::loongarch_lasx_xvldrepl_h:
4287 Op,
"argument out of range or not a multiple of 2", DAG)
4289 case Intrinsic::loongarch_lsx_vldrepl_w:
4290 case Intrinsic::loongarch_lasx_xvldrepl_w:
4294 Op,
"argument out of range or not a multiple of 4", DAG)
4296 case Intrinsic::loongarch_lsx_vldrepl_d:
4297 case Intrinsic::loongarch_lasx_xvldrepl_d:
4301 Op,
"argument out of range or not a multiple of 8", DAG)
4312 return Op.getOperand(0);
4318 MVT GRLenVT = Subtarget.getGRLenVT();
4320 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4322 const StringRef ErrorMsgOOR =
"argument out of range";
4323 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4324 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4325 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4327 switch (IntrinsicEnum) {
4331 case Intrinsic::loongarch_cacop_d:
4332 case Intrinsic::loongarch_cacop_w: {
4333 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4335 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4344 case Intrinsic::loongarch_dbar: {
4351 case Intrinsic::loongarch_ibar: {
4358 case Intrinsic::loongarch_break: {
4365 case Intrinsic::loongarch_movgr2fcsr: {
4366 if (!Subtarget.hasBasicF())
4376 case Intrinsic::loongarch_syscall: {
4383#define IOCSRWR_CASE(NAME, NODE) \
4384 case Intrinsic::loongarch_##NAME: { \
4385 SDValue Op3 = Op.getOperand(3); \
4386 return Subtarget.is64Bit() \
4387 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4388 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4389 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4390 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4397 case Intrinsic::loongarch_iocsrwr_d: {
4398 return !Subtarget.is64Bit()
4405#define ASRT_LE_GT_CASE(NAME) \
4406 case Intrinsic::loongarch_##NAME: { \
4407 return !Subtarget.is64Bit() \
4408 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4413#undef ASRT_LE_GT_CASE
4414 case Intrinsic::loongarch_ldpte_d: {
4415 unsigned Imm =
Op.getConstantOperandVal(3);
4416 return !Subtarget.is64Bit()
4421 case Intrinsic::loongarch_lsx_vst:
4422 case Intrinsic::loongarch_lasx_xvst:
4426 case Intrinsic::loongarch_lasx_xvstelm_b:
4431 case Intrinsic::loongarch_lsx_vstelm_b:
4436 case Intrinsic::loongarch_lasx_xvstelm_h:
4441 Op,
"argument out of range or not a multiple of 2", DAG)
4443 case Intrinsic::loongarch_lsx_vstelm_h:
4448 Op,
"argument out of range or not a multiple of 2", DAG)
4450 case Intrinsic::loongarch_lasx_xvstelm_w:
4455 Op,
"argument out of range or not a multiple of 4", DAG)
4457 case Intrinsic::loongarch_lsx_vstelm_w:
4462 Op,
"argument out of range or not a multiple of 4", DAG)
4464 case Intrinsic::loongarch_lasx_xvstelm_d:
4469 Op,
"argument out of range or not a multiple of 8", DAG)
4471 case Intrinsic::loongarch_lsx_vstelm_d:
4476 Op,
"argument out of range or not a multiple of 8", DAG)
4487 EVT VT =
Lo.getValueType();
4528 EVT VT =
Lo.getValueType();
4582 return LoongArchISD::DIV_W;
4584 return LoongArchISD::DIV_WU;
4586 return LoongArchISD::MOD_W;
4588 return LoongArchISD::MOD_WU;
4590 return LoongArchISD::SLL_W;
4592 return LoongArchISD::SRA_W;
4594 return LoongArchISD::SRL_W;
4597 return LoongArchISD::ROTR_W;
4599 return LoongArchISD::CTZ_W;
4601 return LoongArchISD::CLZ_W;
4620 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4621 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4625 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4631 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4658 StringRef ErrorMsg,
bool WithChain =
true) {
4663 Results.push_back(
N->getOperand(0));
4666template <
unsigned N>
4671 const StringRef ErrorMsgOOR =
"argument out of range";
4672 unsigned Imm =
Node->getConstantOperandVal(2);
4706 switch (
N->getConstantOperandVal(0)) {
4709 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4711 LoongArchISD::VPICK_SEXT_ELT);
4713 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4714 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4716 LoongArchISD::VPICK_SEXT_ELT);
4718 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4720 LoongArchISD::VPICK_SEXT_ELT);
4722 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4724 LoongArchISD::VPICK_ZEXT_ELT);
4726 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4727 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4729 LoongArchISD::VPICK_ZEXT_ELT);
4731 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4733 LoongArchISD::VPICK_ZEXT_ELT);
4735 case Intrinsic::loongarch_lsx_bz_b:
4736 case Intrinsic::loongarch_lsx_bz_h:
4737 case Intrinsic::loongarch_lsx_bz_w:
4738 case Intrinsic::loongarch_lsx_bz_d:
4739 case Intrinsic::loongarch_lasx_xbz_b:
4740 case Intrinsic::loongarch_lasx_xbz_h:
4741 case Intrinsic::loongarch_lasx_xbz_w:
4742 case Intrinsic::loongarch_lasx_xbz_d:
4744 LoongArchISD::VALL_ZERO);
4746 case Intrinsic::loongarch_lsx_bz_v:
4747 case Intrinsic::loongarch_lasx_xbz_v:
4749 LoongArchISD::VANY_ZERO);
4751 case Intrinsic::loongarch_lsx_bnz_b:
4752 case Intrinsic::loongarch_lsx_bnz_h:
4753 case Intrinsic::loongarch_lsx_bnz_w:
4754 case Intrinsic::loongarch_lsx_bnz_d:
4755 case Intrinsic::loongarch_lasx_xbnz_b:
4756 case Intrinsic::loongarch_lasx_xbnz_h:
4757 case Intrinsic::loongarch_lasx_xbnz_w:
4758 case Intrinsic::loongarch_lasx_xbnz_d:
4760 LoongArchISD::VALL_NONZERO);
4762 case Intrinsic::loongarch_lsx_bnz_v:
4763 case Intrinsic::loongarch_lasx_xbnz_v:
4765 LoongArchISD::VANY_NONZERO);
4773 assert(
N->getValueType(0) == MVT::i128 &&
4774 "AtomicCmpSwap on types less than 128 should be legal");
4778 switch (
MemOp->getMergedOrdering()) {
4782 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4786 Opcode = LoongArch::PseudoCmpXchg128;
4793 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4794 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4795 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4796 NewVal.first, NewVal.second,
N->getOperand(0)};
4799 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4810 EVT VT =
N->getValueType(0);
4811 switch (
N->getOpcode()) {
4816 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4817 "Unexpected custom legalisation");
4824 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4825 "Unexpected custom legalisation");
4827 Subtarget.hasDiv32() && VT == MVT::i32
4834 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4835 "Unexpected custom legalisation");
4843 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4844 "Unexpected custom legalisation");
4848 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4849 "Unexpected custom legalisation");
4856 if (Src.getValueType() == MVT::f16)
4857 Src = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Src);
4867 EVT OpVT = Src.getValueType();
4871 std::tie(Result, Chain) =
4876 case ISD::BITCAST: {
4878 EVT SrcVT = Src.getValueType();
4879 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
4880 Subtarget.hasBasicF()) {
4882 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
4884 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
4886 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4894 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4895 "Unexpected custom legalisation");
4898 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4904 assert((VT == MVT::i16 || VT == MVT::i32) &&
4905 "Unexpected custom legalization");
4906 MVT GRLenVT = Subtarget.getGRLenVT();
4913 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
4918 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
4926 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
4927 "Unexpected custom legalization");
4928 MVT GRLenVT = Subtarget.getGRLenVT();
4935 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
4938 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
4946 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4947 "Unexpected custom legalisation");
4954 MVT GRLenVT = Subtarget.getGRLenVT();
4955 const StringRef ErrorMsgOOR =
"argument out of range";
4956 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4957 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4959 switch (
N->getConstantOperandVal(1)) {
4962 case Intrinsic::loongarch_movfcsr2gr: {
4963 if (!Subtarget.hasBasicF()) {
4973 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
4980#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4981 case Intrinsic::loongarch_##NAME: { \
4982 SDValue NODE = DAG.getNode( \
4983 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4984 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4985 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4986 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4987 Results.push_back(NODE.getValue(1)); \
4996#undef CRC_CASE_EXT_BINARYOP
4998#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4999 case Intrinsic::loongarch_##NAME: { \
5000 SDValue NODE = DAG.getNode( \
5001 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5003 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5004 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5005 Results.push_back(NODE.getValue(1)); \
5010#undef CRC_CASE_EXT_UNARYOP
5011#define CSR_CASE(ID) \
5012 case Intrinsic::loongarch_##ID: { \
5013 if (!Subtarget.is64Bit()) \
5014 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5022 case Intrinsic::loongarch_csrrd_w: {
5029 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5036 case Intrinsic::loongarch_csrwr_w: {
5037 unsigned Imm =
N->getConstantOperandVal(3);
5043 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5051 case Intrinsic::loongarch_csrxchg_w: {
5052 unsigned Imm =
N->getConstantOperandVal(4);
5058 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5067#define IOCSRRD_CASE(NAME, NODE) \
5068 case Intrinsic::loongarch_##NAME: { \
5069 SDValue IOCSRRDResults = \
5070 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5071 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5072 Results.push_back( \
5073 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5074 Results.push_back(IOCSRRDResults.getValue(1)); \
5081 case Intrinsic::loongarch_cpucfg: {
5083 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5090 case Intrinsic::loongarch_lddir_d: {
5091 if (!Subtarget.is64Bit()) {
5101 if (Subtarget.is64Bit())
5103 "On LA64, only 64-bit registers can be read.");
5106 "On LA32, only 32-bit registers can be read.");
5108 Results.push_back(
N->getOperand(0));
5119 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5127 case ISD::ATOMIC_CMP_SWAP: {
5132 MVT VT =
N->getSimpleValueType(0);
5138 EVT InVT = In.getValueType();
5149 for (
unsigned I = 0;
I < MinElts; ++
I)
5150 TruncMask[
I] = Scale *
I;
5152 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5153 MVT SVT = In.getSimpleValueType().getScalarType();
5159 "Illegal vector type in truncation");
5175 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5177 MVT VT =
N->getSimpleValueType(0);
5196 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5205 SDValue FirstOperand =
N->getOperand(0);
5206 SDValue SecondOperand =
N->getOperand(1);
5207 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5208 EVT ValTy =
N->getValueType(0);
5211 unsigned SMIdx, SMLen;
5220 if (!Subtarget.has32S())
5242 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
5257 if (SMIdx + SMLen > ValTy.getSizeInBits())
5276 NewOperand = FirstOperand;
5279 msb = lsb + SMLen - 1;
5283 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5296 if (!Subtarget.has32S())
5308 SDValue FirstOperand =
N->getOperand(0);
5310 EVT ValTy =
N->getValueType(0);
5313 unsigned MaskIdx, MaskLen;
5328 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5329 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
5344 switch (Src.getOpcode()) {
5347 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5357 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5370 switch (Src.getOpcode()) {
5380 Src.getOpcode(),
DL, SExtVT,
5386 DL, SExtVT, Src.getOperand(0),
5398 EVT VT =
N->getValueType(0);
5400 EVT SrcVT = Src.getValueType();
5402 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5407 EVT CmpVT = Src.getOperand(0).getValueType();
5412 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5425 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
5430 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5435 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5440 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5442 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5447 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5449 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5454 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
5471 EVT VT =
N->getValueType(0);
5473 EVT SrcVT = Src.getValueType();
5490 bool UseLASX =
false;
5491 bool PropagateSExt =
false;
5493 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5494 EVT CmpVT = Src.getOperand(0).getValueType();
5503 SExtVT = MVT::v2i64;
5506 SExtVT = MVT::v4i32;
5508 SExtVT = MVT::v4i64;
5510 PropagateSExt =
true;
5514 SExtVT = MVT::v8i16;
5516 SExtVT = MVT::v8i32;
5518 PropagateSExt =
true;
5522 SExtVT = MVT::v16i8;
5524 SExtVT = MVT::v16i16;
5526 PropagateSExt =
true;
5530 SExtVT = MVT::v32i8;
5538 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5539 if (Src.getSimpleValueType() == MVT::v32i8) {
5547 }
else if (UseLASX) {
5553 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5566 EVT ValTy =
N->getValueType(0);
5567 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5570 unsigned ValBits = ValTy.getSizeInBits();
5571 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5573 bool SwapAndRetried =
false;
5576 if (!Subtarget.has32S())
5582 if (ValBits != 32 && ValBits != 64)
5597 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5600 (MaskIdx0 + MaskLen0 <= ValBits)) {
5621 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5622 (MaskIdx0 + MaskLen0 <= ValBits)) {
5639 (MaskIdx0 + MaskLen0 <= 64) &&
5647 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5648 : (MaskIdx0 + MaskLen0 - 1),
5664 (MaskIdx0 + MaskLen0 <= ValBits)) {
5687 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5688 : (MaskIdx0 + MaskLen0 - 1),
5703 unsigned MaskIdx, MaskLen;
5704 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5713 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5731 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5737 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5745 if (!SwapAndRetried) {
5747 SwapAndRetried =
true;
5751 SwapAndRetried =
false;
5768 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5777 if (!SwapAndRetried) {
5779 SwapAndRetried =
true;
5789 switch (V.getNode()->getOpcode()) {
5801 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5809 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5886 SDNode *AndNode =
N->getOperand(0).getNode();
5894 SDValue CmpInputValue =
N->getOperand(1);
5905 AndInputValue1 = AndInputValue1.
getOperand(0);
5909 if (AndInputValue2 != CmpInputValue)
5942 TruncInputValue1, TruncInputValue2);
5944 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5957 if (Src.getOpcode() != LoongArchISD::REVB_2W)
5960 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
5985 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6013 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6046 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6047 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6063 EVT VT =
N->getValueType(0);
6066 if (TrueV == FalseV)
6097 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6098 {LHS, RHS, CC, TrueV, FalseV});
6103template <
unsigned N>
6107 bool IsSigned =
false) {
6111 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6112 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6114 ": argument out of range.");
6120template <
unsigned N>
6124 EVT ResTy =
Node->getValueType(0);
6128 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6129 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6131 ": argument out of range.");
6136 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6142 EVT ResTy =
Node->getValueType(0);
6150 EVT ResTy =
Node->getValueType(0);
6159template <
unsigned N>
6162 EVT ResTy =
Node->getValueType(0);
6167 ": argument out of range.");
6177template <
unsigned N>
6180 EVT ResTy =
Node->getValueType(0);
6185 ": argument out of range.");
6194template <
unsigned N>
6197 EVT ResTy =
Node->getValueType(0);
6202 ": argument out of range.");
6211template <
unsigned W>
6214 unsigned Imm =
N->getConstantOperandVal(2);
6216 const StringRef ErrorMsg =
"argument out of range";
6218 return DAG.
getUNDEF(
N->getValueType(0));
6224 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6232 switch (
N->getConstantOperandVal(0)) {
6235 case Intrinsic::loongarch_lsx_vadd_b:
6236 case Intrinsic::loongarch_lsx_vadd_h:
6237 case Intrinsic::loongarch_lsx_vadd_w:
6238 case Intrinsic::loongarch_lsx_vadd_d:
6239 case Intrinsic::loongarch_lasx_xvadd_b:
6240 case Intrinsic::loongarch_lasx_xvadd_h:
6241 case Intrinsic::loongarch_lasx_xvadd_w:
6242 case Intrinsic::loongarch_lasx_xvadd_d:
6245 case Intrinsic::loongarch_lsx_vaddi_bu:
6246 case Intrinsic::loongarch_lsx_vaddi_hu:
6247 case Intrinsic::loongarch_lsx_vaddi_wu:
6248 case Intrinsic::loongarch_lsx_vaddi_du:
6249 case Intrinsic::loongarch_lasx_xvaddi_bu:
6250 case Intrinsic::loongarch_lasx_xvaddi_hu:
6251 case Intrinsic::loongarch_lasx_xvaddi_wu:
6252 case Intrinsic::loongarch_lasx_xvaddi_du:
6255 case Intrinsic::loongarch_lsx_vsub_b:
6256 case Intrinsic::loongarch_lsx_vsub_h:
6257 case Intrinsic::loongarch_lsx_vsub_w:
6258 case Intrinsic::loongarch_lsx_vsub_d:
6259 case Intrinsic::loongarch_lasx_xvsub_b:
6260 case Intrinsic::loongarch_lasx_xvsub_h:
6261 case Intrinsic::loongarch_lasx_xvsub_w:
6262 case Intrinsic::loongarch_lasx_xvsub_d:
6265 case Intrinsic::loongarch_lsx_vsubi_bu:
6266 case Intrinsic::loongarch_lsx_vsubi_hu:
6267 case Intrinsic::loongarch_lsx_vsubi_wu:
6268 case Intrinsic::loongarch_lsx_vsubi_du:
6269 case Intrinsic::loongarch_lasx_xvsubi_bu:
6270 case Intrinsic::loongarch_lasx_xvsubi_hu:
6271 case Intrinsic::loongarch_lasx_xvsubi_wu:
6272 case Intrinsic::loongarch_lasx_xvsubi_du:
6275 case Intrinsic::loongarch_lsx_vneg_b:
6276 case Intrinsic::loongarch_lsx_vneg_h:
6277 case Intrinsic::loongarch_lsx_vneg_w:
6278 case Intrinsic::loongarch_lsx_vneg_d:
6279 case Intrinsic::loongarch_lasx_xvneg_b:
6280 case Intrinsic::loongarch_lasx_xvneg_h:
6281 case Intrinsic::loongarch_lasx_xvneg_w:
6282 case Intrinsic::loongarch_lasx_xvneg_d:
6286 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6288 SDLoc(
N),
N->getValueType(0)),
6290 case Intrinsic::loongarch_lsx_vmax_b:
6291 case Intrinsic::loongarch_lsx_vmax_h:
6292 case Intrinsic::loongarch_lsx_vmax_w:
6293 case Intrinsic::loongarch_lsx_vmax_d:
6294 case Intrinsic::loongarch_lasx_xvmax_b:
6295 case Intrinsic::loongarch_lasx_xvmax_h:
6296 case Intrinsic::loongarch_lasx_xvmax_w:
6297 case Intrinsic::loongarch_lasx_xvmax_d:
6300 case Intrinsic::loongarch_lsx_vmax_bu:
6301 case Intrinsic::loongarch_lsx_vmax_hu:
6302 case Intrinsic::loongarch_lsx_vmax_wu:
6303 case Intrinsic::loongarch_lsx_vmax_du:
6304 case Intrinsic::loongarch_lasx_xvmax_bu:
6305 case Intrinsic::loongarch_lasx_xvmax_hu:
6306 case Intrinsic::loongarch_lasx_xvmax_wu:
6307 case Intrinsic::loongarch_lasx_xvmax_du:
6310 case Intrinsic::loongarch_lsx_vmaxi_b:
6311 case Intrinsic::loongarch_lsx_vmaxi_h:
6312 case Intrinsic::loongarch_lsx_vmaxi_w:
6313 case Intrinsic::loongarch_lsx_vmaxi_d:
6314 case Intrinsic::loongarch_lasx_xvmaxi_b:
6315 case Intrinsic::loongarch_lasx_xvmaxi_h:
6316 case Intrinsic::loongarch_lasx_xvmaxi_w:
6317 case Intrinsic::loongarch_lasx_xvmaxi_d:
6320 case Intrinsic::loongarch_lsx_vmaxi_bu:
6321 case Intrinsic::loongarch_lsx_vmaxi_hu:
6322 case Intrinsic::loongarch_lsx_vmaxi_wu:
6323 case Intrinsic::loongarch_lsx_vmaxi_du:
6324 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6325 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6326 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6327 case Intrinsic::loongarch_lasx_xvmaxi_du:
6330 case Intrinsic::loongarch_lsx_vmin_b:
6331 case Intrinsic::loongarch_lsx_vmin_h:
6332 case Intrinsic::loongarch_lsx_vmin_w:
6333 case Intrinsic::loongarch_lsx_vmin_d:
6334 case Intrinsic::loongarch_lasx_xvmin_b:
6335 case Intrinsic::loongarch_lasx_xvmin_h:
6336 case Intrinsic::loongarch_lasx_xvmin_w:
6337 case Intrinsic::loongarch_lasx_xvmin_d:
6340 case Intrinsic::loongarch_lsx_vmin_bu:
6341 case Intrinsic::loongarch_lsx_vmin_hu:
6342 case Intrinsic::loongarch_lsx_vmin_wu:
6343 case Intrinsic::loongarch_lsx_vmin_du:
6344 case Intrinsic::loongarch_lasx_xvmin_bu:
6345 case Intrinsic::loongarch_lasx_xvmin_hu:
6346 case Intrinsic::loongarch_lasx_xvmin_wu:
6347 case Intrinsic::loongarch_lasx_xvmin_du:
6350 case Intrinsic::loongarch_lsx_vmini_b:
6351 case Intrinsic::loongarch_lsx_vmini_h:
6352 case Intrinsic::loongarch_lsx_vmini_w:
6353 case Intrinsic::loongarch_lsx_vmini_d:
6354 case Intrinsic::loongarch_lasx_xvmini_b:
6355 case Intrinsic::loongarch_lasx_xvmini_h:
6356 case Intrinsic::loongarch_lasx_xvmini_w:
6357 case Intrinsic::loongarch_lasx_xvmini_d:
6360 case Intrinsic::loongarch_lsx_vmini_bu:
6361 case Intrinsic::loongarch_lsx_vmini_hu:
6362 case Intrinsic::loongarch_lsx_vmini_wu:
6363 case Intrinsic::loongarch_lsx_vmini_du:
6364 case Intrinsic::loongarch_lasx_xvmini_bu:
6365 case Intrinsic::loongarch_lasx_xvmini_hu:
6366 case Intrinsic::loongarch_lasx_xvmini_wu:
6367 case Intrinsic::loongarch_lasx_xvmini_du:
6370 case Intrinsic::loongarch_lsx_vmul_b:
6371 case Intrinsic::loongarch_lsx_vmul_h:
6372 case Intrinsic::loongarch_lsx_vmul_w:
6373 case Intrinsic::loongarch_lsx_vmul_d:
6374 case Intrinsic::loongarch_lasx_xvmul_b:
6375 case Intrinsic::loongarch_lasx_xvmul_h:
6376 case Intrinsic::loongarch_lasx_xvmul_w:
6377 case Intrinsic::loongarch_lasx_xvmul_d:
6380 case Intrinsic::loongarch_lsx_vmadd_b:
6381 case Intrinsic::loongarch_lsx_vmadd_h:
6382 case Intrinsic::loongarch_lsx_vmadd_w:
6383 case Intrinsic::loongarch_lsx_vmadd_d:
6384 case Intrinsic::loongarch_lasx_xvmadd_b:
6385 case Intrinsic::loongarch_lasx_xvmadd_h:
6386 case Intrinsic::loongarch_lasx_xvmadd_w:
6387 case Intrinsic::loongarch_lasx_xvmadd_d: {
6388 EVT ResTy =
N->getValueType(0);
6393 case Intrinsic::loongarch_lsx_vmsub_b:
6394 case Intrinsic::loongarch_lsx_vmsub_h:
6395 case Intrinsic::loongarch_lsx_vmsub_w:
6396 case Intrinsic::loongarch_lsx_vmsub_d:
6397 case Intrinsic::loongarch_lasx_xvmsub_b:
6398 case Intrinsic::loongarch_lasx_xvmsub_h:
6399 case Intrinsic::loongarch_lasx_xvmsub_w:
6400 case Intrinsic::loongarch_lasx_xvmsub_d: {
6401 EVT ResTy =
N->getValueType(0);
6406 case Intrinsic::loongarch_lsx_vdiv_b:
6407 case Intrinsic::loongarch_lsx_vdiv_h:
6408 case Intrinsic::loongarch_lsx_vdiv_w:
6409 case Intrinsic::loongarch_lsx_vdiv_d:
6410 case Intrinsic::loongarch_lasx_xvdiv_b:
6411 case Intrinsic::loongarch_lasx_xvdiv_h:
6412 case Intrinsic::loongarch_lasx_xvdiv_w:
6413 case Intrinsic::loongarch_lasx_xvdiv_d:
6416 case Intrinsic::loongarch_lsx_vdiv_bu:
6417 case Intrinsic::loongarch_lsx_vdiv_hu:
6418 case Intrinsic::loongarch_lsx_vdiv_wu:
6419 case Intrinsic::loongarch_lsx_vdiv_du:
6420 case Intrinsic::loongarch_lasx_xvdiv_bu:
6421 case Intrinsic::loongarch_lasx_xvdiv_hu:
6422 case Intrinsic::loongarch_lasx_xvdiv_wu:
6423 case Intrinsic::loongarch_lasx_xvdiv_du:
6426 case Intrinsic::loongarch_lsx_vmod_b:
6427 case Intrinsic::loongarch_lsx_vmod_h:
6428 case Intrinsic::loongarch_lsx_vmod_w:
6429 case Intrinsic::loongarch_lsx_vmod_d:
6430 case Intrinsic::loongarch_lasx_xvmod_b:
6431 case Intrinsic::loongarch_lasx_xvmod_h:
6432 case Intrinsic::loongarch_lasx_xvmod_w:
6433 case Intrinsic::loongarch_lasx_xvmod_d:
6436 case Intrinsic::loongarch_lsx_vmod_bu:
6437 case Intrinsic::loongarch_lsx_vmod_hu:
6438 case Intrinsic::loongarch_lsx_vmod_wu:
6439 case Intrinsic::loongarch_lsx_vmod_du:
6440 case Intrinsic::loongarch_lasx_xvmod_bu:
6441 case Intrinsic::loongarch_lasx_xvmod_hu:
6442 case Intrinsic::loongarch_lasx_xvmod_wu:
6443 case Intrinsic::loongarch_lasx_xvmod_du:
6446 case Intrinsic::loongarch_lsx_vand_v:
6447 case Intrinsic::loongarch_lasx_xvand_v:
6450 case Intrinsic::loongarch_lsx_vor_v:
6451 case Intrinsic::loongarch_lasx_xvor_v:
6454 case Intrinsic::loongarch_lsx_vxor_v:
6455 case Intrinsic::loongarch_lasx_xvxor_v:
6458 case Intrinsic::loongarch_lsx_vnor_v:
6459 case Intrinsic::loongarch_lasx_xvnor_v: {
6464 case Intrinsic::loongarch_lsx_vandi_b:
6465 case Intrinsic::loongarch_lasx_xvandi_b:
6468 case Intrinsic::loongarch_lsx_vori_b:
6469 case Intrinsic::loongarch_lasx_xvori_b:
6472 case Intrinsic::loongarch_lsx_vxori_b:
6473 case Intrinsic::loongarch_lasx_xvxori_b:
6476 case Intrinsic::loongarch_lsx_vsll_b:
6477 case Intrinsic::loongarch_lsx_vsll_h:
6478 case Intrinsic::loongarch_lsx_vsll_w:
6479 case Intrinsic::loongarch_lsx_vsll_d:
6480 case Intrinsic::loongarch_lasx_xvsll_b:
6481 case Intrinsic::loongarch_lasx_xvsll_h:
6482 case Intrinsic::loongarch_lasx_xvsll_w:
6483 case Intrinsic::loongarch_lasx_xvsll_d:
6486 case Intrinsic::loongarch_lsx_vslli_b:
6487 case Intrinsic::loongarch_lasx_xvslli_b:
6490 case Intrinsic::loongarch_lsx_vslli_h:
6491 case Intrinsic::loongarch_lasx_xvslli_h:
6494 case Intrinsic::loongarch_lsx_vslli_w:
6495 case Intrinsic::loongarch_lasx_xvslli_w:
6498 case Intrinsic::loongarch_lsx_vslli_d:
6499 case Intrinsic::loongarch_lasx_xvslli_d:
6502 case Intrinsic::loongarch_lsx_vsrl_b:
6503 case Intrinsic::loongarch_lsx_vsrl_h:
6504 case Intrinsic::loongarch_lsx_vsrl_w:
6505 case Intrinsic::loongarch_lsx_vsrl_d:
6506 case Intrinsic::loongarch_lasx_xvsrl_b:
6507 case Intrinsic::loongarch_lasx_xvsrl_h:
6508 case Intrinsic::loongarch_lasx_xvsrl_w:
6509 case Intrinsic::loongarch_lasx_xvsrl_d:
6512 case Intrinsic::loongarch_lsx_vsrli_b:
6513 case Intrinsic::loongarch_lasx_xvsrli_b:
6516 case Intrinsic::loongarch_lsx_vsrli_h:
6517 case Intrinsic::loongarch_lasx_xvsrli_h:
6520 case Intrinsic::loongarch_lsx_vsrli_w:
6521 case Intrinsic::loongarch_lasx_xvsrli_w:
6524 case Intrinsic::loongarch_lsx_vsrli_d:
6525 case Intrinsic::loongarch_lasx_xvsrli_d:
6528 case Intrinsic::loongarch_lsx_vsra_b:
6529 case Intrinsic::loongarch_lsx_vsra_h:
6530 case Intrinsic::loongarch_lsx_vsra_w:
6531 case Intrinsic::loongarch_lsx_vsra_d:
6532 case Intrinsic::loongarch_lasx_xvsra_b:
6533 case Intrinsic::loongarch_lasx_xvsra_h:
6534 case Intrinsic::loongarch_lasx_xvsra_w:
6535 case Intrinsic::loongarch_lasx_xvsra_d:
6538 case Intrinsic::loongarch_lsx_vsrai_b:
6539 case Intrinsic::loongarch_lasx_xvsrai_b:
6542 case Intrinsic::loongarch_lsx_vsrai_h:
6543 case Intrinsic::loongarch_lasx_xvsrai_h:
6546 case Intrinsic::loongarch_lsx_vsrai_w:
6547 case Intrinsic::loongarch_lasx_xvsrai_w:
6550 case Intrinsic::loongarch_lsx_vsrai_d:
6551 case Intrinsic::loongarch_lasx_xvsrai_d:
6554 case Intrinsic::loongarch_lsx_vclz_b:
6555 case Intrinsic::loongarch_lsx_vclz_h:
6556 case Intrinsic::loongarch_lsx_vclz_w:
6557 case Intrinsic::loongarch_lsx_vclz_d:
6558 case Intrinsic::loongarch_lasx_xvclz_b:
6559 case Intrinsic::loongarch_lasx_xvclz_h:
6560 case Intrinsic::loongarch_lasx_xvclz_w:
6561 case Intrinsic::loongarch_lasx_xvclz_d:
6563 case Intrinsic::loongarch_lsx_vpcnt_b:
6564 case Intrinsic::loongarch_lsx_vpcnt_h:
6565 case Intrinsic::loongarch_lsx_vpcnt_w:
6566 case Intrinsic::loongarch_lsx_vpcnt_d:
6567 case Intrinsic::loongarch_lasx_xvpcnt_b:
6568 case Intrinsic::loongarch_lasx_xvpcnt_h:
6569 case Intrinsic::loongarch_lasx_xvpcnt_w:
6570 case Intrinsic::loongarch_lasx_xvpcnt_d:
6572 case Intrinsic::loongarch_lsx_vbitclr_b:
6573 case Intrinsic::loongarch_lsx_vbitclr_h:
6574 case Intrinsic::loongarch_lsx_vbitclr_w:
6575 case Intrinsic::loongarch_lsx_vbitclr_d:
6576 case Intrinsic::loongarch_lasx_xvbitclr_b:
6577 case Intrinsic::loongarch_lasx_xvbitclr_h:
6578 case Intrinsic::loongarch_lasx_xvbitclr_w:
6579 case Intrinsic::loongarch_lasx_xvbitclr_d:
6581 case Intrinsic::loongarch_lsx_vbitclri_b:
6582 case Intrinsic::loongarch_lasx_xvbitclri_b:
6584 case Intrinsic::loongarch_lsx_vbitclri_h:
6585 case Intrinsic::loongarch_lasx_xvbitclri_h:
6587 case Intrinsic::loongarch_lsx_vbitclri_w:
6588 case Intrinsic::loongarch_lasx_xvbitclri_w:
6590 case Intrinsic::loongarch_lsx_vbitclri_d:
6591 case Intrinsic::loongarch_lasx_xvbitclri_d:
6593 case Intrinsic::loongarch_lsx_vbitset_b:
6594 case Intrinsic::loongarch_lsx_vbitset_h:
6595 case Intrinsic::loongarch_lsx_vbitset_w:
6596 case Intrinsic::loongarch_lsx_vbitset_d:
6597 case Intrinsic::loongarch_lasx_xvbitset_b:
6598 case Intrinsic::loongarch_lasx_xvbitset_h:
6599 case Intrinsic::loongarch_lasx_xvbitset_w:
6600 case Intrinsic::loongarch_lasx_xvbitset_d: {
6601 EVT VecTy =
N->getValueType(0);
6607 case Intrinsic::loongarch_lsx_vbitseti_b:
6608 case Intrinsic::loongarch_lasx_xvbitseti_b:
6610 case Intrinsic::loongarch_lsx_vbitseti_h:
6611 case Intrinsic::loongarch_lasx_xvbitseti_h:
6613 case Intrinsic::loongarch_lsx_vbitseti_w:
6614 case Intrinsic::loongarch_lasx_xvbitseti_w:
6616 case Intrinsic::loongarch_lsx_vbitseti_d:
6617 case Intrinsic::loongarch_lasx_xvbitseti_d:
6619 case Intrinsic::loongarch_lsx_vbitrev_b:
6620 case Intrinsic::loongarch_lsx_vbitrev_h:
6621 case Intrinsic::loongarch_lsx_vbitrev_w:
6622 case Intrinsic::loongarch_lsx_vbitrev_d:
6623 case Intrinsic::loongarch_lasx_xvbitrev_b:
6624 case Intrinsic::loongarch_lasx_xvbitrev_h:
6625 case Intrinsic::loongarch_lasx_xvbitrev_w:
6626 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6627 EVT VecTy =
N->getValueType(0);
6633 case Intrinsic::loongarch_lsx_vbitrevi_b:
6634 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6636 case Intrinsic::loongarch_lsx_vbitrevi_h:
6637 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6639 case Intrinsic::loongarch_lsx_vbitrevi_w:
6640 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6642 case Intrinsic::loongarch_lsx_vbitrevi_d:
6643 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6645 case Intrinsic::loongarch_lsx_vfadd_s:
6646 case Intrinsic::loongarch_lsx_vfadd_d:
6647 case Intrinsic::loongarch_lasx_xvfadd_s:
6648 case Intrinsic::loongarch_lasx_xvfadd_d:
6651 case Intrinsic::loongarch_lsx_vfsub_s:
6652 case Intrinsic::loongarch_lsx_vfsub_d:
6653 case Intrinsic::loongarch_lasx_xvfsub_s:
6654 case Intrinsic::loongarch_lasx_xvfsub_d:
6657 case Intrinsic::loongarch_lsx_vfmul_s:
6658 case Intrinsic::loongarch_lsx_vfmul_d:
6659 case Intrinsic::loongarch_lasx_xvfmul_s:
6660 case Intrinsic::loongarch_lasx_xvfmul_d:
6663 case Intrinsic::loongarch_lsx_vfdiv_s:
6664 case Intrinsic::loongarch_lsx_vfdiv_d:
6665 case Intrinsic::loongarch_lasx_xvfdiv_s:
6666 case Intrinsic::loongarch_lasx_xvfdiv_d:
6669 case Intrinsic::loongarch_lsx_vfmadd_s:
6670 case Intrinsic::loongarch_lsx_vfmadd_d:
6671 case Intrinsic::loongarch_lasx_xvfmadd_s:
6672 case Intrinsic::loongarch_lasx_xvfmadd_d:
6674 N->getOperand(2),
N->getOperand(3));
6675 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6677 N->getOperand(1),
N->getOperand(2),
6679 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6680 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6682 N->getOperand(1),
N->getOperand(2),
6684 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6685 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6687 N->getOperand(1),
N->getOperand(2),
6689 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6691 N->getOperand(1),
N->getOperand(2),
6693 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6694 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6695 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6696 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6697 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6698 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6699 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6700 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6701 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
6704 case Intrinsic::loongarch_lsx_vreplve_b:
6705 case Intrinsic::loongarch_lsx_vreplve_h:
6706 case Intrinsic::loongarch_lsx_vreplve_w:
6707 case Intrinsic::loongarch_lsx_vreplve_d:
6708 case Intrinsic::loongarch_lasx_xvreplve_b:
6709 case Intrinsic::loongarch_lasx_xvreplve_h:
6710 case Intrinsic::loongarch_lasx_xvreplve_w:
6711 case Intrinsic::loongarch_lasx_xvreplve_d:
6712 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
6716 case Intrinsic::loongarch_lsx_vpickve2gr_b:
6720 case Intrinsic::loongarch_lsx_vpickve2gr_h:
6721 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
6725 case Intrinsic::loongarch_lsx_vpickve2gr_w:
6729 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
6733 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
6734 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
6738 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
6742 case Intrinsic::loongarch_lsx_bz_b:
6743 case Intrinsic::loongarch_lsx_bz_h:
6744 case Intrinsic::loongarch_lsx_bz_w:
6745 case Intrinsic::loongarch_lsx_bz_d:
6746 case Intrinsic::loongarch_lasx_xbz_b:
6747 case Intrinsic::loongarch_lasx_xbz_h:
6748 case Intrinsic::loongarch_lasx_xbz_w:
6749 case Intrinsic::loongarch_lasx_xbz_d:
6751 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
6754 case Intrinsic::loongarch_lsx_bz_v:
6755 case Intrinsic::loongarch_lasx_xbz_v:
6757 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
6760 case Intrinsic::loongarch_lsx_bnz_b:
6761 case Intrinsic::loongarch_lsx_bnz_h:
6762 case Intrinsic::loongarch_lsx_bnz_w:
6763 case Intrinsic::loongarch_lsx_bnz_d:
6764 case Intrinsic::loongarch_lasx_xbnz_b:
6765 case Intrinsic::loongarch_lasx_xbnz_h:
6766 case Intrinsic::loongarch_lasx_xbnz_w:
6767 case Intrinsic::loongarch_lasx_xbnz_d:
6769 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
6772 case Intrinsic::loongarch_lsx_bnz_v:
6773 case Intrinsic::loongarch_lasx_xbnz_v:
6775 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
6778 case Intrinsic::loongarch_lasx_concat_128_s:
6779 case Intrinsic::loongarch_lasx_concat_128_d:
6780 case Intrinsic::loongarch_lasx_concat_128:
6782 N->getOperand(1),
N->getOperand(2));
6794 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
6806 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
6808 "Unexpected value type!");
6817 MVT VT =
N->getSimpleValueType(0);
6838 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
6851 APInt V =
C->getValueAPF().bitcastToAPInt();
6867 MVT EltVT =
N->getSimpleValueType(0);
6902 MVT VT =
N->getSimpleValueType(0);
6962 switch (
N->getOpcode()) {
6975 case LoongArchISD::BITREV_W:
6977 case LoongArchISD::BR_CC:
6979 case LoongArchISD::SELECT_CC:
6983 case LoongArchISD::MOVGR2FR_W_LA64:
6985 case LoongArchISD::MOVFR2GR_S_LA64:
6987 case LoongArchISD::VMSKLTZ:
6988 case LoongArchISD::XVMSKLTZ:
6990 case LoongArchISD::SPLIT_PAIR_F64:
6994 case LoongArchISD::VANDN:
7018 MF->
insert(It, BreakMBB);
7022 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
7023 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
7035 MBB->addSuccessor(BreakMBB);
7036 MBB->addSuccessor(SinkMBB);
7042 BreakMBB->addSuccessor(SinkMBB);
7054 switch (
MI.getOpcode()) {
7057 case LoongArch::PseudoVBZ:
7058 CondOpc = LoongArch::VSETEQZ_V;
7060 case LoongArch::PseudoVBZ_B:
7061 CondOpc = LoongArch::VSETANYEQZ_B;
7063 case LoongArch::PseudoVBZ_H:
7064 CondOpc = LoongArch::VSETANYEQZ_H;
7066 case LoongArch::PseudoVBZ_W:
7067 CondOpc = LoongArch::VSETANYEQZ_W;
7069 case LoongArch::PseudoVBZ_D:
7070 CondOpc = LoongArch::VSETANYEQZ_D;
7072 case LoongArch::PseudoVBNZ:
7073 CondOpc = LoongArch::VSETNEZ_V;
7075 case LoongArch::PseudoVBNZ_B:
7076 CondOpc = LoongArch::VSETALLNEZ_B;
7078 case LoongArch::PseudoVBNZ_H:
7079 CondOpc = LoongArch::VSETALLNEZ_H;
7081 case LoongArch::PseudoVBNZ_W:
7082 CondOpc = LoongArch::VSETALLNEZ_W;
7084 case LoongArch::PseudoVBNZ_D:
7085 CondOpc = LoongArch::VSETALLNEZ_D;
7087 case LoongArch::PseudoXVBZ:
7088 CondOpc = LoongArch::XVSETEQZ_V;
7090 case LoongArch::PseudoXVBZ_B:
7091 CondOpc = LoongArch::XVSETANYEQZ_B;
7093 case LoongArch::PseudoXVBZ_H:
7094 CondOpc = LoongArch::XVSETANYEQZ_H;
7096 case LoongArch::PseudoXVBZ_W:
7097 CondOpc = LoongArch::XVSETANYEQZ_W;
7099 case LoongArch::PseudoXVBZ_D:
7100 CondOpc = LoongArch::XVSETANYEQZ_D;
7102 case LoongArch::PseudoXVBNZ:
7103 CondOpc = LoongArch::XVSETNEZ_V;
7105 case LoongArch::PseudoXVBNZ_B:
7106 CondOpc = LoongArch::XVSETALLNEZ_B;
7108 case LoongArch::PseudoXVBNZ_H:
7109 CondOpc = LoongArch::XVSETALLNEZ_H;
7111 case LoongArch::PseudoXVBNZ_W:
7112 CondOpc = LoongArch::XVSETALLNEZ_W;
7114 case LoongArch::PseudoXVBNZ_D:
7115 CondOpc = LoongArch::XVSETALLNEZ_D;
7130 F->insert(It, FalseBB);
7131 F->insert(It, TrueBB);
7132 F->insert(It, SinkBB);
7135 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
7139 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
7148 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7156 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7164 MI.getOperand(0).getReg())
7171 MI.eraseFromParent();
7179 unsigned BroadcastOp;
7181 switch (
MI.getOpcode()) {
7184 case LoongArch::PseudoXVINSGR2VR_B:
7186 BroadcastOp = LoongArch::XVREPLGR2VR_B;
7187 InsOp = LoongArch::XVEXTRINS_B;
7189 case LoongArch::PseudoXVINSGR2VR_H:
7191 BroadcastOp = LoongArch::XVREPLGR2VR_H;
7192 InsOp = LoongArch::XVEXTRINS_H;
7204 unsigned Idx =
MI.getOperand(3).getImm();
7206 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
7208 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
7209 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
7212 .
addReg(XSrc, 0, LoongArch::sub_128);
7214 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
7215 : LoongArch::VINSGR2VR_B),
7224 .
addImm(LoongArch::sub_128);
7226 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7227 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7231 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
7234 .
addImm(Idx >= HalfSize ? 48 : 18);
7239 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
7242 MI.eraseFromParent();
7249 assert(Subtarget.hasExtLSX());
7256 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7257 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7258 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
7262 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
7263 : LoongArch::VINSGR2VR_W),
7270 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
7274 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
7275 : LoongArch::VPICKVE2GR_W),
7280 MI.eraseFromParent();
7294 unsigned EleBits = 8;
7295 unsigned NotOpc = 0;
7298 switch (
MI.getOpcode()) {
7301 case LoongArch::PseudoVMSKLTZ_B:
7302 MskOpc = LoongArch::VMSKLTZ_B;
7304 case LoongArch::PseudoVMSKLTZ_H:
7305 MskOpc = LoongArch::VMSKLTZ_H;
7308 case LoongArch::PseudoVMSKLTZ_W:
7309 MskOpc = LoongArch::VMSKLTZ_W;
7312 case LoongArch::PseudoVMSKLTZ_D:
7313 MskOpc = LoongArch::VMSKLTZ_D;
7316 case LoongArch::PseudoVMSKGEZ_B:
7317 MskOpc = LoongArch::VMSKGEZ_B;
7319 case LoongArch::PseudoVMSKEQZ_B:
7320 MskOpc = LoongArch::VMSKNZ_B;
7321 NotOpc = LoongArch::VNOR_V;
7323 case LoongArch::PseudoVMSKNEZ_B:
7324 MskOpc = LoongArch::VMSKNZ_B;
7326 case LoongArch::PseudoXVMSKLTZ_B:
7327 MskOpc = LoongArch::XVMSKLTZ_B;
7328 RC = &LoongArch::LASX256RegClass;
7330 case LoongArch::PseudoXVMSKLTZ_H:
7331 MskOpc = LoongArch::XVMSKLTZ_H;
7332 RC = &LoongArch::LASX256RegClass;
7335 case LoongArch::PseudoXVMSKLTZ_W:
7336 MskOpc = LoongArch::XVMSKLTZ_W;
7337 RC = &LoongArch::LASX256RegClass;
7340 case LoongArch::PseudoXVMSKLTZ_D:
7341 MskOpc = LoongArch::XVMSKLTZ_D;
7342 RC = &LoongArch::LASX256RegClass;
7345 case LoongArch::PseudoXVMSKGEZ_B:
7346 MskOpc = LoongArch::XVMSKGEZ_B;
7347 RC = &LoongArch::LASX256RegClass;
7349 case LoongArch::PseudoXVMSKEQZ_B:
7350 MskOpc = LoongArch::XVMSKNZ_B;
7351 NotOpc = LoongArch::XVNOR_V;
7352 RC = &LoongArch::LASX256RegClass;
7354 case LoongArch::PseudoXVMSKNEZ_B:
7355 MskOpc = LoongArch::XVMSKNZ_B;
7356 RC = &LoongArch::LASX256RegClass;
7371 if (
TRI->getRegSizeInBits(*RC) > 128) {
7372 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7373 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7381 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
7382 : LoongArch::BSTRINS_W),
7386 .
addImm(256 / EleBits - 1)
7394 MI.eraseFromParent();
7401 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
7402 "Unexpected instruction");
7414 MI.eraseFromParent();
7421 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
7422 "Unexpected instruction");
7428 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
7438 MI.eraseFromParent();
7443 switch (
MI.getOpcode()) {
7446 case LoongArch::Select_GPR_Using_CC_GPR:
7482 if (
MI.getOperand(2).isReg())
7483 RHS =
MI.getOperand(2).getReg();
7484 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
7488 SelectDests.
insert(
MI.getOperand(0).getReg());
7492 SequenceMBBI !=
E; ++SequenceMBBI) {
7493 if (SequenceMBBI->isDebugInstr())
7496 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
7497 !SequenceMBBI->getOperand(2).isReg() ||
7498 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
7499 SequenceMBBI->getOperand(3).getImm() != CC ||
7500 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
7501 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
7503 LastSelectPseudo = &*SequenceMBBI;
7505 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
7508 if (SequenceMBBI->hasUnmodeledSideEffects() ||
7509 SequenceMBBI->mayLoadOrStore() ||
7510 SequenceMBBI->usesCustomInsertionHook())
7513 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
7528 F->insert(
I, IfFalseMBB);
7529 F->insert(
I, TailMBB);
7532 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
7538 TailMBB->
push_back(DebugInstr->removeFromParent());
7542 TailMBB->
splice(TailMBB->
end(), HeadMBB,
7552 if (
MI.getOperand(2).isImm())
7564 auto SelectMBBI =
MI.getIterator();
7565 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7567 while (SelectMBBI != SelectEnd) {
7568 auto Next = std::next(SelectMBBI);
7572 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7573 .
addReg(SelectMBBI->getOperand(4).getReg())
7575 .
addReg(SelectMBBI->getOperand(5).getReg())
7582 F->getProperties().resetNoPHIs();
7588 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7591 switch (
MI.getOpcode()) {
7594 case LoongArch::DIV_W:
7595 case LoongArch::DIV_WU:
7596 case LoongArch::MOD_W:
7597 case LoongArch::MOD_WU:
7598 case LoongArch::DIV_D:
7599 case LoongArch::DIV_DU:
7600 case LoongArch::MOD_D:
7601 case LoongArch::MOD_DU:
7604 case LoongArch::WRFCSR: {
7606 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7607 .
addReg(
MI.getOperand(1).getReg());
7608 MI.eraseFromParent();
7611 case LoongArch::RDFCSR: {
7612 MachineInstr *ReadFCSR =
7614 MI.getOperand(0).getReg())
7615 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
7617 MI.eraseFromParent();
7620 case LoongArch::Select_GPR_Using_CC_GPR:
7622 case LoongArch::BuildPairF64Pseudo:
7624 case LoongArch::SplitPairF64Pseudo:
7626 case LoongArch::PseudoVBZ:
7627 case LoongArch::PseudoVBZ_B:
7628 case LoongArch::PseudoVBZ_H:
7629 case LoongArch::PseudoVBZ_W:
7630 case LoongArch::PseudoVBZ_D:
7631 case LoongArch::PseudoVBNZ:
7632 case LoongArch::PseudoVBNZ_B:
7633 case LoongArch::PseudoVBNZ_H:
7634 case LoongArch::PseudoVBNZ_W:
7635 case LoongArch::PseudoVBNZ_D:
7636 case LoongArch::PseudoXVBZ:
7637 case LoongArch::PseudoXVBZ_B:
7638 case LoongArch::PseudoXVBZ_H:
7639 case LoongArch::PseudoXVBZ_W:
7640 case LoongArch::PseudoXVBZ_D:
7641 case LoongArch::PseudoXVBNZ:
7642 case LoongArch::PseudoXVBNZ_B:
7643 case LoongArch::PseudoXVBNZ_H:
7644 case LoongArch::PseudoXVBNZ_W:
7645 case LoongArch::PseudoXVBNZ_D:
7647 case LoongArch::PseudoXVINSGR2VR_B:
7648 case LoongArch::PseudoXVINSGR2VR_H:
7650 case LoongArch::PseudoCTPOP:
7652 case LoongArch::PseudoVMSKLTZ_B:
7653 case LoongArch::PseudoVMSKLTZ_H:
7654 case LoongArch::PseudoVMSKLTZ_W:
7655 case LoongArch::PseudoVMSKLTZ_D:
7656 case LoongArch::PseudoVMSKGEZ_B:
7657 case LoongArch::PseudoVMSKEQZ_B:
7658 case LoongArch::PseudoVMSKNEZ_B:
7659 case LoongArch::PseudoXVMSKLTZ_B:
7660 case LoongArch::PseudoXVMSKLTZ_H:
7661 case LoongArch::PseudoXVMSKLTZ_W:
7662 case LoongArch::PseudoXVMSKLTZ_D:
7663 case LoongArch::PseudoXVMSKGEZ_B:
7664 case LoongArch::PseudoXVMSKEQZ_B:
7665 case LoongArch::PseudoXVMSKNEZ_B:
7667 case TargetOpcode::STATEPOINT:
7673 MI.addOperand(*
MI.getMF(),
7675 LoongArch::R1,
true,
7678 if (!Subtarget.is64Bit())
7686 unsigned *
Fast)
const {
7687 if (!Subtarget.hasUAL())
7705 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7706 LoongArch::R10, LoongArch::R11};
7710 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7711 LoongArch::F6, LoongArch::F7};
7714 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7715 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7718 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7719 LoongArch::VR6, LoongArch::VR7};
7722 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7723 LoongArch::XR6, LoongArch::XR7};
7729 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7731 unsigned GRLenInBytes = GRLen / 8;
7742 State.AllocateStack(GRLenInBytes, StackAlign),
7745 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7756 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7764 unsigned ValNo,
MVT ValVT,
7767 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7768 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7769 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7774 if (IsRet && ValNo > 1)
7778 bool UseGPRForFloat =
true;
7788 UseGPRForFloat = ArgFlags.
isVarArg();
7801 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7804 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7805 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
7807 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7813 State.getPendingArgFlags();
7816 "PendingLocs and PendingArgFlags out of sync");
7820 UseGPRForFloat =
true;
7822 if (UseGPRForFloat && ValVT == MVT::f32) {
7825 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7828 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7831 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7873 PendingLocs.
size() <= 2) {
7874 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7879 PendingLocs.
clear();
7880 PendingArgFlags.
clear();
7887 unsigned StoreSizeBytes = GRLen / 8;
7890 if (ValVT == MVT::f32 && !UseGPRForFloat) {
7892 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
7896 UseGPRForFloat =
false;
7897 StoreSizeBytes = 16;
7898 StackAlign =
Align(16);
7901 UseGPRForFloat =
false;
7902 StoreSizeBytes = 32;
7903 StackAlign =
Align(32);
7909 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
7913 if (!PendingLocs.
empty()) {
7915 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7916 for (
auto &It : PendingLocs) {
7918 It.convertToReg(
Reg);
7923 PendingLocs.clear();
7924 PendingArgFlags.
clear();
7927 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7928 "Expected an GRLenVT at this stage");
7945void LoongArchTargetLowering::analyzeInputArgs(
7948 LoongArchCCAssignFn Fn)
const {
7950 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7951 MVT ArgVT =
Ins[i].VT;
7952 Type *ArgTy =
nullptr;
7954 ArgTy = FType->getReturnType();
7955 else if (Ins[i].isOrigArg())
7956 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7960 CCInfo, IsRet, ArgTy)) {
7961 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7968void LoongArchTargetLowering::analyzeOutputArgs(
7971 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7972 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7973 MVT ArgVT = Outs[i].VT;
7974 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7978 CCInfo, IsRet, OrigTy)) {
7979 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7998 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
8020 if (In.isOrigArg()) {
8025 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
8026 (
BitWidth < 32 && In.Flags.isZExt())) {
8076 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8089 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8093 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
8107 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
8109 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
8119 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8123 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8124 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8125 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8132 if (LocVT == MVT::f32) {
8135 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
8136 LoongArch::F26, LoongArch::F27};
8143 if (LocVT == MVT::f64) {
8146 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
8147 LoongArch::F30_64, LoongArch::F31_64};
8177 "GHC calling convention requires the F and D extensions");
8181 MVT GRLenVT = Subtarget.getGRLenVT();
8182 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
8184 std::vector<SDValue> OutChains;
8193 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
8195 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
8212 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
8213 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
8214 assert(ArgPartOffset == 0);
8215 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
8217 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
8241 int VaArgOffset, VarArgsSaveSize;
8245 if (ArgRegs.
size() == Idx) {
8247 VarArgsSaveSize = 0;
8249 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
8250 VaArgOffset = -VarArgsSaveSize;
8256 LoongArchFI->setVarArgsFrameIndex(FI);
8264 VarArgsSaveSize += GRLenInBytes;
8269 for (
unsigned I = Idx;
I < ArgRegs.
size();
8270 ++
I, VaArgOffset += GRLenInBytes) {
8271 const Register Reg = RegInfo.createVirtualRegister(RC);
8272 RegInfo.addLiveIn(ArgRegs[
I], Reg);
8280 ->setValue((
Value *)
nullptr);
8281 OutChains.push_back(Store);
8283 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
8288 if (!OutChains.empty()) {
8289 OutChains.push_back(Chain);
8304 if (
N->getNumValues() != 1)
8306 if (!
N->hasNUsesOfValue(1, 0))
8309 SDNode *Copy = *
N->user_begin();
8315 if (Copy->getGluedNode())
8319 bool HasRet =
false;
8321 if (
Node->getOpcode() != LoongArchISD::RET)
8329 Chain = Copy->getOperand(0);
8334bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
8338 auto CalleeCC = CLI.CallConv;
8339 auto &Outs = CLI.Outs;
8341 auto CallerCC = Caller.getCallingConv();
8348 for (
auto &VA : ArgLocs)
8354 auto IsCallerStructRet = Caller.hasStructRetAttr();
8355 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
8356 if (IsCallerStructRet || IsCalleeStructRet)
8360 for (
auto &Arg : Outs)
8361 if (Arg.Flags.isByVal())
8366 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
8367 if (CalleeCC != CallerCC) {
8368 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
8369 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
8395 MVT GRLenVT = Subtarget.getGRLenVT();
8407 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
8411 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
8417 "site marked musttail");
8424 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8426 if (!Flags.isByVal())
8430 unsigned Size = Flags.getByValSize();
8431 Align Alignment = Flags.getNonZeroByValAlign();
8438 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
8440 false,
nullptr, std::nullopt,
8452 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8455 SDValue ArgValue = OutVals[OutIdx];
8463 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
8464 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8476 if (!StackPtr.getNode())
8488 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8503 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8504 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8505 assert(ArgPartOffset == 0);
8510 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8511 SDValue PartValue = OutVals[OutIdx + 1];
8512 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8527 for (
const auto &Part : Parts) {
8528 SDValue PartValue = Part.first;
8529 SDValue PartOffset = Part.second;
8536 ArgValue = SpillSlot;
8542 if (Flags.isByVal())
8543 ArgValue = ByValArgs[j++];
8550 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8551 "for passing parameters");
8554 if (!StackPtr.getNode())
8567 if (!MemOpChains.
empty())
8573 for (
auto &Reg : RegsToPass) {
8574 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8596 Ops.push_back(Chain);
8597 Ops.push_back(Callee);
8601 for (
auto &Reg : RegsToPass)
8602 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8607 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8608 assert(Mask &&
"Missing call preserved mask for calling convention");
8614 Ops.push_back(Glue);
8623 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
8626 assert(Subtarget.is64Bit() &&
"Medium code model requires LA64");
8627 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
8630 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8631 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
8653 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8656 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8657 auto &VA = RVLocs[i];
8665 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8666 assert(VA.needsCustom());
8671 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
8672 RetValue, RetValue2);
8685 const Type *RetTy)
const {
8687 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8689 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8693 Outs[i].Flags, CCInfo,
true,
nullptr))
8719 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8720 SDValue Val = OutVals[OutIdx];
8729 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8733 Register RegHi = RVLocs[++i].getLocReg();
8758 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
8766 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
8769 if (SplatBitSize == 16 && !(V & 0x00FF)) {
8771 RequiredImm = (0b10101 << 8) | (V >> 8);
8772 return {
true, RequiredImm};
8773 }
else if (SplatBitSize == 32) {
8775 if (!(V & 0xFFFF00FF)) {
8776 RequiredImm = (0b10001 << 8) | (V >> 8);
8777 return {
true, RequiredImm};
8780 if (!(V & 0xFF00FFFF)) {
8781 RequiredImm = (0b10010 << 8) | (V >> 16);
8782 return {
true, RequiredImm};
8785 if (!(V & 0x00FFFFFF)) {
8786 RequiredImm = (0b10011 << 8) | (V >> 24);
8787 return {
true, RequiredImm};
8790 if ((V & 0xFFFF00FF) == 0xFF) {
8791 RequiredImm = (0b10110 << 8) | (V >> 8);
8792 return {
true, RequiredImm};
8795 if ((V & 0xFF00FFFF) == 0xFFFF) {
8796 RequiredImm = (0b10111 << 8) | (V >> 16);
8797 return {
true, RequiredImm};
8800 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
8802 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8803 return {
true, RequiredImm};
8805 }
else if (SplatBitSize == 64) {
8807 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
8808 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
8810 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8811 return {
true, RequiredImm};
8814 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
8815 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
8817 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
8818 return {
true, RequiredImm};
8821 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
8823 for (
int i = 0; i < 8; ++i) {
8825 if (
byte == 0 ||
byte == 0xFF)
8826 res |= ((
byte & 1) << i);
8833 auto [IsSame, Suffix] = sameBitsPreByte(V);
8835 RequiredImm = (0b11001 << 8) | Suffix;
8836 return {
true, RequiredImm};
8839 return {
false, RequiredImm};
8844 if (!Subtarget.hasExtLSX())
8847 if (VT == MVT::f32) {
8848 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8849 return (masked == 0x3e000000 || masked == 0x40000000);
8852 if (VT == MVT::f64) {
8853 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8854 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8860bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8861 bool ForCodeSize)
const {
8863 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8865 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8867 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8878bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8888 Type *Ty =
I->getOperand(0)->getType();
8890 unsigned Size = Ty->getIntegerBitWidth();
8906 EVT VT =
Y.getValueType();
8909 return Subtarget.hasExtLSX() && VT.
isInteger();
8921 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8922 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8923 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8924 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8926 Info.memVT = MVT::i32;
8927 Info.ptrVal =
I.getArgOperand(0);
8929 Info.align =
Align(4);
8946 "Unable to expand");
8947 unsigned MinWordSize = 4;
8959 Value *AlignedAddr = Builder.CreateIntrinsic(
8960 Intrinsic::ptrmask, {PtrTy, IntTy},
8961 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8964 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
8965 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8966 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
8967 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8968 Value *Mask = Builder.CreateShl(
8969 ConstantInt::get(WordType,
8972 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
8973 Value *ValOperand_Shifted =
8974 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
8975 ShiftAmt,
"ValOperand_Shifted");
8978 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8980 NewOperand = ValOperand_Shifted;
8983 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
8986 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
8987 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
9006 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
9014 if (Subtarget.hasLAMCAS()) {
9036 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
9038 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
9040 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
9042 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
9044 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
9046 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
9048 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
9050 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
9060 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
9062 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
9064 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
9066 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
9068 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
9070 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
9072 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
9074 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
9086 if (Subtarget.hasLAMCAS())
9098 unsigned GRLen = Subtarget.getGRLen();
9100 Value *FailureOrdering =
9101 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9102 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9104 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9105 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9106 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9107 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9110 Value *Result = Builder.CreateIntrinsic(
9111 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
9113 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9129 Builder.CreateNot(Mask,
"Inv_Mask"),
9136 unsigned GRLen = Subtarget.getGRLen();
9145 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
9146 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9147 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
9163 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
9164 Result = Builder.CreateCall(LlwOpScwLoop,
9165 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
9168 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
9172 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9195 const Constant *PersonalityFn)
const {
9196 return LoongArch::R4;
9200 const Constant *PersonalityFn)
const {
9201 return LoongArch::R5;
9212 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
9213 return RefinementSteps;
9218 int &RefinementSteps,
9219 bool &UseOneConstNR,
9220 bool Reciprocal)
const {
9221 if (Subtarget.hasFrecipe()) {
9225 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9226 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9227 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9228 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9229 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9248 int &RefinementSteps)
const {
9249 if (Subtarget.hasFrecipe()) {
9253 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9254 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9255 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9256 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9257 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9262 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
9274LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
9294 if (Constraint.
size() == 1) {
9295 switch (Constraint[0]) {
9311 if (Constraint ==
"ZC" || Constraint ==
"ZB")
9320 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
9327std::pair<unsigned, const TargetRegisterClass *>
9328LoongArchTargetLowering::getRegForInlineAsmConstraint(
9332 if (Constraint.
size() == 1) {
9333 switch (Constraint[0]) {
9338 return std::make_pair(0U, &LoongArch::GPRRegClass);
9340 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
9342 if (Subtarget.hasBasicF() && VT == MVT::f32)
9343 return std::make_pair(0U, &LoongArch::FPR32RegClass);
9344 if (Subtarget.hasBasicD() && VT == MVT::f64)
9345 return std::make_pair(0U, &LoongArch::FPR64RegClass);
9346 if (Subtarget.hasExtLSX() &&
9347 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
9348 return std::make_pair(0U, &LoongArch::LSX128RegClass);
9349 if (Subtarget.hasExtLASX() &&
9350 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
9351 return std::make_pair(0U, &LoongArch::LASX256RegClass);
9371 bool IsFP = Constraint[2] ==
'f';
9372 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
9373 std::pair<unsigned, const TargetRegisterClass *>
R;
9378 unsigned RegNo =
R.first;
9379 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
9380 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
9381 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
9382 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
9392void LoongArchTargetLowering::LowerAsmOperandForConstraint(
9396 if (Constraint.
size() == 1) {
9397 switch (Constraint[0]) {
9401 uint64_t CVal =
C->getSExtValue();
9404 Subtarget.getGRLenVT()));
9410 uint64_t CVal =
C->getSExtValue();
9413 Subtarget.getGRLenVT()));
9419 if (
C->getZExtValue() == 0)
9426 uint64_t CVal =
C->getZExtValue();
9439#define GET_REGISTER_MATCHER
9440#include "LoongArchGenAsmMatcher.inc"
9446 std::string NewRegName = Name.second.str();
9452 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
9453 if (!ReservedRegs.
test(Reg))
9470 const APInt &Imm = ConstNode->getAPIntValue();
9472 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
9473 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
9476 if (ConstNode->hasOneUse() &&
9477 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
9478 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
9484 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
9485 unsigned Shifts = Imm.countr_zero();
9491 APInt ImmPop = Imm.ashr(Shifts);
9492 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
9496 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
9497 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
9498 (ImmSmall - Imm).isPowerOf2())
9508 Type *Ty,
unsigned AS,
9563 EVT MemVT = LD->getMemoryVT();
9564 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
9575 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
9584 if (
Y.getValueType().isVector())
9596 Type *Ty,
bool IsSigned)
const {
9597 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
9606 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
9607 Type.getSizeInBits() < Subtarget.getGRLen()))
9617 Align &PrefAlign)
const {
9621 if (Subtarget.is64Bit()) {
9623 PrefAlign =
Align(8);
9626 PrefAlign =
Align(4);
9641bool LoongArchTargetLowering::splitValueIntoRegisterParts(
9643 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
9644 bool IsABIRegCopy = CC.has_value();
9647 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9648 PartVT == MVT::f32) {
9651 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
9655 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f32, Val);
9663SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
9665 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
9666 bool IsABIRegCopy = CC.has_value();
9668 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9669 PartVT == MVT::f32) {
9673 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
9675 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
9686 if (VT == MVT::f16 && Subtarget.hasBasicF())
9692unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
9695 if (VT == MVT::f16 && Subtarget.hasBasicF())
9704 unsigned Depth)
const {
9705 EVT VT =
Op.getValueType();
9707 unsigned Opc =
Op.getOpcode();
9711 case LoongArchISD::VMSKLTZ:
9712 case LoongArchISD::XVMSKLTZ: {
9714 MVT SrcVT = Src.getSimpleValueType();
9719 if (OriginalDemandedBits.
countr_zero() >= NumElts)
9723 APInt KnownUndef, KnownZero;
9739 if (KnownSrc.
One[SrcBits - 1])
9741 else if (KnownSrc.
Zero[SrcBits - 1])
9746 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
9753 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
9776 unsigned Index)
const {
9785 unsigned Index)
const {
9789 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 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.
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)
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 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 getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &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 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.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
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.
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)