32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
248 if (Subtarget.is64Bit())
251 if (!Subtarget.hasBasicD()) {
253 if (Subtarget.is64Bit()) {
262 if (Subtarget.hasBasicD()) {
295 if (Subtarget.is64Bit())
301 if (Subtarget.hasExtLSX()) {
316 for (
MVT VT : LSXVTs) {
330 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
354 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
356 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
358 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
386 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
387 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
402 if (Subtarget.hasExtLASX()) {
403 for (
MVT VT : LASXVTs) {
418 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
443 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
445 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
447 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
451 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
471 if (Subtarget.hasBasicF()) {
482 if (Subtarget.hasExtLSX()) {
488 if (Subtarget.hasExtLASX()) {
514 if (Subtarget.hasLAMCAS())
517 if (Subtarget.hasSCQ()) {
537 switch (
Op.getOpcode()) {
539 return lowerATOMIC_FENCE(
Op, DAG);
541 return lowerEH_DWARF_CFA(
Op, DAG);
543 return lowerGlobalAddress(
Op, DAG);
545 return lowerGlobalTLSAddress(
Op, DAG);
547 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
549 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
551 return lowerINTRINSIC_VOID(
Op, DAG);
553 return lowerBlockAddress(
Op, DAG);
555 return lowerJumpTable(
Op, DAG);
557 return lowerShiftLeftParts(
Op, DAG);
559 return lowerShiftRightParts(
Op, DAG,
true);
561 return lowerShiftRightParts(
Op, DAG,
false);
563 return lowerConstantPool(
Op, DAG);
565 return lowerFP_TO_SINT(
Op, DAG);
567 return lowerBITCAST(
Op, DAG);
569 return lowerUINT_TO_FP(
Op, DAG);
571 return lowerSINT_TO_FP(
Op, DAG);
573 return lowerVASTART(
Op, DAG);
575 return lowerFRAMEADDR(
Op, DAG);
577 return lowerRETURNADDR(
Op, DAG);
579 return lowerWRITE_REGISTER(
Op, DAG);
581 return lowerINSERT_VECTOR_ELT(
Op, DAG);
583 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
585 return lowerBUILD_VECTOR(
Op, DAG);
587 return lowerCONCAT_VECTORS(
Op, DAG);
589 return lowerVECTOR_SHUFFLE(
Op, DAG);
591 return lowerBITREVERSE(
Op, DAG);
593 return lowerSCALAR_TO_VECTOR(
Op, DAG);
595 return lowerPREFETCH(
Op, DAG);
597 return lowerSELECT(
Op, DAG);
599 return lowerBRCOND(
Op, DAG);
601 return lowerFP_TO_FP16(
Op, DAG);
603 return lowerFP16_TO_FP(
Op, DAG);
605 return lowerFP_TO_BF16(
Op, DAG);
607 return lowerBF16_TO_FP(
Op, DAG);
609 return lowerVECREDUCE_ADD(
Op, DAG);
612 return lowerRotate(
Op, DAG);
620 return lowerVECREDUCE(
Op, DAG);
622 return lowerConstantFP(
Op, DAG);
624 return lowerSETCC(
Op, DAG);
633 EVT VT = V.getValueType();
639 return V.getOperand(0);
643 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
645 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
655 if (!V->isOnlyUserOf(SplatValue.getNode()))
659 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
667 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
684 EVT VT =
Op.getValueType();
689 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
690 (VT == MVT::f64 && Subtarget.hasBasicD()));
707 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
717 if (Subtarget.is64Bit())
719 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
720 : LoongArchISD::MOVGR2FR_W,
724 if (Subtarget.is64Bit()) {
726 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
730 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
742 EVT ResultVT =
Op.getValueType();
743 EVT OperandVT =
Op.getOperand(0).getValueType();
748 if (ResultVT == SetCCResultVT)
751 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
752 "SETCC operands must have the same type!");
756 Op.getOperand(1),
Op.getOperand(2));
758 if (ResultVT.
bitsGT(SetCCResultVT))
760 else if (ResultVT.
bitsLT(SetCCResultVT))
778 MVT OpVT =
Op.getSimpleValueType();
785 unsigned LegalVecSize = 128;
786 bool isLASX256Vector =
796 if (isLASX256Vector) {
801 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
804 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
807 if (isLASX256Vector) {
833 MVT OpVT =
Op.getSimpleValueType();
846 MVT GRLenVT = Subtarget.getGRLenVT();
848 for (
int i = NumEles; i > 1; i /= 2) {
851 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
860 unsigned IsData =
Op.getConstantOperandVal(4);
865 return Op.getOperand(0);
872 MVT VT =
Op.getSimpleValueType();
878 unsigned Opcode =
Op.getOpcode();
881 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
887 CstSplatValue =
C->getAPIntValue();
896 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
900 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
916 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
932 if (
LHS == LHS2 &&
RHS == RHS2) {
937 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
953 MVT VT =
N->getSimpleValueType(0);
984 if (~TrueVal == FalseVal) {
1024 unsigned SelOpNo = 0;
1034 unsigned ConstSelOpNo = 1;
1035 unsigned OtherSelOpNo = 2;
1042 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1047 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1053 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1055 std::swap(NewConstOps[0], NewConstOps[1]);
1067 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1069 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1072 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1073 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1093 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1107 int64_t
C = RHSC->getSExtValue();
1150 MVT VT =
Op.getSimpleValueType();
1151 MVT GRLenVT = Subtarget.getGRLenVT();
1156 if (
Op.hasOneUse()) {
1157 unsigned UseOpc =
Op->user_begin()->getOpcode();
1159 SDNode *BinOp = *
Op->user_begin();
1166 return lowerSELECT(NewSel, DAG);
1183 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1206 if (TrueVal - 1 == FalseVal)
1208 if (TrueVal + 1 == FalseVal)
1215 RHS == TrueV &&
LHS == FalseV) {
1240 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1247 MVT GRLenVT = Subtarget.getGRLenVT();
1258 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1259 Op.getOperand(0),
LHS,
RHS, TargetCC,
1262 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1263 Op.getOperand(0), CondV,
Op.getOperand(2));
1267 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1273LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1276 MVT OpVT =
Op.getSimpleValueType();
1287 EVT ResTy =
Op->getValueType(0);
1292 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1302 for (
unsigned int i = 0; i < NewEltNum; i++) {
1305 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1306 ? (
unsigned)LoongArchISD::BITREV_8B
1324 for (
unsigned int i = 0; i < NewEltNum; i++)
1325 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1326 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1344 if (EltBits > 32 || EltBits == 1)
1372 int MaskOffset,
const APInt &Zeroable) {
1373 int Size = Mask.size();
1374 unsigned SizeInBits =
Size * ScalarSizeInBits;
1376 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1377 for (
int i = 0; i <
Size; i += Scale)
1378 for (
int j = 0; j < Shift; ++j)
1379 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1387 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1388 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1393 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1394 for (
int i = 0; i !=
Size; i += Scale) {
1395 unsigned Pos =
Left ? i + Shift : i;
1396 unsigned Low =
Left ? i : i + Shift;
1397 unsigned Len = Scale - Shift;
1402 int ShiftEltBits = ScalarSizeInBits * Scale;
1403 bool ByteShift = ShiftEltBits > 64;
1404 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1405 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1406 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1410 Scale = ByteShift ? Scale / 2 : Scale;
1416 return (
int)ShiftAmt;
1419 unsigned MaxWidth = 128;
1420 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1421 for (
int Shift = 1; Shift != Scale; ++Shift)
1422 for (
bool Left : {
true,
false})
1423 if (CheckZeros(Shift, Scale,
Left)) {
1424 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1449 const APInt &Zeroable) {
1450 int Size = Mask.size();
1464 Mask,
Size, Zeroable);
1472 "Illegal integer vector type");
1481template <
typename ValType>
1484 unsigned CheckStride,
1486 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1490 if (*
I != -1 && *
I != ExpectedIndex)
1492 ExpectedIndex += ExpectedIndexStride;
1496 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1508 int Size = Mask.size();
1518 int ScalarSizeInBits = VectorSizeInBits /
Size;
1519 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1520 (void)ScalarSizeInBits;
1522 for (
int i = 0; i <
Size; ++i) {
1528 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1545 RepeatedMask.
assign(LaneSize, -1);
1546 int Size = Mask.size();
1547 for (
int i = 0; i <
Size; ++i) {
1548 assert(Mask[i] == -1 || Mask[i] >= 0);
1551 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1558 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1559 if (RepeatedMask[i % LaneSize] < 0)
1561 RepeatedMask[i % LaneSize] = LocalM;
1562 else if (RepeatedMask[i % LaneSize] != LocalM)
1579 int NumElts = RepeatedMask.
size();
1581 int Scale = 16 / NumElts;
1583 for (
int i = 0; i < NumElts; ++i) {
1584 int M = RepeatedMask[i];
1585 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1586 "Unexpected mask index.");
1591 int StartIdx = i - (M % NumElts);
1598 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1601 Rotation = CandidateRotation;
1602 else if (Rotation != CandidateRotation)
1606 SDValue MaskV = M < NumElts ? V1 : V2;
1617 else if (TargetV != MaskV)
1622 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1623 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1632 return Rotation * Scale;
1651 if (ByteRotation <= 0)
1658 int LoByteShift = 16 - ByteRotation;
1659 int HiByteShift = ByteRotation;
1682 const APInt &Zeroable) {
1696 for (
int i = 0; i < NumElements; i++) {
1700 if (i % Scale != 0) {
1711 SDValue V = M < NumElements ? V1 : V2;
1712 M = M % NumElements;
1715 Offset = M - (i / Scale);
1718 if (
Offset % (NumElements / Scale))
1720 }
else if (InputV != V)
1723 if (M != (
Offset + (i / Scale)))
1733 unsigned VilVLoHi = LoongArchISD::VILVL;
1734 if (
Offset >= (NumElements / 2)) {
1735 VilVLoHi = LoongArchISD::VILVH;
1736 Offset -= (NumElements / 2);
1743 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1747 }
while (Scale > 1);
1753 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1754 NumExtElements *= 2) {
1774 int SplatIndex = -1;
1775 for (
const auto &M : Mask) {
1782 if (SplatIndex == -1)
1785 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1787 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
1817 unsigned SubVecSize = 4;
1818 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1821 int SubMask[4] = {-1, -1, -1, -1};
1822 for (
unsigned i = 0; i < SubVecSize; ++i) {
1823 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1829 M -= 4 * (j / SubVecSize);
1830 if (M < 0 || M >= 4)
1836 if (SubMask[i] == -1)
1840 else if (M != -1 && M != SubMask[i])
1847 for (
int i = SubVecSize - 1; i >= 0; --i) {
1860 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1861 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
1864 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
1882 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
1891 for (
int i = 0; i < WidenNumElts; ++i)
1892 WidenMask[i] = WidenNumElts - 1 - i;
1900 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
1924 const auto &Begin = Mask.begin();
1925 const auto &End = Mask.end();
1926 SDValue OriV1 = V1, OriV2 = V2;
1942 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
1964 const auto &Begin = Mask.begin();
1965 const auto &End = Mask.end();
1966 SDValue OriV1 = V1, OriV2 = V2;
1982 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2005 const auto &Begin = Mask.begin();
2006 const auto &End = Mask.end();
2007 unsigned HalfSize = Mask.size() / 2;
2008 SDValue OriV1 = V1, OriV2 = V2;
2025 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2048 const auto &Begin = Mask.begin();
2049 const auto &End = Mask.end();
2050 SDValue OriV1 = V1, OriV2 = V2;
2066 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2088 const auto &Begin = Mask.begin();
2089 const auto &Mid = Mask.begin() + Mask.size() / 2;
2090 const auto &End = Mask.end();
2091 SDValue OriV1 = V1, OriV2 = V2;
2108 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2130 const auto &Begin = Mask.begin();
2131 const auto &Mid = Mask.begin() + Mask.size() / 2;
2132 const auto &End = Mask.end();
2133 SDValue OriV1 = V1, OriV2 = V2;
2149 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2175 if (Mask.size() != NumElts)
2178 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2181 for (
unsigned i = 0; i < NumElts; ++i) {
2184 if (Mask[i] !=
int(
Base + i)) {
2197 int DiffMask = Mask[DiffPos];
2198 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2204 if (
unsigned(DiffMask) < NumElts) {
2209 SrcIdx =
unsigned(DiffMask) - NumElts;
2225 if (
SDValue Result = tryLowerToExtrAndIns(0))
2227 return tryLowerToExtrAndIns(NumElts);
2253 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2266 "Vector type is unsupported for lsx!");
2268 "Two operands have different types!");
2270 "Unexpected mask size for shuffle!");
2271 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2273 APInt KnownUndef, KnownZero;
2275 APInt Zeroable = KnownUndef | KnownZero;
2345 int SplatIndex = -1;
2346 for (
const auto &M : Mask) {
2353 if (SplatIndex == -1)
2356 const auto &Begin = Mask.begin();
2357 const auto &End = Mask.end();
2358 int HalfSize = Mask.size() / 2;
2360 if (SplatIndex >= HalfSize)
2363 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2367 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2381 if (Mask.size() <= 4)
2392 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2395 unsigned MaskImm = 0;
2396 for (
unsigned i = 0; i < Mask.size(); ++i) {
2399 MaskImm |= Mask[i] << (i * 2);
2402 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2411 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2415 unsigned HalfSize = NumElts / 2;
2416 bool FrontLo =
true, FrontHi =
true;
2417 bool BackLo =
true, BackHi =
true;
2419 auto inRange = [](
int val,
int low,
int high) {
2420 return (val == -1) || (val >= low && val < high);
2423 for (
unsigned i = 0; i < HalfSize; ++i) {
2424 int Fronti = Mask[i];
2425 int Backi = Mask[i + HalfSize];
2427 FrontLo &=
inRange(Fronti, 0, HalfSize);
2428 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2429 BackLo &=
inRange(Backi, 0, HalfSize);
2430 BackHi &=
inRange(Backi, HalfSize, NumElts);
2436 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2441 for (
unsigned i = 0; i < NumElts; ++i)
2446 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2468 const auto &Begin = Mask.begin();
2469 const auto &End = Mask.end();
2470 unsigned HalfSize = Mask.size() / 2;
2471 unsigned LeftSize = HalfSize / 2;
2472 SDValue OriV1 = V1, OriV2 = V2;
2479 Mask.size() + HalfSize - LeftSize, 1) &&
2481 Mask.size() + HalfSize + LeftSize, 1))
2492 Mask.size() + HalfSize - LeftSize, 1) &&
2494 Mask.size() + HalfSize + LeftSize, 1))
2499 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2507 const auto &Begin = Mask.begin();
2508 const auto &End = Mask.end();
2509 unsigned HalfSize = Mask.size() / 2;
2510 SDValue OriV1 = V1, OriV2 = V2;
2517 Mask.size() + HalfSize, 1))
2528 Mask.size() + HalfSize, 1))
2533 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2541 const auto &Begin = Mask.begin();
2542 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2543 const auto &Mid = Mask.begin() + Mask.size() / 2;
2544 const auto &RightMid = Mask.end() - Mask.size() / 4;
2545 const auto &End = Mask.end();
2546 unsigned HalfSize = Mask.size() / 2;
2547 SDValue OriV1 = V1, OriV2 = V2;
2568 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2576 const auto &Begin = Mask.begin();
2577 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2578 const auto &Mid = Mask.begin() + Mask.size() / 2;
2579 const auto &RightMid = Mask.end() - Mask.size() / 4;
2580 const auto &End = Mask.end();
2581 unsigned HalfSize = Mask.size() / 2;
2582 SDValue OriV1 = V1, OriV2 = V2;
2604 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2613 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2618 int MaskSize = Mask.size();
2624 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2626 for (
int i = 0; i < MaskSize; ++i) {
2627 if (Mask[i] ==
Base + i || Mask[i] == -1)
2629 if (Mask[i] != Replaced)
2640 int Idx = checkReplaceOne(0, MaskSize);
2642 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
2646 Idx = checkReplaceOne(MaskSize, 0);
2648 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
2659 int MaskSize = Mask.size();
2660 int HalfSize = Mask.size() / 2;
2661 const auto &Begin = Mask.begin();
2662 const auto &Mid = Mask.begin() + HalfSize;
2663 const auto &End = Mask.end();
2675 for (
auto it = Begin; it < Mid; it++) {
2678 else if ((*it >= 0 && *it < HalfSize) ||
2679 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2680 int M = *it < HalfSize ? *it : *it - HalfSize;
2685 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2687 for (
auto it = Mid; it < End; it++) {
2690 else if ((*it >= HalfSize && *it < MaskSize) ||
2691 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2692 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2697 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2701 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2729 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2731 int MaskSize = Mask.size();
2732 int HalfSize = Mask.size() / 2;
2735 HalfMaskType preMask =
None, postMask =
None;
2737 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2738 return M < 0 || (M >= 0 && M < HalfSize) ||
2739 (M >= MaskSize && M < MaskSize + HalfSize);
2741 preMask = HighLaneTy;
2742 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2743 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2744 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2746 preMask = LowLaneTy;
2748 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2749 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2750 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2752 postMask = LowLaneTy;
2753 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2754 return M < 0 || (M >= 0 && M < HalfSize) ||
2755 (M >= MaskSize && M < MaskSize + HalfSize);
2757 postMask = HighLaneTy;
2765 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2768 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2770 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2776 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2781 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2782 *it = *it < 0 ? *it : *it - HalfSize;
2784 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2785 *it = *it < 0 ? *it : *it + HalfSize;
2787 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2789 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2795 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2800 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2801 *it = *it < 0 ? *it : *it - HalfSize;
2803 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2805 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
2811 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
2816 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2817 *it = *it < 0 ? *it : *it + HalfSize;
2842 int Size = Mask.size();
2843 int LaneSize =
Size / 2;
2845 bool LaneCrossing[2] = {
false,
false};
2846 for (
int i = 0; i <
Size; ++i)
2847 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2848 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2851 if (!LaneCrossing[0] && !LaneCrossing[1])
2855 InLaneMask.
assign(Mask.begin(), Mask.end());
2856 for (
int i = 0; i <
Size; ++i) {
2857 int &M = InLaneMask[i];
2860 if (((M %
Size) / LaneSize) != (i / LaneSize))
2861 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2866 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2881 "Vector type is unsupported for lasx!");
2883 "Two operands have different types!");
2885 "Unexpected mask size for shuffle!");
2886 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2887 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2889 APInt KnownUndef, KnownZero;
2891 APInt Zeroable = KnownUndef | KnownZero;
2968 ArrayRef<int> OrigMask = SVOp->
getMask();
2971 MVT VT =
Op.getSimpleValueType();
2975 bool V1IsUndef = V1.
isUndef();
2976 bool V2IsUndef = V2.
isUndef();
2977 if (V1IsUndef && V2IsUndef)
2990 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2991 SmallVector<int, 8> NewMask(OrigMask);
2992 for (
int &M : NewMask)
2993 if (M >= NumElements)
2999 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3000 (void)MaskUpperLimit;
3002 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3003 "Out of bounds shuffle index");
3025 std::tie(Res, Chain) =
3026 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3027 if (Subtarget.is64Bit())
3028 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3040 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3044 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3045 CallOptions,
DL, Chain);
3051 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3057 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3058 if (Subtarget.is64Bit())
3059 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3065 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3066 MVT VT =
Op.getSimpleValueType();
3071 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3092 "Unsupported vector type for broadcast.");
3095 bool IsIdeneity =
true;
3097 for (
int i = 0; i !=
NumOps; i++) {
3099 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3111 auto ExtType = LN->getExtensionType();
3116 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3121 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3139 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3153 EVT ResTy,
unsigned first) {
3156 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3159 Node->op_begin() + first + NumElts);
3168 MVT VT =
Node->getSimpleValueType(0);
3169 EVT ResTy =
Op->getValueType(0);
3172 APInt SplatValue, SplatUndef;
3173 unsigned SplatBitSize;
3176 bool UseSameConstant =
true;
3181 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3182 (!Subtarget.hasExtLASX() || !Is256Vec))
3188 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3190 SplatBitSize <= 64) {
3192 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3196 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3203 if ((Is128Vec && ResTy == MVT::v4i32) ||
3204 (Is256Vec && ResTy == MVT::v8i32))
3210 switch (SplatBitSize) {
3214 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3217 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3220 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3223 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3231 if (ViaVecTy != ResTy)
3240 for (
unsigned i = 0; i < NumElts; ++i) {
3245 ConstantValue = Opi;
3246 else if (ConstantValue != Opi)
3247 UseSameConstant =
false;
3252 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3254 for (
unsigned i = 0; i < NumElts; ++i) {
3272 BitVector UndefElements;
3273 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3274 UndefElements.
count() == 0) {
3278 EVT FillTy = Is256Vec
3284 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3287 unsigned SplatLen = NumElts / SeqLen;
3293 if (SplatEltTy == MVT::i128)
3294 SplatTy = MVT::v4i64;
3302 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3303 : LoongArchISD::XVREPLVE0,
3304 DL, SplatTy, SrcVec);
3306 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3319 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3320 ResTy == MVT::v4f64) {
3321 unsigned NonUndefCount = 0;
3322 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3323 if (!
Node->getOperand(i).isUndef()) {
3325 if (NonUndefCount > 1)
3329 if (NonUndefCount == 1)
3342 VecTy, NumElts / 2);
3353 MVT ResVT =
Op.getSimpleValueType();
3357 unsigned NumFreezeUndef = 0;
3358 unsigned NumZero = 0;
3359 unsigned NumNonZero = 0;
3360 unsigned NonZeros = 0;
3361 SmallSet<SDValue, 4> Undefs;
3362 for (
unsigned i = 0; i != NumOperands; ++i) {
3377 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3384 if (NumNonZero > 2) {
3388 Ops.slice(0, NumOperands / 2));
3390 Ops.slice(NumOperands / 2));
3403 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3405 for (
unsigned i = 0; i != NumOperands; ++i) {
3406 if ((NonZeros & (1 << i)) == 0)
3417LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3419 MVT EltVT =
Op.getSimpleValueType();
3424 MVT GRLenVT = Subtarget.getGRLenVT();
3452 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3456 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3458 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3467 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3476LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3478 MVT VT =
Op.getSimpleValueType();
3501 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3503 for (
unsigned i = 0; i < NumElts; ++i) {
3511 for (
unsigned i = 0; i < NumElts; ++i) {
3520 for (
unsigned i = 0; i < NumElts; ++i)
3552 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3554 "On LA64, only 64-bit registers can be written.");
3555 return Op.getOperand(0);
3558 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3560 "On LA32, only 32-bit registers can be written.");
3561 return Op.getOperand(0);
3571 "be a constant integer");
3577 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3578 EVT VT =
Op.getValueType();
3581 unsigned Depth =
Op.getConstantOperandVal(0);
3582 int GRLenInBytes = Subtarget.getGRLen() / 8;
3585 int Offset = -(GRLenInBytes * 2);
3597 if (
Op.getConstantOperandVal(0) != 0) {
3599 "return address can only be determined for the current frame");
3605 MVT GRLenVT = Subtarget.getGRLenVT();
3617 auto Size = Subtarget.getGRLen() / 8;
3625 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3635 MachinePointerInfo(SV));
3640 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3641 !Subtarget.hasBasicD() &&
"unexpected target features");
3647 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3651 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
3661 EVT RetVT =
Op.getValueType();
3667 std::tie(Result, Chain) =
3674 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3675 !Subtarget.hasBasicD() &&
"unexpected target features");
3686 EVT RetVT =
Op.getValueType();
3692 std::tie(Result, Chain) =
3701 EVT VT =
Op.getValueType();
3705 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3706 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3708 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
3710 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3713 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
3727 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3728 !Subtarget.hasBasicD()) {
3730 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
3752 N->getOffset(), Flags);
3760template <
class NodeTy>
3763 bool IsLocal)
const {
3774 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3855 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3857 const GlobalValue *GV =
N->getGlobal();
3869 unsigned Opc,
bool UseGOT,
3873 MVT GRLenVT = Subtarget.getGRLenVT();
3887 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3925 Args.emplace_back(Load, CallTy);
3928 TargetLowering::CallLoweringInfo CLI(DAG);
3943 const GlobalValue *GV =
N->getGlobal();
3957LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3964 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3967 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3980 return getDynamicTLSAddr(
N, DAG,
3981 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3982 : LoongArch::PseudoLA_TLS_GD,
3989 return getDynamicTLSAddr(
N, DAG,
3990 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3991 : LoongArch::PseudoLA_TLS_LD,
3996 return getStaticTLSAddr(
N, DAG,
3997 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3998 : LoongArch::PseudoLA_TLS_IE,
4005 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4009 return getTLSDescAddr(
N, DAG,
4010 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4011 : LoongArch::PseudoLA_TLS_DESC,
4015template <
unsigned N>
4020 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4021 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4023 ": argument out of range.");
4030LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4032 switch (
Op.getConstantOperandVal(0)) {
4035 case Intrinsic::thread_pointer: {
4039 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4040 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4041 case Intrinsic::loongarch_lsx_vreplvei_d:
4042 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4044 case Intrinsic::loongarch_lsx_vreplvei_w:
4045 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4046 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4047 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4048 case Intrinsic::loongarch_lasx_xvpickve_d:
4049 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4051 case Intrinsic::loongarch_lasx_xvinsve0_d:
4053 case Intrinsic::loongarch_lsx_vsat_b:
4054 case Intrinsic::loongarch_lsx_vsat_bu:
4055 case Intrinsic::loongarch_lsx_vrotri_b:
4056 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4057 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4058 case Intrinsic::loongarch_lsx_vsrlri_b:
4059 case Intrinsic::loongarch_lsx_vsrari_b:
4060 case Intrinsic::loongarch_lsx_vreplvei_h:
4061 case Intrinsic::loongarch_lasx_xvsat_b:
4062 case Intrinsic::loongarch_lasx_xvsat_bu:
4063 case Intrinsic::loongarch_lasx_xvrotri_b:
4064 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4065 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4066 case Intrinsic::loongarch_lasx_xvsrlri_b:
4067 case Intrinsic::loongarch_lasx_xvsrari_b:
4068 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4069 case Intrinsic::loongarch_lasx_xvpickve_w:
4070 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4072 case Intrinsic::loongarch_lasx_xvinsve0_w:
4074 case Intrinsic::loongarch_lsx_vsat_h:
4075 case Intrinsic::loongarch_lsx_vsat_hu:
4076 case Intrinsic::loongarch_lsx_vrotri_h:
4077 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4078 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4079 case Intrinsic::loongarch_lsx_vsrlri_h:
4080 case Intrinsic::loongarch_lsx_vsrari_h:
4081 case Intrinsic::loongarch_lsx_vreplvei_b:
4082 case Intrinsic::loongarch_lasx_xvsat_h:
4083 case Intrinsic::loongarch_lasx_xvsat_hu:
4084 case Intrinsic::loongarch_lasx_xvrotri_h:
4085 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4086 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4087 case Intrinsic::loongarch_lasx_xvsrlri_h:
4088 case Intrinsic::loongarch_lasx_xvsrari_h:
4089 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4091 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4092 case Intrinsic::loongarch_lsx_vsrani_b_h:
4093 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4094 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4095 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4096 case Intrinsic::loongarch_lsx_vssrani_b_h:
4097 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4098 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4099 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4100 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4101 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4102 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4103 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4104 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4105 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4106 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4107 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4108 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4109 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4110 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4111 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4112 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4113 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4114 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4116 case Intrinsic::loongarch_lsx_vsat_w:
4117 case Intrinsic::loongarch_lsx_vsat_wu:
4118 case Intrinsic::loongarch_lsx_vrotri_w:
4119 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4120 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4121 case Intrinsic::loongarch_lsx_vsrlri_w:
4122 case Intrinsic::loongarch_lsx_vsrari_w:
4123 case Intrinsic::loongarch_lsx_vslei_bu:
4124 case Intrinsic::loongarch_lsx_vslei_hu:
4125 case Intrinsic::loongarch_lsx_vslei_wu:
4126 case Intrinsic::loongarch_lsx_vslei_du:
4127 case Intrinsic::loongarch_lsx_vslti_bu:
4128 case Intrinsic::loongarch_lsx_vslti_hu:
4129 case Intrinsic::loongarch_lsx_vslti_wu:
4130 case Intrinsic::loongarch_lsx_vslti_du:
4131 case Intrinsic::loongarch_lsx_vbsll_v:
4132 case Intrinsic::loongarch_lsx_vbsrl_v:
4133 case Intrinsic::loongarch_lasx_xvsat_w:
4134 case Intrinsic::loongarch_lasx_xvsat_wu:
4135 case Intrinsic::loongarch_lasx_xvrotri_w:
4136 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4137 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4138 case Intrinsic::loongarch_lasx_xvsrlri_w:
4139 case Intrinsic::loongarch_lasx_xvsrari_w:
4140 case Intrinsic::loongarch_lasx_xvslei_bu:
4141 case Intrinsic::loongarch_lasx_xvslei_hu:
4142 case Intrinsic::loongarch_lasx_xvslei_wu:
4143 case Intrinsic::loongarch_lasx_xvslei_du:
4144 case Intrinsic::loongarch_lasx_xvslti_bu:
4145 case Intrinsic::loongarch_lasx_xvslti_hu:
4146 case Intrinsic::loongarch_lasx_xvslti_wu:
4147 case Intrinsic::loongarch_lasx_xvslti_du:
4148 case Intrinsic::loongarch_lasx_xvbsll_v:
4149 case Intrinsic::loongarch_lasx_xvbsrl_v:
4151 case Intrinsic::loongarch_lsx_vseqi_b:
4152 case Intrinsic::loongarch_lsx_vseqi_h:
4153 case Intrinsic::loongarch_lsx_vseqi_w:
4154 case Intrinsic::loongarch_lsx_vseqi_d:
4155 case Intrinsic::loongarch_lsx_vslei_b:
4156 case Intrinsic::loongarch_lsx_vslei_h:
4157 case Intrinsic::loongarch_lsx_vslei_w:
4158 case Intrinsic::loongarch_lsx_vslei_d:
4159 case Intrinsic::loongarch_lsx_vslti_b:
4160 case Intrinsic::loongarch_lsx_vslti_h:
4161 case Intrinsic::loongarch_lsx_vslti_w:
4162 case Intrinsic::loongarch_lsx_vslti_d:
4163 case Intrinsic::loongarch_lasx_xvseqi_b:
4164 case Intrinsic::loongarch_lasx_xvseqi_h:
4165 case Intrinsic::loongarch_lasx_xvseqi_w:
4166 case Intrinsic::loongarch_lasx_xvseqi_d:
4167 case Intrinsic::loongarch_lasx_xvslei_b:
4168 case Intrinsic::loongarch_lasx_xvslei_h:
4169 case Intrinsic::loongarch_lasx_xvslei_w:
4170 case Intrinsic::loongarch_lasx_xvslei_d:
4171 case Intrinsic::loongarch_lasx_xvslti_b:
4172 case Intrinsic::loongarch_lasx_xvslti_h:
4173 case Intrinsic::loongarch_lasx_xvslti_w:
4174 case Intrinsic::loongarch_lasx_xvslti_d:
4176 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4177 case Intrinsic::loongarch_lsx_vsrani_h_w:
4178 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4179 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4180 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4181 case Intrinsic::loongarch_lsx_vssrani_h_w:
4182 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4183 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4184 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4185 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4186 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4187 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4188 case Intrinsic::loongarch_lsx_vfrstpi_b:
4189 case Intrinsic::loongarch_lsx_vfrstpi_h:
4190 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4191 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4192 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4193 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4194 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4195 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4196 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4197 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4198 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4199 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4200 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4201 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4202 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4203 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4205 case Intrinsic::loongarch_lsx_vsat_d:
4206 case Intrinsic::loongarch_lsx_vsat_du:
4207 case Intrinsic::loongarch_lsx_vrotri_d:
4208 case Intrinsic::loongarch_lsx_vsrlri_d:
4209 case Intrinsic::loongarch_lsx_vsrari_d:
4210 case Intrinsic::loongarch_lasx_xvsat_d:
4211 case Intrinsic::loongarch_lasx_xvsat_du:
4212 case Intrinsic::loongarch_lasx_xvrotri_d:
4213 case Intrinsic::loongarch_lasx_xvsrlri_d:
4214 case Intrinsic::loongarch_lasx_xvsrari_d:
4216 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4217 case Intrinsic::loongarch_lsx_vsrani_w_d:
4218 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4219 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4220 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4221 case Intrinsic::loongarch_lsx_vssrani_w_d:
4222 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4223 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4224 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4225 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4226 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4227 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4228 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4229 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4230 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4231 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4232 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4233 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4234 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4235 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4236 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4237 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4238 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4239 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4241 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4242 case Intrinsic::loongarch_lsx_vsrani_d_q:
4243 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4244 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4245 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4246 case Intrinsic::loongarch_lsx_vssrani_d_q:
4247 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4248 case Intrinsic::loongarch_lsx_vssrani_du_q:
4249 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4250 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4251 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4252 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4253 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4254 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4255 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4256 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4257 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4258 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4259 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4260 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4261 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4262 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4263 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4264 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4266 case Intrinsic::loongarch_lsx_vnori_b:
4267 case Intrinsic::loongarch_lsx_vshuf4i_b:
4268 case Intrinsic::loongarch_lsx_vshuf4i_h:
4269 case Intrinsic::loongarch_lsx_vshuf4i_w:
4270 case Intrinsic::loongarch_lasx_xvnori_b:
4271 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4272 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4273 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4274 case Intrinsic::loongarch_lasx_xvpermi_d:
4276 case Intrinsic::loongarch_lsx_vshuf4i_d:
4277 case Intrinsic::loongarch_lsx_vpermi_w:
4278 case Intrinsic::loongarch_lsx_vbitseli_b:
4279 case Intrinsic::loongarch_lsx_vextrins_b:
4280 case Intrinsic::loongarch_lsx_vextrins_h:
4281 case Intrinsic::loongarch_lsx_vextrins_w:
4282 case Intrinsic::loongarch_lsx_vextrins_d:
4283 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4284 case Intrinsic::loongarch_lasx_xvpermi_w:
4285 case Intrinsic::loongarch_lasx_xvpermi_q:
4286 case Intrinsic::loongarch_lasx_xvbitseli_b:
4287 case Intrinsic::loongarch_lasx_xvextrins_b:
4288 case Intrinsic::loongarch_lasx_xvextrins_h:
4289 case Intrinsic::loongarch_lasx_xvextrins_w:
4290 case Intrinsic::loongarch_lasx_xvextrins_d:
4292 case Intrinsic::loongarch_lsx_vrepli_b:
4293 case Intrinsic::loongarch_lsx_vrepli_h:
4294 case Intrinsic::loongarch_lsx_vrepli_w:
4295 case Intrinsic::loongarch_lsx_vrepli_d:
4296 case Intrinsic::loongarch_lasx_xvrepli_b:
4297 case Intrinsic::loongarch_lasx_xvrepli_h:
4298 case Intrinsic::loongarch_lasx_xvrepli_w:
4299 case Intrinsic::loongarch_lasx_xvrepli_d:
4301 case Intrinsic::loongarch_lsx_vldi:
4302 case Intrinsic::loongarch_lasx_xvldi:
4318LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4321 MVT GRLenVT = Subtarget.getGRLenVT();
4322 EVT VT =
Op.getValueType();
4324 const StringRef ErrorMsgOOR =
"argument out of range";
4325 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4326 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4328 switch (
Op.getConstantOperandVal(1)) {
4331 case Intrinsic::loongarch_crc_w_b_w:
4332 case Intrinsic::loongarch_crc_w_h_w:
4333 case Intrinsic::loongarch_crc_w_w_w:
4334 case Intrinsic::loongarch_crc_w_d_w:
4335 case Intrinsic::loongarch_crcc_w_b_w:
4336 case Intrinsic::loongarch_crcc_w_h_w:
4337 case Intrinsic::loongarch_crcc_w_w_w:
4338 case Intrinsic::loongarch_crcc_w_d_w:
4340 case Intrinsic::loongarch_csrrd_w:
4341 case Intrinsic::loongarch_csrrd_d: {
4342 unsigned Imm =
Op.getConstantOperandVal(2);
4345 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4348 case Intrinsic::loongarch_csrwr_w:
4349 case Intrinsic::loongarch_csrwr_d: {
4350 unsigned Imm =
Op.getConstantOperandVal(3);
4353 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4354 {Chain,
Op.getOperand(2),
4357 case Intrinsic::loongarch_csrxchg_w:
4358 case Intrinsic::loongarch_csrxchg_d: {
4359 unsigned Imm =
Op.getConstantOperandVal(4);
4362 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4363 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4366 case Intrinsic::loongarch_iocsrrd_d: {
4368 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4371#define IOCSRRD_CASE(NAME, NODE) \
4372 case Intrinsic::loongarch_##NAME: { \
4373 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4374 {Chain, Op.getOperand(2)}); \
4380 case Intrinsic::loongarch_cpucfg: {
4381 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4382 {Chain,
Op.getOperand(2)});
4384 case Intrinsic::loongarch_lddir_d: {
4385 unsigned Imm =
Op.getConstantOperandVal(3);
4390 case Intrinsic::loongarch_movfcsr2gr: {
4391 if (!Subtarget.hasBasicF())
4393 unsigned Imm =
Op.getConstantOperandVal(2);
4396 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4399 case Intrinsic::loongarch_lsx_vld:
4400 case Intrinsic::loongarch_lsx_vldrepl_b:
4401 case Intrinsic::loongarch_lasx_xvld:
4402 case Intrinsic::loongarch_lasx_xvldrepl_b:
4406 case Intrinsic::loongarch_lsx_vldrepl_h:
4407 case Intrinsic::loongarch_lasx_xvldrepl_h:
4411 Op,
"argument out of range or not a multiple of 2", DAG)
4413 case Intrinsic::loongarch_lsx_vldrepl_w:
4414 case Intrinsic::loongarch_lasx_xvldrepl_w:
4418 Op,
"argument out of range or not a multiple of 4", DAG)
4420 case Intrinsic::loongarch_lsx_vldrepl_d:
4421 case Intrinsic::loongarch_lasx_xvldrepl_d:
4425 Op,
"argument out of range or not a multiple of 8", DAG)
4436 return Op.getOperand(0);
4442 MVT GRLenVT = Subtarget.getGRLenVT();
4444 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4446 const StringRef ErrorMsgOOR =
"argument out of range";
4447 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4448 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4449 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4451 switch (IntrinsicEnum) {
4455 case Intrinsic::loongarch_cacop_d:
4456 case Intrinsic::loongarch_cacop_w: {
4457 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4459 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4468 case Intrinsic::loongarch_dbar: {
4475 case Intrinsic::loongarch_ibar: {
4482 case Intrinsic::loongarch_break: {
4489 case Intrinsic::loongarch_movgr2fcsr: {
4490 if (!Subtarget.hasBasicF())
4500 case Intrinsic::loongarch_syscall: {
4507#define IOCSRWR_CASE(NAME, NODE) \
4508 case Intrinsic::loongarch_##NAME: { \
4509 SDValue Op3 = Op.getOperand(3); \
4510 return Subtarget.is64Bit() \
4511 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4512 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4513 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4514 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4521 case Intrinsic::loongarch_iocsrwr_d: {
4522 return !Subtarget.is64Bit()
4529#define ASRT_LE_GT_CASE(NAME) \
4530 case Intrinsic::loongarch_##NAME: { \
4531 return !Subtarget.is64Bit() \
4532 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4537#undef ASRT_LE_GT_CASE
4538 case Intrinsic::loongarch_ldpte_d: {
4539 unsigned Imm =
Op.getConstantOperandVal(3);
4540 return !Subtarget.is64Bit()
4545 case Intrinsic::loongarch_lsx_vst:
4546 case Intrinsic::loongarch_lasx_xvst:
4550 case Intrinsic::loongarch_lasx_xvstelm_b:
4555 case Intrinsic::loongarch_lsx_vstelm_b:
4560 case Intrinsic::loongarch_lasx_xvstelm_h:
4565 Op,
"argument out of range or not a multiple of 2", DAG)
4567 case Intrinsic::loongarch_lsx_vstelm_h:
4572 Op,
"argument out of range or not a multiple of 2", DAG)
4574 case Intrinsic::loongarch_lasx_xvstelm_w:
4579 Op,
"argument out of range or not a multiple of 4", DAG)
4581 case Intrinsic::loongarch_lsx_vstelm_w:
4586 Op,
"argument out of range or not a multiple of 4", DAG)
4588 case Intrinsic::loongarch_lasx_xvstelm_d:
4593 Op,
"argument out of range or not a multiple of 8", DAG)
4595 case Intrinsic::loongarch_lsx_vstelm_d:
4600 Op,
"argument out of range or not a multiple of 8", DAG)
4611 EVT VT =
Lo.getValueType();
4652 EVT VT =
Lo.getValueType();
4706 return LoongArchISD::DIV_W;
4708 return LoongArchISD::DIV_WU;
4710 return LoongArchISD::MOD_W;
4712 return LoongArchISD::MOD_WU;
4714 return LoongArchISD::SLL_W;
4716 return LoongArchISD::SRA_W;
4718 return LoongArchISD::SRL_W;
4721 return LoongArchISD::ROTR_W;
4723 return LoongArchISD::CTZ_W;
4725 return LoongArchISD::CLZ_W;
4744 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4745 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4749 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4755 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4782 StringRef ErrorMsg,
bool WithChain =
true) {
4787 Results.push_back(
N->getOperand(0));
4790template <
unsigned N>
4795 const StringRef ErrorMsgOOR =
"argument out of range";
4796 unsigned Imm =
Node->getConstantOperandVal(2);
4830 switch (
N->getConstantOperandVal(0)) {
4833 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4835 LoongArchISD::VPICK_SEXT_ELT);
4837 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4838 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4840 LoongArchISD::VPICK_SEXT_ELT);
4842 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4844 LoongArchISD::VPICK_SEXT_ELT);
4846 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4848 LoongArchISD::VPICK_ZEXT_ELT);
4850 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4851 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4853 LoongArchISD::VPICK_ZEXT_ELT);
4855 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4857 LoongArchISD::VPICK_ZEXT_ELT);
4859 case Intrinsic::loongarch_lsx_bz_b:
4860 case Intrinsic::loongarch_lsx_bz_h:
4861 case Intrinsic::loongarch_lsx_bz_w:
4862 case Intrinsic::loongarch_lsx_bz_d:
4863 case Intrinsic::loongarch_lasx_xbz_b:
4864 case Intrinsic::loongarch_lasx_xbz_h:
4865 case Intrinsic::loongarch_lasx_xbz_w:
4866 case Intrinsic::loongarch_lasx_xbz_d:
4868 LoongArchISD::VALL_ZERO);
4870 case Intrinsic::loongarch_lsx_bz_v:
4871 case Intrinsic::loongarch_lasx_xbz_v:
4873 LoongArchISD::VANY_ZERO);
4875 case Intrinsic::loongarch_lsx_bnz_b:
4876 case Intrinsic::loongarch_lsx_bnz_h:
4877 case Intrinsic::loongarch_lsx_bnz_w:
4878 case Intrinsic::loongarch_lsx_bnz_d:
4879 case Intrinsic::loongarch_lasx_xbnz_b:
4880 case Intrinsic::loongarch_lasx_xbnz_h:
4881 case Intrinsic::loongarch_lasx_xbnz_w:
4882 case Intrinsic::loongarch_lasx_xbnz_d:
4884 LoongArchISD::VALL_NONZERO);
4886 case Intrinsic::loongarch_lsx_bnz_v:
4887 case Intrinsic::loongarch_lasx_xbnz_v:
4889 LoongArchISD::VANY_NONZERO);
4897 assert(
N->getValueType(0) == MVT::i128 &&
4898 "AtomicCmpSwap on types less than 128 should be legal");
4902 switch (
MemOp->getMergedOrdering()) {
4906 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4910 Opcode = LoongArch::PseudoCmpXchg128;
4917 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4918 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4919 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4920 NewVal.first, NewVal.second,
N->getOperand(0)};
4923 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4934 EVT VT =
N->getValueType(0);
4935 switch (
N->getOpcode()) {
4940 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4941 "Unexpected custom legalisation");
4948 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4949 "Unexpected custom legalisation");
4951 Subtarget.hasDiv32() && VT == MVT::i32
4958 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4959 "Unexpected custom legalisation");
4967 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4968 "Unexpected custom legalisation");
4972 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4973 "Unexpected custom legalisation");
4980 if (Src.getValueType() == MVT::f16)
4991 EVT OpVT = Src.getValueType();
4995 std::tie(Result, Chain) =
5002 EVT SrcVT = Src.getValueType();
5003 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5004 Subtarget.hasBasicF()) {
5006 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5008 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5010 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5018 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5019 "Unexpected custom legalisation");
5022 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5028 assert((VT == MVT::i16 || VT == MVT::i32) &&
5029 "Unexpected custom legalization");
5030 MVT GRLenVT = Subtarget.getGRLenVT();
5037 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5042 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5050 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5051 "Unexpected custom legalization");
5052 MVT GRLenVT = Subtarget.getGRLenVT();
5059 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5062 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5070 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5071 "Unexpected custom legalisation");
5078 MVT GRLenVT = Subtarget.getGRLenVT();
5079 const StringRef ErrorMsgOOR =
"argument out of range";
5080 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5081 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5083 switch (
N->getConstantOperandVal(1)) {
5086 case Intrinsic::loongarch_movfcsr2gr: {
5087 if (!Subtarget.hasBasicF()) {
5097 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5104#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5105 case Intrinsic::loongarch_##NAME: { \
5106 SDValue NODE = DAG.getNode( \
5107 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5108 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5109 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5110 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5111 Results.push_back(NODE.getValue(1)); \
5120#undef CRC_CASE_EXT_BINARYOP
5122#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5123 case Intrinsic::loongarch_##NAME: { \
5124 SDValue NODE = DAG.getNode( \
5125 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5127 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5128 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5129 Results.push_back(NODE.getValue(1)); \
5134#undef CRC_CASE_EXT_UNARYOP
5135#define CSR_CASE(ID) \
5136 case Intrinsic::loongarch_##ID: { \
5137 if (!Subtarget.is64Bit()) \
5138 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5146 case Intrinsic::loongarch_csrrd_w: {
5153 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5160 case Intrinsic::loongarch_csrwr_w: {
5161 unsigned Imm =
N->getConstantOperandVal(3);
5167 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5175 case Intrinsic::loongarch_csrxchg_w: {
5176 unsigned Imm =
N->getConstantOperandVal(4);
5182 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5191#define IOCSRRD_CASE(NAME, NODE) \
5192 case Intrinsic::loongarch_##NAME: { \
5193 SDValue IOCSRRDResults = \
5194 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5195 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5196 Results.push_back( \
5197 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5198 Results.push_back(IOCSRRDResults.getValue(1)); \
5205 case Intrinsic::loongarch_cpucfg: {
5207 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5214 case Intrinsic::loongarch_lddir_d: {
5215 if (!Subtarget.is64Bit()) {
5225 if (Subtarget.is64Bit())
5227 "On LA64, only 64-bit registers can be read.");
5230 "On LA32, only 32-bit registers can be read.");
5232 Results.push_back(
N->getOperand(0));
5243 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5256 MVT VT =
N->getSimpleValueType(0);
5262 EVT InVT = In.getValueType();
5273 for (
unsigned I = 0;
I < MinElts; ++
I)
5274 TruncMask[
I] = Scale *
I;
5276 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5277 MVT SVT = In.getSimpleValueType().getScalarType();
5283 "Illegal vector type in truncation");
5299 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5301 MVT VT =
N->getSimpleValueType(0);
5320 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5329 SDValue FirstOperand =
N->getOperand(0);
5330 SDValue SecondOperand =
N->getOperand(1);
5331 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5332 EVT ValTy =
N->getValueType(0);
5335 unsigned SMIdx, SMLen;
5344 if (!Subtarget.has32S())
5400 NewOperand = FirstOperand;
5403 msb = lsb + SMLen - 1;
5407 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5420 if (!Subtarget.has32S())
5432 SDValue FirstOperand =
N->getOperand(0);
5434 EVT ValTy =
N->getValueType(0);
5437 unsigned MaskIdx, MaskLen;
5452 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5453 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
5468 switch (Src.getOpcode()) {
5471 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5481 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5494 switch (Src.getOpcode()) {
5504 Src.getOpcode(),
DL, SExtVT,
5510 DL, SExtVT, Src.getOperand(0),
5522 EVT VT =
N->getValueType(0);
5524 EVT SrcVT = Src.getValueType();
5526 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5531 EVT CmpVT = Src.getOperand(0).getValueType();
5536 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5549 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
5554 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5559 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5564 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5566 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5571 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5573 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5578 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
5595 EVT VT =
N->getValueType(0);
5597 EVT SrcVT = Src.getValueType();
5614 bool UseLASX =
false;
5615 bool PropagateSExt =
false;
5617 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5618 EVT CmpVT = Src.getOperand(0).getValueType();
5627 SExtVT = MVT::v2i64;
5630 SExtVT = MVT::v4i32;
5632 SExtVT = MVT::v4i64;
5634 PropagateSExt =
true;
5638 SExtVT = MVT::v8i16;
5640 SExtVT = MVT::v8i32;
5642 PropagateSExt =
true;
5646 SExtVT = MVT::v16i8;
5648 SExtVT = MVT::v16i16;
5650 PropagateSExt =
true;
5654 SExtVT = MVT::v32i8;
5662 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5663 if (Src.getSimpleValueType() == MVT::v32i8) {
5671 }
else if (UseLASX) {
5677 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
5690 EVT ValTy =
N->getValueType(0);
5691 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5695 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5697 bool SwapAndRetried =
false;
5700 if (!Subtarget.has32S())
5706 if (ValBits != 32 && ValBits != 64)
5721 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5724 (MaskIdx0 + MaskLen0 <= ValBits)) {
5745 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5746 (MaskIdx0 + MaskLen0 <= ValBits)) {
5763 (MaskIdx0 + MaskLen0 <= 64) &&
5771 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5772 : (MaskIdx0 + MaskLen0 - 1),
5788 (MaskIdx0 + MaskLen0 <= ValBits)) {
5811 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5812 : (MaskIdx0 + MaskLen0 - 1),
5827 unsigned MaskIdx, MaskLen;
5828 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5837 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5855 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5861 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5869 if (!SwapAndRetried) {
5871 SwapAndRetried =
true;
5875 SwapAndRetried =
false;
5892 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
5901 if (!SwapAndRetried) {
5903 SwapAndRetried =
true;
5913 switch (V.getNode()->getOpcode()) {
5925 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5933 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6010 SDNode *AndNode =
N->getOperand(0).getNode();
6018 SDValue CmpInputValue =
N->getOperand(1);
6027 if (!CN || !CN->
isZero())
6029 AndInputValue1 = AndInputValue1.
getOperand(0);
6033 if (AndInputValue2 != CmpInputValue)
6066 TruncInputValue1, TruncInputValue2);
6068 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6081 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6084 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6109 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6137 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6170 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6171 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6187 EVT VT =
N->getValueType(0);
6190 if (TrueV == FalseV)
6221 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6222 {LHS, RHS, CC, TrueV, FalseV});
6227template <
unsigned N>
6231 bool IsSigned =
false) {
6235 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6236 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6238 ": argument out of range.");
6244template <
unsigned N>
6248 EVT ResTy =
Node->getValueType(0);
6252 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6253 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6255 ": argument out of range.");
6260 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6266 EVT ResTy =
Node->getValueType(0);
6274 EVT ResTy =
Node->getValueType(0);
6283template <
unsigned N>
6286 EVT ResTy =
Node->getValueType(0);
6291 ": argument out of range.");
6301template <
unsigned N>
6304 EVT ResTy =
Node->getValueType(0);
6309 ": argument out of range.");
6318template <
unsigned N>
6321 EVT ResTy =
Node->getValueType(0);
6326 ": argument out of range.");
6335template <
unsigned W>
6338 unsigned Imm =
N->getConstantOperandVal(2);
6340 const StringRef ErrorMsg =
"argument out of range";
6342 return DAG.
getUNDEF(
N->getValueType(0));
6348 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6356 switch (
N->getConstantOperandVal(0)) {
6359 case Intrinsic::loongarch_lsx_vadd_b:
6360 case Intrinsic::loongarch_lsx_vadd_h:
6361 case Intrinsic::loongarch_lsx_vadd_w:
6362 case Intrinsic::loongarch_lsx_vadd_d:
6363 case Intrinsic::loongarch_lasx_xvadd_b:
6364 case Intrinsic::loongarch_lasx_xvadd_h:
6365 case Intrinsic::loongarch_lasx_xvadd_w:
6366 case Intrinsic::loongarch_lasx_xvadd_d:
6369 case Intrinsic::loongarch_lsx_vaddi_bu:
6370 case Intrinsic::loongarch_lsx_vaddi_hu:
6371 case Intrinsic::loongarch_lsx_vaddi_wu:
6372 case Intrinsic::loongarch_lsx_vaddi_du:
6373 case Intrinsic::loongarch_lasx_xvaddi_bu:
6374 case Intrinsic::loongarch_lasx_xvaddi_hu:
6375 case Intrinsic::loongarch_lasx_xvaddi_wu:
6376 case Intrinsic::loongarch_lasx_xvaddi_du:
6379 case Intrinsic::loongarch_lsx_vsub_b:
6380 case Intrinsic::loongarch_lsx_vsub_h:
6381 case Intrinsic::loongarch_lsx_vsub_w:
6382 case Intrinsic::loongarch_lsx_vsub_d:
6383 case Intrinsic::loongarch_lasx_xvsub_b:
6384 case Intrinsic::loongarch_lasx_xvsub_h:
6385 case Intrinsic::loongarch_lasx_xvsub_w:
6386 case Intrinsic::loongarch_lasx_xvsub_d:
6389 case Intrinsic::loongarch_lsx_vsubi_bu:
6390 case Intrinsic::loongarch_lsx_vsubi_hu:
6391 case Intrinsic::loongarch_lsx_vsubi_wu:
6392 case Intrinsic::loongarch_lsx_vsubi_du:
6393 case Intrinsic::loongarch_lasx_xvsubi_bu:
6394 case Intrinsic::loongarch_lasx_xvsubi_hu:
6395 case Intrinsic::loongarch_lasx_xvsubi_wu:
6396 case Intrinsic::loongarch_lasx_xvsubi_du:
6399 case Intrinsic::loongarch_lsx_vneg_b:
6400 case Intrinsic::loongarch_lsx_vneg_h:
6401 case Intrinsic::loongarch_lsx_vneg_w:
6402 case Intrinsic::loongarch_lsx_vneg_d:
6403 case Intrinsic::loongarch_lasx_xvneg_b:
6404 case Intrinsic::loongarch_lasx_xvneg_h:
6405 case Intrinsic::loongarch_lasx_xvneg_w:
6406 case Intrinsic::loongarch_lasx_xvneg_d:
6410 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6412 SDLoc(
N),
N->getValueType(0)),
6414 case Intrinsic::loongarch_lsx_vmax_b:
6415 case Intrinsic::loongarch_lsx_vmax_h:
6416 case Intrinsic::loongarch_lsx_vmax_w:
6417 case Intrinsic::loongarch_lsx_vmax_d:
6418 case Intrinsic::loongarch_lasx_xvmax_b:
6419 case Intrinsic::loongarch_lasx_xvmax_h:
6420 case Intrinsic::loongarch_lasx_xvmax_w:
6421 case Intrinsic::loongarch_lasx_xvmax_d:
6424 case Intrinsic::loongarch_lsx_vmax_bu:
6425 case Intrinsic::loongarch_lsx_vmax_hu:
6426 case Intrinsic::loongarch_lsx_vmax_wu:
6427 case Intrinsic::loongarch_lsx_vmax_du:
6428 case Intrinsic::loongarch_lasx_xvmax_bu:
6429 case Intrinsic::loongarch_lasx_xvmax_hu:
6430 case Intrinsic::loongarch_lasx_xvmax_wu:
6431 case Intrinsic::loongarch_lasx_xvmax_du:
6434 case Intrinsic::loongarch_lsx_vmaxi_b:
6435 case Intrinsic::loongarch_lsx_vmaxi_h:
6436 case Intrinsic::loongarch_lsx_vmaxi_w:
6437 case Intrinsic::loongarch_lsx_vmaxi_d:
6438 case Intrinsic::loongarch_lasx_xvmaxi_b:
6439 case Intrinsic::loongarch_lasx_xvmaxi_h:
6440 case Intrinsic::loongarch_lasx_xvmaxi_w:
6441 case Intrinsic::loongarch_lasx_xvmaxi_d:
6444 case Intrinsic::loongarch_lsx_vmaxi_bu:
6445 case Intrinsic::loongarch_lsx_vmaxi_hu:
6446 case Intrinsic::loongarch_lsx_vmaxi_wu:
6447 case Intrinsic::loongarch_lsx_vmaxi_du:
6448 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6449 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6450 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6451 case Intrinsic::loongarch_lasx_xvmaxi_du:
6454 case Intrinsic::loongarch_lsx_vmin_b:
6455 case Intrinsic::loongarch_lsx_vmin_h:
6456 case Intrinsic::loongarch_lsx_vmin_w:
6457 case Intrinsic::loongarch_lsx_vmin_d:
6458 case Intrinsic::loongarch_lasx_xvmin_b:
6459 case Intrinsic::loongarch_lasx_xvmin_h:
6460 case Intrinsic::loongarch_lasx_xvmin_w:
6461 case Intrinsic::loongarch_lasx_xvmin_d:
6464 case Intrinsic::loongarch_lsx_vmin_bu:
6465 case Intrinsic::loongarch_lsx_vmin_hu:
6466 case Intrinsic::loongarch_lsx_vmin_wu:
6467 case Intrinsic::loongarch_lsx_vmin_du:
6468 case Intrinsic::loongarch_lasx_xvmin_bu:
6469 case Intrinsic::loongarch_lasx_xvmin_hu:
6470 case Intrinsic::loongarch_lasx_xvmin_wu:
6471 case Intrinsic::loongarch_lasx_xvmin_du:
6474 case Intrinsic::loongarch_lsx_vmini_b:
6475 case Intrinsic::loongarch_lsx_vmini_h:
6476 case Intrinsic::loongarch_lsx_vmini_w:
6477 case Intrinsic::loongarch_lsx_vmini_d:
6478 case Intrinsic::loongarch_lasx_xvmini_b:
6479 case Intrinsic::loongarch_lasx_xvmini_h:
6480 case Intrinsic::loongarch_lasx_xvmini_w:
6481 case Intrinsic::loongarch_lasx_xvmini_d:
6484 case Intrinsic::loongarch_lsx_vmini_bu:
6485 case Intrinsic::loongarch_lsx_vmini_hu:
6486 case Intrinsic::loongarch_lsx_vmini_wu:
6487 case Intrinsic::loongarch_lsx_vmini_du:
6488 case Intrinsic::loongarch_lasx_xvmini_bu:
6489 case Intrinsic::loongarch_lasx_xvmini_hu:
6490 case Intrinsic::loongarch_lasx_xvmini_wu:
6491 case Intrinsic::loongarch_lasx_xvmini_du:
6494 case Intrinsic::loongarch_lsx_vmul_b:
6495 case Intrinsic::loongarch_lsx_vmul_h:
6496 case Intrinsic::loongarch_lsx_vmul_w:
6497 case Intrinsic::loongarch_lsx_vmul_d:
6498 case Intrinsic::loongarch_lasx_xvmul_b:
6499 case Intrinsic::loongarch_lasx_xvmul_h:
6500 case Intrinsic::loongarch_lasx_xvmul_w:
6501 case Intrinsic::loongarch_lasx_xvmul_d:
6504 case Intrinsic::loongarch_lsx_vmadd_b:
6505 case Intrinsic::loongarch_lsx_vmadd_h:
6506 case Intrinsic::loongarch_lsx_vmadd_w:
6507 case Intrinsic::loongarch_lsx_vmadd_d:
6508 case Intrinsic::loongarch_lasx_xvmadd_b:
6509 case Intrinsic::loongarch_lasx_xvmadd_h:
6510 case Intrinsic::loongarch_lasx_xvmadd_w:
6511 case Intrinsic::loongarch_lasx_xvmadd_d: {
6512 EVT ResTy =
N->getValueType(0);
6517 case Intrinsic::loongarch_lsx_vmsub_b:
6518 case Intrinsic::loongarch_lsx_vmsub_h:
6519 case Intrinsic::loongarch_lsx_vmsub_w:
6520 case Intrinsic::loongarch_lsx_vmsub_d:
6521 case Intrinsic::loongarch_lasx_xvmsub_b:
6522 case Intrinsic::loongarch_lasx_xvmsub_h:
6523 case Intrinsic::loongarch_lasx_xvmsub_w:
6524 case Intrinsic::loongarch_lasx_xvmsub_d: {
6525 EVT ResTy =
N->getValueType(0);
6530 case Intrinsic::loongarch_lsx_vdiv_b:
6531 case Intrinsic::loongarch_lsx_vdiv_h:
6532 case Intrinsic::loongarch_lsx_vdiv_w:
6533 case Intrinsic::loongarch_lsx_vdiv_d:
6534 case Intrinsic::loongarch_lasx_xvdiv_b:
6535 case Intrinsic::loongarch_lasx_xvdiv_h:
6536 case Intrinsic::loongarch_lasx_xvdiv_w:
6537 case Intrinsic::loongarch_lasx_xvdiv_d:
6540 case Intrinsic::loongarch_lsx_vdiv_bu:
6541 case Intrinsic::loongarch_lsx_vdiv_hu:
6542 case Intrinsic::loongarch_lsx_vdiv_wu:
6543 case Intrinsic::loongarch_lsx_vdiv_du:
6544 case Intrinsic::loongarch_lasx_xvdiv_bu:
6545 case Intrinsic::loongarch_lasx_xvdiv_hu:
6546 case Intrinsic::loongarch_lasx_xvdiv_wu:
6547 case Intrinsic::loongarch_lasx_xvdiv_du:
6550 case Intrinsic::loongarch_lsx_vmod_b:
6551 case Intrinsic::loongarch_lsx_vmod_h:
6552 case Intrinsic::loongarch_lsx_vmod_w:
6553 case Intrinsic::loongarch_lsx_vmod_d:
6554 case Intrinsic::loongarch_lasx_xvmod_b:
6555 case Intrinsic::loongarch_lasx_xvmod_h:
6556 case Intrinsic::loongarch_lasx_xvmod_w:
6557 case Intrinsic::loongarch_lasx_xvmod_d:
6560 case Intrinsic::loongarch_lsx_vmod_bu:
6561 case Intrinsic::loongarch_lsx_vmod_hu:
6562 case Intrinsic::loongarch_lsx_vmod_wu:
6563 case Intrinsic::loongarch_lsx_vmod_du:
6564 case Intrinsic::loongarch_lasx_xvmod_bu:
6565 case Intrinsic::loongarch_lasx_xvmod_hu:
6566 case Intrinsic::loongarch_lasx_xvmod_wu:
6567 case Intrinsic::loongarch_lasx_xvmod_du:
6570 case Intrinsic::loongarch_lsx_vand_v:
6571 case Intrinsic::loongarch_lasx_xvand_v:
6574 case Intrinsic::loongarch_lsx_vor_v:
6575 case Intrinsic::loongarch_lasx_xvor_v:
6578 case Intrinsic::loongarch_lsx_vxor_v:
6579 case Intrinsic::loongarch_lasx_xvxor_v:
6582 case Intrinsic::loongarch_lsx_vnor_v:
6583 case Intrinsic::loongarch_lasx_xvnor_v: {
6588 case Intrinsic::loongarch_lsx_vandi_b:
6589 case Intrinsic::loongarch_lasx_xvandi_b:
6592 case Intrinsic::loongarch_lsx_vori_b:
6593 case Intrinsic::loongarch_lasx_xvori_b:
6596 case Intrinsic::loongarch_lsx_vxori_b:
6597 case Intrinsic::loongarch_lasx_xvxori_b:
6600 case Intrinsic::loongarch_lsx_vsll_b:
6601 case Intrinsic::loongarch_lsx_vsll_h:
6602 case Intrinsic::loongarch_lsx_vsll_w:
6603 case Intrinsic::loongarch_lsx_vsll_d:
6604 case Intrinsic::loongarch_lasx_xvsll_b:
6605 case Intrinsic::loongarch_lasx_xvsll_h:
6606 case Intrinsic::loongarch_lasx_xvsll_w:
6607 case Intrinsic::loongarch_lasx_xvsll_d:
6610 case Intrinsic::loongarch_lsx_vslli_b:
6611 case Intrinsic::loongarch_lasx_xvslli_b:
6614 case Intrinsic::loongarch_lsx_vslli_h:
6615 case Intrinsic::loongarch_lasx_xvslli_h:
6618 case Intrinsic::loongarch_lsx_vslli_w:
6619 case Intrinsic::loongarch_lasx_xvslli_w:
6622 case Intrinsic::loongarch_lsx_vslli_d:
6623 case Intrinsic::loongarch_lasx_xvslli_d:
6626 case Intrinsic::loongarch_lsx_vsrl_b:
6627 case Intrinsic::loongarch_lsx_vsrl_h:
6628 case Intrinsic::loongarch_lsx_vsrl_w:
6629 case Intrinsic::loongarch_lsx_vsrl_d:
6630 case Intrinsic::loongarch_lasx_xvsrl_b:
6631 case Intrinsic::loongarch_lasx_xvsrl_h:
6632 case Intrinsic::loongarch_lasx_xvsrl_w:
6633 case Intrinsic::loongarch_lasx_xvsrl_d:
6636 case Intrinsic::loongarch_lsx_vsrli_b:
6637 case Intrinsic::loongarch_lasx_xvsrli_b:
6640 case Intrinsic::loongarch_lsx_vsrli_h:
6641 case Intrinsic::loongarch_lasx_xvsrli_h:
6644 case Intrinsic::loongarch_lsx_vsrli_w:
6645 case Intrinsic::loongarch_lasx_xvsrli_w:
6648 case Intrinsic::loongarch_lsx_vsrli_d:
6649 case Intrinsic::loongarch_lasx_xvsrli_d:
6652 case Intrinsic::loongarch_lsx_vsra_b:
6653 case Intrinsic::loongarch_lsx_vsra_h:
6654 case Intrinsic::loongarch_lsx_vsra_w:
6655 case Intrinsic::loongarch_lsx_vsra_d:
6656 case Intrinsic::loongarch_lasx_xvsra_b:
6657 case Intrinsic::loongarch_lasx_xvsra_h:
6658 case Intrinsic::loongarch_lasx_xvsra_w:
6659 case Intrinsic::loongarch_lasx_xvsra_d:
6662 case Intrinsic::loongarch_lsx_vsrai_b:
6663 case Intrinsic::loongarch_lasx_xvsrai_b:
6666 case Intrinsic::loongarch_lsx_vsrai_h:
6667 case Intrinsic::loongarch_lasx_xvsrai_h:
6670 case Intrinsic::loongarch_lsx_vsrai_w:
6671 case Intrinsic::loongarch_lasx_xvsrai_w:
6674 case Intrinsic::loongarch_lsx_vsrai_d:
6675 case Intrinsic::loongarch_lasx_xvsrai_d:
6678 case Intrinsic::loongarch_lsx_vclz_b:
6679 case Intrinsic::loongarch_lsx_vclz_h:
6680 case Intrinsic::loongarch_lsx_vclz_w:
6681 case Intrinsic::loongarch_lsx_vclz_d:
6682 case Intrinsic::loongarch_lasx_xvclz_b:
6683 case Intrinsic::loongarch_lasx_xvclz_h:
6684 case Intrinsic::loongarch_lasx_xvclz_w:
6685 case Intrinsic::loongarch_lasx_xvclz_d:
6687 case Intrinsic::loongarch_lsx_vpcnt_b:
6688 case Intrinsic::loongarch_lsx_vpcnt_h:
6689 case Intrinsic::loongarch_lsx_vpcnt_w:
6690 case Intrinsic::loongarch_lsx_vpcnt_d:
6691 case Intrinsic::loongarch_lasx_xvpcnt_b:
6692 case Intrinsic::loongarch_lasx_xvpcnt_h:
6693 case Intrinsic::loongarch_lasx_xvpcnt_w:
6694 case Intrinsic::loongarch_lasx_xvpcnt_d:
6696 case Intrinsic::loongarch_lsx_vbitclr_b:
6697 case Intrinsic::loongarch_lsx_vbitclr_h:
6698 case Intrinsic::loongarch_lsx_vbitclr_w:
6699 case Intrinsic::loongarch_lsx_vbitclr_d:
6700 case Intrinsic::loongarch_lasx_xvbitclr_b:
6701 case Intrinsic::loongarch_lasx_xvbitclr_h:
6702 case Intrinsic::loongarch_lasx_xvbitclr_w:
6703 case Intrinsic::loongarch_lasx_xvbitclr_d:
6705 case Intrinsic::loongarch_lsx_vbitclri_b:
6706 case Intrinsic::loongarch_lasx_xvbitclri_b:
6708 case Intrinsic::loongarch_lsx_vbitclri_h:
6709 case Intrinsic::loongarch_lasx_xvbitclri_h:
6711 case Intrinsic::loongarch_lsx_vbitclri_w:
6712 case Intrinsic::loongarch_lasx_xvbitclri_w:
6714 case Intrinsic::loongarch_lsx_vbitclri_d:
6715 case Intrinsic::loongarch_lasx_xvbitclri_d:
6717 case Intrinsic::loongarch_lsx_vbitset_b:
6718 case Intrinsic::loongarch_lsx_vbitset_h:
6719 case Intrinsic::loongarch_lsx_vbitset_w:
6720 case Intrinsic::loongarch_lsx_vbitset_d:
6721 case Intrinsic::loongarch_lasx_xvbitset_b:
6722 case Intrinsic::loongarch_lasx_xvbitset_h:
6723 case Intrinsic::loongarch_lasx_xvbitset_w:
6724 case Intrinsic::loongarch_lasx_xvbitset_d: {
6725 EVT VecTy =
N->getValueType(0);
6731 case Intrinsic::loongarch_lsx_vbitseti_b:
6732 case Intrinsic::loongarch_lasx_xvbitseti_b:
6734 case Intrinsic::loongarch_lsx_vbitseti_h:
6735 case Intrinsic::loongarch_lasx_xvbitseti_h:
6737 case Intrinsic::loongarch_lsx_vbitseti_w:
6738 case Intrinsic::loongarch_lasx_xvbitseti_w:
6740 case Intrinsic::loongarch_lsx_vbitseti_d:
6741 case Intrinsic::loongarch_lasx_xvbitseti_d:
6743 case Intrinsic::loongarch_lsx_vbitrev_b:
6744 case Intrinsic::loongarch_lsx_vbitrev_h:
6745 case Intrinsic::loongarch_lsx_vbitrev_w:
6746 case Intrinsic::loongarch_lsx_vbitrev_d:
6747 case Intrinsic::loongarch_lasx_xvbitrev_b:
6748 case Intrinsic::loongarch_lasx_xvbitrev_h:
6749 case Intrinsic::loongarch_lasx_xvbitrev_w:
6750 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6751 EVT VecTy =
N->getValueType(0);
6757 case Intrinsic::loongarch_lsx_vbitrevi_b:
6758 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6760 case Intrinsic::loongarch_lsx_vbitrevi_h:
6761 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6763 case Intrinsic::loongarch_lsx_vbitrevi_w:
6764 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6766 case Intrinsic::loongarch_lsx_vbitrevi_d:
6767 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6769 case Intrinsic::loongarch_lsx_vfadd_s:
6770 case Intrinsic::loongarch_lsx_vfadd_d:
6771 case Intrinsic::loongarch_lasx_xvfadd_s:
6772 case Intrinsic::loongarch_lasx_xvfadd_d:
6775 case Intrinsic::loongarch_lsx_vfsub_s:
6776 case Intrinsic::loongarch_lsx_vfsub_d:
6777 case Intrinsic::loongarch_lasx_xvfsub_s:
6778 case Intrinsic::loongarch_lasx_xvfsub_d:
6781 case Intrinsic::loongarch_lsx_vfmul_s:
6782 case Intrinsic::loongarch_lsx_vfmul_d:
6783 case Intrinsic::loongarch_lasx_xvfmul_s:
6784 case Intrinsic::loongarch_lasx_xvfmul_d:
6787 case Intrinsic::loongarch_lsx_vfdiv_s:
6788 case Intrinsic::loongarch_lsx_vfdiv_d:
6789 case Intrinsic::loongarch_lasx_xvfdiv_s:
6790 case Intrinsic::loongarch_lasx_xvfdiv_d:
6793 case Intrinsic::loongarch_lsx_vfmadd_s:
6794 case Intrinsic::loongarch_lsx_vfmadd_d:
6795 case Intrinsic::loongarch_lasx_xvfmadd_s:
6796 case Intrinsic::loongarch_lasx_xvfmadd_d:
6798 N->getOperand(2),
N->getOperand(3));
6799 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6801 N->getOperand(1),
N->getOperand(2),
6803 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6804 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6806 N->getOperand(1),
N->getOperand(2),
6808 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6809 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6811 N->getOperand(1),
N->getOperand(2),
6813 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6815 N->getOperand(1),
N->getOperand(2),
6817 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6818 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6819 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6820 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6821 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6822 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6823 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6824 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6825 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
6828 case Intrinsic::loongarch_lsx_vreplve_b:
6829 case Intrinsic::loongarch_lsx_vreplve_h:
6830 case Intrinsic::loongarch_lsx_vreplve_w:
6831 case Intrinsic::loongarch_lsx_vreplve_d:
6832 case Intrinsic::loongarch_lasx_xvreplve_b:
6833 case Intrinsic::loongarch_lasx_xvreplve_h:
6834 case Intrinsic::loongarch_lasx_xvreplve_w:
6835 case Intrinsic::loongarch_lasx_xvreplve_d:
6836 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
6840 case Intrinsic::loongarch_lsx_vpickve2gr_b:
6844 case Intrinsic::loongarch_lsx_vpickve2gr_h:
6845 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
6849 case Intrinsic::loongarch_lsx_vpickve2gr_w:
6853 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
6857 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
6858 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
6862 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
6866 case Intrinsic::loongarch_lsx_bz_b:
6867 case Intrinsic::loongarch_lsx_bz_h:
6868 case Intrinsic::loongarch_lsx_bz_w:
6869 case Intrinsic::loongarch_lsx_bz_d:
6870 case Intrinsic::loongarch_lasx_xbz_b:
6871 case Intrinsic::loongarch_lasx_xbz_h:
6872 case Intrinsic::loongarch_lasx_xbz_w:
6873 case Intrinsic::loongarch_lasx_xbz_d:
6875 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
6878 case Intrinsic::loongarch_lsx_bz_v:
6879 case Intrinsic::loongarch_lasx_xbz_v:
6881 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
6884 case Intrinsic::loongarch_lsx_bnz_b:
6885 case Intrinsic::loongarch_lsx_bnz_h:
6886 case Intrinsic::loongarch_lsx_bnz_w:
6887 case Intrinsic::loongarch_lsx_bnz_d:
6888 case Intrinsic::loongarch_lasx_xbnz_b:
6889 case Intrinsic::loongarch_lasx_xbnz_h:
6890 case Intrinsic::loongarch_lasx_xbnz_w:
6891 case Intrinsic::loongarch_lasx_xbnz_d:
6893 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
6896 case Intrinsic::loongarch_lsx_bnz_v:
6897 case Intrinsic::loongarch_lasx_xbnz_v:
6899 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
6902 case Intrinsic::loongarch_lasx_concat_128_s:
6903 case Intrinsic::loongarch_lasx_concat_128_d:
6904 case Intrinsic::loongarch_lasx_concat_128:
6906 N->getOperand(1),
N->getOperand(2));
6918 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
6930 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
6932 "Unexpected value type!");
6941 MVT VT =
N->getSimpleValueType(0);
6962 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
6975 APInt V =
C->getValueAPF().bitcastToAPInt();
6990 MVT VT =
N->getSimpleValueType(0);
7051 EVT VT =
N->getValueType(0);
7053 if (VT != MVT::f32 && VT != MVT::f64)
7055 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7057 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7080 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
7137 Subtarget.hasExtLASX() && N1.
hasOneUse())
7149 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
7159 EVT VT =
N.getValueType();
7176 switch (
N.getOpcode()) {
7192 EVT VT =
N->getValueType(0);
7205 switch (
N->getOpcode()) {
7224 case LoongArchISD::BITREV_W:
7226 case LoongArchISD::BR_CC:
7228 case LoongArchISD::SELECT_CC:
7232 case LoongArchISD::MOVGR2FR_W_LA64:
7234 case LoongArchISD::MOVFR2GR_S_LA64:
7236 case LoongArchISD::VMSKLTZ:
7237 case LoongArchISD::XVMSKLTZ:
7239 case LoongArchISD::SPLIT_PAIR_F64:
7241 case LoongArchISD::VANDN:
7265 MF->
insert(It, BreakMBB);
7269 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
7270 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
7282 MBB->addSuccessor(BreakMBB);
7283 MBB->addSuccessor(SinkMBB);
7289 BreakMBB->addSuccessor(SinkMBB);
7301 switch (
MI.getOpcode()) {
7304 case LoongArch::PseudoVBZ:
7305 CondOpc = LoongArch::VSETEQZ_V;
7307 case LoongArch::PseudoVBZ_B:
7308 CondOpc = LoongArch::VSETANYEQZ_B;
7310 case LoongArch::PseudoVBZ_H:
7311 CondOpc = LoongArch::VSETANYEQZ_H;
7313 case LoongArch::PseudoVBZ_W:
7314 CondOpc = LoongArch::VSETANYEQZ_W;
7316 case LoongArch::PseudoVBZ_D:
7317 CondOpc = LoongArch::VSETANYEQZ_D;
7319 case LoongArch::PseudoVBNZ:
7320 CondOpc = LoongArch::VSETNEZ_V;
7322 case LoongArch::PseudoVBNZ_B:
7323 CondOpc = LoongArch::VSETALLNEZ_B;
7325 case LoongArch::PseudoVBNZ_H:
7326 CondOpc = LoongArch::VSETALLNEZ_H;
7328 case LoongArch::PseudoVBNZ_W:
7329 CondOpc = LoongArch::VSETALLNEZ_W;
7331 case LoongArch::PseudoVBNZ_D:
7332 CondOpc = LoongArch::VSETALLNEZ_D;
7334 case LoongArch::PseudoXVBZ:
7335 CondOpc = LoongArch::XVSETEQZ_V;
7337 case LoongArch::PseudoXVBZ_B:
7338 CondOpc = LoongArch::XVSETANYEQZ_B;
7340 case LoongArch::PseudoXVBZ_H:
7341 CondOpc = LoongArch::XVSETANYEQZ_H;
7343 case LoongArch::PseudoXVBZ_W:
7344 CondOpc = LoongArch::XVSETANYEQZ_W;
7346 case LoongArch::PseudoXVBZ_D:
7347 CondOpc = LoongArch::XVSETANYEQZ_D;
7349 case LoongArch::PseudoXVBNZ:
7350 CondOpc = LoongArch::XVSETNEZ_V;
7352 case LoongArch::PseudoXVBNZ_B:
7353 CondOpc = LoongArch::XVSETALLNEZ_B;
7355 case LoongArch::PseudoXVBNZ_H:
7356 CondOpc = LoongArch::XVSETALLNEZ_H;
7358 case LoongArch::PseudoXVBNZ_W:
7359 CondOpc = LoongArch::XVSETALLNEZ_W;
7361 case LoongArch::PseudoXVBNZ_D:
7362 CondOpc = LoongArch::XVSETALLNEZ_D;
7377 F->insert(It, FalseBB);
7378 F->insert(It, TrueBB);
7379 F->insert(It, SinkBB);
7382 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
7411 MI.getOperand(0).getReg())
7418 MI.eraseFromParent();
7426 unsigned BroadcastOp;
7428 switch (
MI.getOpcode()) {
7431 case LoongArch::PseudoXVINSGR2VR_B:
7433 BroadcastOp = LoongArch::XVREPLGR2VR_B;
7434 InsOp = LoongArch::XVEXTRINS_B;
7436 case LoongArch::PseudoXVINSGR2VR_H:
7438 BroadcastOp = LoongArch::XVREPLGR2VR_H;
7439 InsOp = LoongArch::XVEXTRINS_H;
7451 unsigned Idx =
MI.getOperand(3).getImm();
7459 .
addReg(XSrc, {}, LoongArch::sub_128);
7461 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
7462 : LoongArch::VINSGR2VR_B),
7470 .
addImm(LoongArch::sub_128);
7477 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
7480 .
addImm(Idx >= HalfSize ? 48 : 18);
7485 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
7488 MI.eraseFromParent();
7495 assert(Subtarget.hasExtLSX());
7508 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
7509 : LoongArch::VINSGR2VR_W),
7516 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
7520 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
7521 : LoongArch::VPICKVE2GR_W),
7526 MI.eraseFromParent();
7540 unsigned EleBits = 8;
7541 unsigned NotOpc = 0;
7544 switch (
MI.getOpcode()) {
7547 case LoongArch::PseudoVMSKLTZ_B:
7548 MskOpc = LoongArch::VMSKLTZ_B;
7550 case LoongArch::PseudoVMSKLTZ_H:
7551 MskOpc = LoongArch::VMSKLTZ_H;
7554 case LoongArch::PseudoVMSKLTZ_W:
7555 MskOpc = LoongArch::VMSKLTZ_W;
7558 case LoongArch::PseudoVMSKLTZ_D:
7559 MskOpc = LoongArch::VMSKLTZ_D;
7562 case LoongArch::PseudoVMSKGEZ_B:
7563 MskOpc = LoongArch::VMSKGEZ_B;
7565 case LoongArch::PseudoVMSKEQZ_B:
7566 MskOpc = LoongArch::VMSKNZ_B;
7567 NotOpc = LoongArch::VNOR_V;
7569 case LoongArch::PseudoVMSKNEZ_B:
7570 MskOpc = LoongArch::VMSKNZ_B;
7572 case LoongArch::PseudoXVMSKLTZ_B:
7573 MskOpc = LoongArch::XVMSKLTZ_B;
7574 RC = &LoongArch::LASX256RegClass;
7576 case LoongArch::PseudoXVMSKLTZ_H:
7577 MskOpc = LoongArch::XVMSKLTZ_H;
7578 RC = &LoongArch::LASX256RegClass;
7581 case LoongArch::PseudoXVMSKLTZ_W:
7582 MskOpc = LoongArch::XVMSKLTZ_W;
7583 RC = &LoongArch::LASX256RegClass;
7586 case LoongArch::PseudoXVMSKLTZ_D:
7587 MskOpc = LoongArch::XVMSKLTZ_D;
7588 RC = &LoongArch::LASX256RegClass;
7591 case LoongArch::PseudoXVMSKGEZ_B:
7592 MskOpc = LoongArch::XVMSKGEZ_B;
7593 RC = &LoongArch::LASX256RegClass;
7595 case LoongArch::PseudoXVMSKEQZ_B:
7596 MskOpc = LoongArch::XVMSKNZ_B;
7597 NotOpc = LoongArch::XVNOR_V;
7598 RC = &LoongArch::LASX256RegClass;
7600 case LoongArch::PseudoXVMSKNEZ_B:
7601 MskOpc = LoongArch::XVMSKNZ_B;
7602 RC = &LoongArch::LASX256RegClass;
7617 if (
TRI->getRegSizeInBits(*RC) > 128) {
7627 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
7628 : LoongArch::BSTRINS_W),
7632 .
addImm(256 / EleBits - 1)
7640 MI.eraseFromParent();
7647 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
7648 "Unexpected instruction");
7660 MI.eraseFromParent();
7667 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
7668 "Unexpected instruction");
7684 MI.eraseFromParent();
7689 switch (
MI.getOpcode()) {
7692 case LoongArch::Select_GPR_Using_CC_GPR:
7728 if (
MI.getOperand(2).isReg())
7729 RHS =
MI.getOperand(2).getReg();
7730 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
7734 SelectDests.
insert(
MI.getOperand(0).getReg());
7738 SequenceMBBI !=
E; ++SequenceMBBI) {
7739 if (SequenceMBBI->isDebugInstr())
7742 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
7743 !SequenceMBBI->getOperand(2).isReg() ||
7744 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
7745 SequenceMBBI->getOperand(3).getImm() != CC ||
7746 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
7747 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
7749 LastSelectPseudo = &*SequenceMBBI;
7751 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
7754 if (SequenceMBBI->hasUnmodeledSideEffects() ||
7755 SequenceMBBI->mayLoadOrStore() ||
7756 SequenceMBBI->usesCustomInsertionHook())
7759 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
7774 F->insert(
I, IfFalseMBB);
7775 F->insert(
I, TailMBB);
7778 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
7784 TailMBB->
push_back(DebugInstr->removeFromParent());
7788 TailMBB->
splice(TailMBB->
end(), HeadMBB,
7798 if (
MI.getOperand(2).isImm())
7810 auto SelectMBBI =
MI.getIterator();
7811 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7813 while (SelectMBBI != SelectEnd) {
7814 auto Next = std::next(SelectMBBI);
7818 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7819 .
addReg(SelectMBBI->getOperand(4).getReg())
7821 .
addReg(SelectMBBI->getOperand(5).getReg())
7828 F->getProperties().resetNoPHIs();
7834 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7837 switch (
MI.getOpcode()) {
7840 case LoongArch::DIV_W:
7841 case LoongArch::DIV_WU:
7842 case LoongArch::MOD_W:
7843 case LoongArch::MOD_WU:
7844 case LoongArch::DIV_D:
7845 case LoongArch::DIV_DU:
7846 case LoongArch::MOD_D:
7847 case LoongArch::MOD_DU:
7850 case LoongArch::WRFCSR: {
7852 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7853 .
addReg(
MI.getOperand(1).getReg());
7854 MI.eraseFromParent();
7857 case LoongArch::RDFCSR: {
7858 MachineInstr *ReadFCSR =
7860 MI.getOperand(0).getReg())
7861 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
7863 MI.eraseFromParent();
7866 case LoongArch::Select_GPR_Using_CC_GPR:
7868 case LoongArch::BuildPairF64Pseudo:
7870 case LoongArch::SplitPairF64Pseudo:
7872 case LoongArch::PseudoVBZ:
7873 case LoongArch::PseudoVBZ_B:
7874 case LoongArch::PseudoVBZ_H:
7875 case LoongArch::PseudoVBZ_W:
7876 case LoongArch::PseudoVBZ_D:
7877 case LoongArch::PseudoVBNZ:
7878 case LoongArch::PseudoVBNZ_B:
7879 case LoongArch::PseudoVBNZ_H:
7880 case LoongArch::PseudoVBNZ_W:
7881 case LoongArch::PseudoVBNZ_D:
7882 case LoongArch::PseudoXVBZ:
7883 case LoongArch::PseudoXVBZ_B:
7884 case LoongArch::PseudoXVBZ_H:
7885 case LoongArch::PseudoXVBZ_W:
7886 case LoongArch::PseudoXVBZ_D:
7887 case LoongArch::PseudoXVBNZ:
7888 case LoongArch::PseudoXVBNZ_B:
7889 case LoongArch::PseudoXVBNZ_H:
7890 case LoongArch::PseudoXVBNZ_W:
7891 case LoongArch::PseudoXVBNZ_D:
7893 case LoongArch::PseudoXVINSGR2VR_B:
7894 case LoongArch::PseudoXVINSGR2VR_H:
7896 case LoongArch::PseudoCTPOP:
7898 case LoongArch::PseudoVMSKLTZ_B:
7899 case LoongArch::PseudoVMSKLTZ_H:
7900 case LoongArch::PseudoVMSKLTZ_W:
7901 case LoongArch::PseudoVMSKLTZ_D:
7902 case LoongArch::PseudoVMSKGEZ_B:
7903 case LoongArch::PseudoVMSKEQZ_B:
7904 case LoongArch::PseudoVMSKNEZ_B:
7905 case LoongArch::PseudoXVMSKLTZ_B:
7906 case LoongArch::PseudoXVMSKLTZ_H:
7907 case LoongArch::PseudoXVMSKLTZ_W:
7908 case LoongArch::PseudoXVMSKLTZ_D:
7909 case LoongArch::PseudoXVMSKGEZ_B:
7910 case LoongArch::PseudoXVMSKEQZ_B:
7911 case LoongArch::PseudoXVMSKNEZ_B:
7913 case TargetOpcode::STATEPOINT:
7919 MI.addOperand(*
MI.getMF(),
7921 LoongArch::R1,
true,
7924 if (!Subtarget.is64Bit())
7932 unsigned *
Fast)
const {
7933 if (!Subtarget.hasUAL())
7951 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7952 LoongArch::R10, LoongArch::R11};
7967 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
7968 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
7969 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
7970 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
7971 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
7972 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
7978 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7979 LoongArch::F6, LoongArch::F7};
7982 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7983 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7986 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7987 LoongArch::VR6, LoongArch::VR7};
7990 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7991 LoongArch::XR6, LoongArch::XR7};
7994 switch (State.getCallingConv()) {
7996 if (!State.isVarArg())
8000 return State.AllocateReg(
ArgGPRs);
8008 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
8010 unsigned GRLenInBytes = GRLen / 8;
8021 State.AllocateStack(GRLenInBytes, StackAlign),
8024 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8035 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8043 unsigned ValNo,
MVT ValVT,
8046 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
8047 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
8048 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
8053 if (IsRet && ValNo > 1)
8057 bool UseGPRForFloat =
true;
8067 UseGPRForFloat = ArgFlags.
isVarArg();
8080 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
8083 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
8084 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
8086 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
8092 State.getPendingArgFlags();
8095 "PendingLocs and PendingArgFlags out of sync");
8099 UseGPRForFloat =
true;
8101 if (UseGPRForFloat && ValVT == MVT::f32) {
8104 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
8107 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
8110 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
8152 PendingLocs.
size() <= 2) {
8153 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
8158 PendingLocs.
clear();
8159 PendingArgFlags.
clear();
8166 unsigned StoreSizeBytes = GRLen / 8;
8169 if (ValVT == MVT::f32 && !UseGPRForFloat) {
8171 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
8175 UseGPRForFloat =
false;
8176 StoreSizeBytes = 16;
8177 StackAlign =
Align(16);
8180 UseGPRForFloat =
false;
8181 StoreSizeBytes = 32;
8182 StackAlign =
Align(32);
8188 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
8192 if (!PendingLocs.
empty()) {
8194 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
8195 for (
auto &It : PendingLocs) {
8197 It.convertToReg(
Reg);
8202 PendingLocs.clear();
8203 PendingArgFlags.
clear();
8206 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
8207 "Expected an GRLenVT at this stage");
8224void LoongArchTargetLowering::analyzeInputArgs(
8227 LoongArchCCAssignFn Fn)
const {
8229 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
8230 MVT ArgVT = Ins[i].VT;
8231 Type *ArgTy =
nullptr;
8233 ArgTy = FType->getReturnType();
8234 else if (Ins[i].isOrigArg())
8235 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
8239 CCInfo, IsRet, ArgTy)) {
8240 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
8247void LoongArchTargetLowering::analyzeOutputArgs(
8250 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
8251 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8252 MVT ArgVT = Outs[i].VT;
8253 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
8257 CCInfo, IsRet, OrigTy)) {
8258 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
8277 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
8299 if (In.isOrigArg()) {
8304 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
8305 (
BitWidth < 32 && In.Flags.isZExt())) {
8355 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8368 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8372 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
8386 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
8398 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8402 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8403 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8404 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8411 if (LocVT == MVT::f32) {
8414 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
8415 LoongArch::F26, LoongArch::F27};
8422 if (LocVT == MVT::f64) {
8425 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
8426 LoongArch::F30_64, LoongArch::F31_64};
8457 "GHC calling convention requires the F and D extensions");
8461 MVT GRLenVT = Subtarget.getGRLenVT();
8462 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
8464 std::vector<SDValue> OutChains;
8473 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
8475 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
8492 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
8493 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
8494 assert(ArgPartOffset == 0);
8495 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
8497 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
8521 int VaArgOffset, VarArgsSaveSize;
8525 if (ArgRegs.
size() == Idx) {
8527 VarArgsSaveSize = 0;
8529 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
8530 VaArgOffset = -VarArgsSaveSize;
8536 LoongArchFI->setVarArgsFrameIndex(FI);
8544 VarArgsSaveSize += GRLenInBytes;
8549 for (
unsigned I = Idx;
I < ArgRegs.
size();
8550 ++
I, VaArgOffset += GRLenInBytes) {
8551 const Register Reg = RegInfo.createVirtualRegister(RC);
8552 RegInfo.addLiveIn(ArgRegs[
I], Reg);
8560 ->setValue((
Value *)
nullptr);
8561 OutChains.push_back(Store);
8563 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
8568 if (!OutChains.empty()) {
8569 OutChains.push_back(Chain);
8584 if (
N->getNumValues() != 1)
8586 if (!
N->hasNUsesOfValue(1, 0))
8589 SDNode *Copy = *
N->user_begin();
8595 if (Copy->getGluedNode())
8599 bool HasRet =
false;
8601 if (
Node->getOpcode() != LoongArchISD::RET)
8609 Chain = Copy->getOperand(0);
8614bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
8618 auto CalleeCC = CLI.CallConv;
8619 auto &Outs = CLI.Outs;
8621 auto CallerCC = Caller.getCallingConv();
8628 for (
auto &VA : ArgLocs)
8634 auto IsCallerStructRet = Caller.hasStructRetAttr();
8635 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
8636 if (IsCallerStructRet || IsCalleeStructRet)
8640 for (
auto &Arg : Outs)
8641 if (Arg.Flags.isByVal())
8646 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
8647 if (CalleeCC != CallerCC) {
8648 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
8649 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
8675 MVT GRLenVT = Subtarget.getGRLenVT();
8687 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
8691 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
8697 "site marked musttail");
8704 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8706 if (!Flags.isByVal())
8710 unsigned Size = Flags.getByValSize();
8711 Align Alignment = Flags.getNonZeroByValAlign();
8718 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
8720 false,
nullptr, std::nullopt,
8732 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8735 SDValue ArgValue = OutVals[OutIdx];
8743 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
8744 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8756 if (!StackPtr.getNode())
8768 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8783 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8784 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8785 assert(ArgPartOffset == 0);
8790 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8791 SDValue PartValue = OutVals[OutIdx + 1];
8792 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8807 for (
const auto &Part : Parts) {
8808 SDValue PartValue = Part.first;
8809 SDValue PartOffset = Part.second;
8816 ArgValue = SpillSlot;
8822 if (Flags.isByVal())
8823 ArgValue = ByValArgs[j++];
8830 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8831 "for passing parameters");
8834 if (!StackPtr.getNode())
8847 if (!MemOpChains.
empty())
8853 for (
auto &Reg : RegsToPass) {
8854 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8876 Ops.push_back(Chain);
8877 Ops.push_back(Callee);
8881 for (
auto &Reg : RegsToPass)
8882 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8887 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8888 assert(Mask &&
"Missing call preserved mask for calling convention");
8894 Ops.push_back(Glue);
8903 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
8906 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
8909 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8910 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
8932 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8935 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8936 auto &VA = RVLocs[i];
8944 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8945 assert(VA.needsCustom());
8950 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
8951 RetValue, RetValue2);
8964 const Type *RetTy)
const {
8966 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8968 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8972 Outs[i].Flags, CCInfo,
true,
nullptr))
8998 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8999 SDValue Val = OutVals[OutIdx];
9008 DAG.
getVTList(MVT::i32, MVT::i32), Val);
9012 Register RegHi = RVLocs[++i].getLocReg();
9037 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
9045 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
9048 if (SplatBitSize == 16 && !(V & 0x00FF)) {
9050 RequiredImm = (0b10101 << 8) | (V >> 8);
9051 return {
true, RequiredImm};
9052 }
else if (SplatBitSize == 32) {
9054 if (!(V & 0xFFFF00FF)) {
9055 RequiredImm = (0b10001 << 8) | (V >> 8);
9056 return {
true, RequiredImm};
9059 if (!(V & 0xFF00FFFF)) {
9060 RequiredImm = (0b10010 << 8) | (V >> 16);
9061 return {
true, RequiredImm};
9064 if (!(V & 0x00FFFFFF)) {
9065 RequiredImm = (0b10011 << 8) | (V >> 24);
9066 return {
true, RequiredImm};
9069 if ((V & 0xFFFF00FF) == 0xFF) {
9070 RequiredImm = (0b10110 << 8) | (V >> 8);
9071 return {
true, RequiredImm};
9074 if ((V & 0xFF00FFFF) == 0xFFFF) {
9075 RequiredImm = (0b10111 << 8) | (V >> 16);
9076 return {
true, RequiredImm};
9079 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
9081 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9082 return {
true, RequiredImm};
9084 }
else if (SplatBitSize == 64) {
9086 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
9087 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
9089 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9090 return {
true, RequiredImm};
9093 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
9094 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
9096 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
9097 return {
true, RequiredImm};
9100 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
9102 for (
int i = 0; i < 8; ++i) {
9104 if (
byte == 0 ||
byte == 0xFF)
9105 res |= ((
byte & 1) << i);
9112 auto [IsSame, Suffix] = sameBitsPreByte(V);
9114 RequiredImm = (0b11001 << 8) | Suffix;
9115 return {
true, RequiredImm};
9118 return {
false, RequiredImm};
9123 if (!Subtarget.hasExtLSX())
9126 if (VT == MVT::f32) {
9127 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
9128 return (masked == 0x3e000000 || masked == 0x40000000);
9131 if (VT == MVT::f64) {
9132 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
9133 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
9139bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
9140 bool ForCodeSize)
const {
9142 if (VT == MVT::f32 && !Subtarget.hasBasicF())
9144 if (VT == MVT::f64 && !Subtarget.hasBasicD())
9146 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
9157bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
9167 Type *Ty =
I->getOperand(0)->getType();
9169 unsigned Size = Ty->getIntegerBitWidth();
9189 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
9194 if (Subtarget.hasExtLASX())
9196 else if (Subtarget.hasExtLSX())
9203 EVT VT =
Y.getValueType();
9206 return Subtarget.hasExtLSX() && VT.
isInteger();
9217 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
9218 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
9219 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
9220 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
9223 Info.memVT = MVT::i32;
9224 Info.ptrVal =
I.getArgOperand(0);
9226 Info.align =
Align(4);
9245 "Unable to expand");
9246 unsigned MinWordSize = 4;
9258 Value *AlignedAddr = Builder.CreateIntrinsic(
9259 Intrinsic::ptrmask, {PtrTy, IntTy},
9260 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
9263 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
9264 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
9265 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
9266 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
9267 Value *Mask = Builder.CreateShl(
9268 ConstantInt::get(WordType,
9271 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
9272 Value *ValOperand_Shifted =
9273 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
9274 ShiftAmt,
"ValOperand_Shifted");
9277 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
9279 NewOperand = ValOperand_Shifted;
9282 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
9285 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
9286 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
9306 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
9314 if (Subtarget.hasLAMCAS()) {
9336 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
9338 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
9340 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
9342 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
9344 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
9346 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
9348 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
9350 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
9360 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
9362 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
9364 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
9366 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
9368 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
9370 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
9372 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
9374 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
9386 if (Subtarget.hasLAMCAS())
9398 unsigned GRLen = Subtarget.getGRLen();
9400 Value *FailureOrdering =
9401 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9402 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9404 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9405 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9406 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9407 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9410 Value *Result = Builder.CreateIntrinsic(
9411 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
9413 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9429 Builder.CreateNot(Mask,
"Inv_Mask"),
9436 unsigned GRLen = Subtarget.getGRLen();
9445 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
9446 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9447 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
9463 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
9464 Result = Builder.CreateCall(LlwOpScwLoop,
9465 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
9468 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
9472 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9495 const Constant *PersonalityFn)
const {
9496 return LoongArch::R4;
9500 const Constant *PersonalityFn)
const {
9501 return LoongArch::R5;
9512 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
9513 return RefinementSteps;
9518 assert(Subtarget.hasFrecipe() &&
9519 "Reciprocal estimate queried on unsupported target");
9530 return Subtarget.hasBasicD();
9534 return Subtarget.hasExtLSX();
9538 return Subtarget.hasExtLASX();
9547 int &RefinementSteps,
9548 bool &UseOneConstNR,
9549 bool Reciprocal)
const {
9551 "Enabled should never be Disabled here");
9553 if (!Subtarget.hasFrecipe())
9568 UseOneConstNR =
false;
9574 if (Reciprocal || RefinementSteps > 0)
9584 int &RefinementSteps)
const {
9586 "Enabled should never be Disabled here");
9588 if (!Subtarget.hasFrecipe())
9602 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
9610LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
9630 if (Constraint.
size() == 1) {
9631 switch (Constraint[0]) {
9647 if (Constraint ==
"ZC" || Constraint ==
"ZB")
9656 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
9663std::pair<unsigned, const TargetRegisterClass *>
9664LoongArchTargetLowering::getRegForInlineAsmConstraint(
9668 if (Constraint.
size() == 1) {
9669 switch (Constraint[0]) {
9674 return std::make_pair(0U, &LoongArch::GPRRegClass);
9676 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
9678 if (Subtarget.hasBasicF() && VT == MVT::f32)
9679 return std::make_pair(0U, &LoongArch::FPR32RegClass);
9680 if (Subtarget.hasBasicD() && VT == MVT::f64)
9681 return std::make_pair(0U, &LoongArch::FPR64RegClass);
9682 if (Subtarget.hasExtLSX() &&
9683 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
9684 return std::make_pair(0U, &LoongArch::LSX128RegClass);
9685 if (Subtarget.hasExtLASX() &&
9686 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
9687 return std::make_pair(0U, &LoongArch::LASX256RegClass);
9707 bool IsFP = Constraint[2] ==
'f';
9708 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
9709 std::pair<unsigned, const TargetRegisterClass *>
R;
9714 unsigned RegNo =
R.first;
9715 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
9716 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
9717 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
9718 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
9728void LoongArchTargetLowering::LowerAsmOperandForConstraint(
9732 if (Constraint.
size() == 1) {
9733 switch (Constraint[0]) {
9737 uint64_t CVal =
C->getSExtValue();
9740 Subtarget.getGRLenVT()));
9746 uint64_t CVal =
C->getSExtValue();
9749 Subtarget.getGRLenVT()));
9755 if (
C->getZExtValue() == 0)
9762 uint64_t CVal =
C->getZExtValue();
9775#define GET_REGISTER_MATCHER
9776#include "LoongArchGenAsmMatcher.inc"
9782 std::string NewRegName = Name.second.str();
9788 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
9789 if (!ReservedRegs.
test(Reg))
9806 const APInt &Imm = ConstNode->getAPIntValue();
9808 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
9809 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
9812 if (ConstNode->hasOneUse() &&
9813 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
9814 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
9820 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
9821 unsigned Shifts = Imm.countr_zero();
9827 APInt ImmPop = Imm.ashr(Shifts);
9828 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
9832 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
9833 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
9834 (ImmSmall - Imm).isPowerOf2())
9844 Type *Ty,
unsigned AS,
9899 EVT MemVT = LD->getMemoryVT();
9900 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
9911 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
9920 if (
Y.getValueType().isVector())
9932 Type *Ty,
bool IsSigned)
const {
9933 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
9942 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
9943 Type.getSizeInBits() < Subtarget.getGRLen()))
9953 Align &PrefAlign)
const {
9957 if (Subtarget.is64Bit()) {
9959 PrefAlign =
Align(8);
9962 PrefAlign =
Align(4);
9977bool LoongArchTargetLowering::splitValueIntoRegisterParts(
9979 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
9980 bool IsABIRegCopy = CC.has_value();
9983 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9984 PartVT == MVT::f32) {
9999SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
10001 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
10002 bool IsABIRegCopy = CC.has_value();
10004 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10005 PartVT == MVT::f32) {
10022 if (VT == MVT::f16 && Subtarget.hasBasicF())
10028unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
10031 if (VT == MVT::f16 && Subtarget.hasBasicF())
10040 unsigned Opc =
Op.getOpcode();
10045 case LoongArchISD::VPICK_ZEXT_ELT: {
10059 unsigned Depth)
const {
10060 EVT VT =
Op.getValueType();
10062 unsigned Opc =
Op.getOpcode();
10066 case LoongArchISD::VMSKLTZ:
10067 case LoongArchISD::XVMSKLTZ: {
10069 MVT SrcVT = Src.getSimpleValueType();
10074 if (OriginalDemandedBits.
countr_zero() >= NumElts)
10078 APInt KnownUndef, KnownZero;
10094 if (KnownSrc.
One[SrcBits - 1])
10096 else if (KnownSrc.
Zero[SrcBits - 1])
10101 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
10108 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
10131 unsigned Index)
const {
10140 unsigned Index)
const {
10144 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
static MCRegister MatchRegisterName(StringRef Name)
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static 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 Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
size_type count() const
count - Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void addSExt32Register(Register Reg)
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Kill
The last use of a register.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
unsigned getBitWidth() const
Get the bit width of this value.
void resetAll()
Resets the known state of all bits.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)