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()) {
249 if (Subtarget.is64Bit())
252 if (!Subtarget.hasBasicD()) {
254 if (Subtarget.is64Bit()) {
263 if (Subtarget.hasBasicD()) {
296 if (Subtarget.is64Bit())
302 if (Subtarget.hasExtLSX()) {
317 for (
MVT VT : LSXVTs) {
331 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
359 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
361 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
363 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
368 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
392 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
393 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
408 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
410 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
417 if (Subtarget.hasExtLASX()) {
418 for (
MVT VT : LASXVTs) {
433 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
462 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
464 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
466 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
470 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
489 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
494 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
498 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
503 if (Subtarget.hasBasicF()) {
514 if (Subtarget.hasExtLSX()) {
527 if (Subtarget.hasExtLASX()) {
554 if (Subtarget.hasLAMCAS())
557 if (Subtarget.hasSCQ()) {
577 switch (
Op.getOpcode()) {
579 return lowerATOMIC_FENCE(
Op, DAG);
581 return lowerEH_DWARF_CFA(
Op, DAG);
583 return lowerGlobalAddress(
Op, DAG);
585 return lowerGlobalTLSAddress(
Op, DAG);
587 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
589 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
591 return lowerINTRINSIC_VOID(
Op, DAG);
593 return lowerBlockAddress(
Op, DAG);
595 return lowerJumpTable(
Op, DAG);
597 return lowerShiftLeftParts(
Op, DAG);
599 return lowerShiftRightParts(
Op, DAG,
true);
601 return lowerShiftRightParts(
Op, DAG,
false);
603 return lowerConstantPool(
Op, DAG);
605 return lowerFP_TO_SINT(
Op, DAG);
607 return lowerFP_TO_UINT(
Op, DAG);
609 return lowerBITCAST(
Op, DAG);
611 return lowerUINT_TO_FP(
Op, DAG);
613 return lowerSINT_TO_FP(
Op, DAG);
615 return lowerVASTART(
Op, DAG);
617 return lowerFRAMEADDR(
Op, DAG);
619 return lowerRETURNADDR(
Op, DAG);
621 return lowerSET_ROUNDING(
Op, DAG);
623 return lowerWRITE_REGISTER(
Op, DAG);
625 return lowerINSERT_VECTOR_ELT(
Op, DAG);
627 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
629 return lowerBUILD_VECTOR(
Op, DAG);
631 return lowerCONCAT_VECTORS(
Op, DAG);
633 return lowerVECTOR_SHUFFLE(
Op, DAG);
635 return lowerBITREVERSE(
Op, DAG);
637 return lowerSCALAR_TO_VECTOR(
Op, DAG);
639 return lowerPREFETCH(
Op, DAG);
641 return lowerSELECT(
Op, DAG);
643 return lowerBRCOND(
Op, DAG);
645 return lowerFP_TO_FP16(
Op, DAG);
647 return lowerFP16_TO_FP(
Op, DAG);
649 return lowerFP_TO_BF16(
Op, DAG);
651 return lowerBF16_TO_FP(
Op, DAG);
653 return lowerVECREDUCE_ADD(
Op, DAG);
656 return lowerRotate(
Op, DAG);
664 return lowerVECREDUCE(
Op, DAG);
666 return lowerConstantFP(
Op, DAG);
668 return lowerSETCC(
Op, DAG);
670 return lowerFP_ROUND(
Op, DAG);
672 return lowerFP_EXTEND(
Op, DAG);
674 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
676 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
685 EVT VT = V.getValueType();
691 return V.getOperand(0);
695 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
697 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
707 if (!V->isOnlyUserOf(SplatValue.getNode()))
711 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
719 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
747 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
748 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
755 if (Opcode0 != Opcode1)
758 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
765 EVT VT =
N.getValueType();
779 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
780 SSVT0 == MVT::v4f64) {
799 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
800 N->getOpcode() == LoongArchISD::VPERMI) &&
801 Opcode0 == LoongArchISD::VFCVT) {
806 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
809 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
810 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
816 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
832 MVT VT =
Op.getSimpleValueType();
833 MVT SVT =
In.getSimpleValueType();
835 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
848 EVT VT =
Op.getValueType();
850 EVT SVT = Src.getValueType();
853 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
855 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
856 if (!V2F32ToV2F64 && !V4F32ToV4F64)
868 const uint64_t
Imm =
Op.getConstantOperandVal(1);
883 if (
SDValue V = CheckVecHighPart(Src)) {
885 "Unexpected wide vector");
886 Opcode = LoongArchISD::VFCVTH;
889 Opcode = LoongArchISD::VFCVTL;
891 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
896 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
902 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
914 EVT VT =
Op.getValueType();
919 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
920 (VT == MVT::f64 && Subtarget.hasBasicD()));
937 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
947 if (Subtarget.is64Bit())
949 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
950 : LoongArchISD::MOVGR2FR_W,
954 if (Subtarget.is64Bit()) {
956 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
960 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
972 EVT ResultVT =
Op.getValueType();
973 EVT OperandVT =
Op.getOperand(0).getValueType();
978 if (ResultVT == SetCCResultVT)
981 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
982 "SETCC operands must have the same type!");
986 Op.getOperand(1),
Op.getOperand(2));
988 if (ResultVT.
bitsGT(SetCCResultVT))
990 else if (ResultVT.
bitsLT(SetCCResultVT))
1002SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1006 MVT SrcVT = Src.getSimpleValueType();
1007 MVT DstVT =
Op.getSimpleValueType();
1018 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1038 MVT OpVT =
Op.getSimpleValueType();
1045 unsigned LegalVecSize = 128;
1046 bool isLASX256Vector =
1056 if (isLASX256Vector) {
1062 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1063 EleBits = std::min(EleBits, 64u);
1066 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1069 if (isLASX256Vector) {
1095 MVT OpVT =
Op.getSimpleValueType();
1108 MVT GRLenVT = Subtarget.getGRLenVT();
1110 for (
int i = NumEles; i > 1; i /= 2) {
1113 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1122 unsigned IsData =
Op.getConstantOperandVal(4);
1127 return Op.getOperand(0);
1134 MVT VT =
Op.getSimpleValueType();
1140 unsigned Opcode =
Op.getOpcode();
1143 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1149 CstSplatValue =
C->getAPIntValue();
1157 APInt CstSplatValue;
1158 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1162 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1178 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1194 if (
LHS == LHS2 &&
RHS == RHS2) {
1199 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1207 return std::nullopt;
1215 MVT VT =
N->getSimpleValueType(0);
1246 if (~TrueVal == FalseVal) {
1286 unsigned SelOpNo = 0;
1296 unsigned ConstSelOpNo = 1;
1297 unsigned OtherSelOpNo = 2;
1304 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1309 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1315 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1317 std::swap(NewConstOps[0], NewConstOps[1]);
1329 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1331 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1334 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1335 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1355 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1369 int64_t
C = RHSC->getSExtValue();
1412 MVT VT =
Op.getSimpleValueType();
1413 MVT GRLenVT = Subtarget.getGRLenVT();
1418 if (
Op.hasOneUse()) {
1419 unsigned UseOpc =
Op->user_begin()->getOpcode();
1421 SDNode *BinOp = *
Op->user_begin();
1428 return lowerSELECT(NewSel, DAG);
1445 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1468 if (TrueVal - 1 == FalseVal)
1470 if (TrueVal + 1 == FalseVal)
1477 RHS == TrueV &&
LHS == FalseV) {
1502 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1509 MVT GRLenVT = Subtarget.getGRLenVT();
1520 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1521 Op.getOperand(0),
LHS,
RHS, TargetCC,
1524 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1525 Op.getOperand(0), CondV,
Op.getOperand(2));
1529 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1535LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1538 MVT OpVT =
Op.getSimpleValueType();
1549 EVT ResTy =
Op->getValueType(0);
1554 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1564 for (
unsigned int i = 0; i < NewEltNum; i++) {
1567 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1568 ? (
unsigned)LoongArchISD::BITREV_8B
1586 for (
unsigned int i = 0; i < NewEltNum; i++)
1587 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1588 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1606 if (EltBits > 32 || EltBits == 1)
1634 int MaskOffset,
const APInt &Zeroable) {
1635 int Size = Mask.size();
1636 unsigned SizeInBits =
Size * ScalarSizeInBits;
1638 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1639 for (
int i = 0; i <
Size; i += Scale)
1640 for (
int j = 0; j < Shift; ++j)
1641 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1649 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1650 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1655 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1656 for (
int i = 0; i !=
Size; i += Scale) {
1657 unsigned Pos =
Left ? i + Shift : i;
1658 unsigned Low =
Left ? i : i + Shift;
1659 unsigned Len = Scale - Shift;
1664 int ShiftEltBits = ScalarSizeInBits * Scale;
1665 bool ByteShift = ShiftEltBits > 64;
1666 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1667 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1668 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1672 Scale = ByteShift ? Scale / 2 : Scale;
1678 return (
int)ShiftAmt;
1681 unsigned MaxWidth = 128;
1682 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1683 for (
int Shift = 1; Shift != Scale; ++Shift)
1684 for (
bool Left : {
true,
false})
1685 if (CheckZeros(Shift, Scale,
Left)) {
1686 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1711 const APInt &Zeroable) {
1712 int Size = Mask.size();
1726 Mask,
Size, Zeroable);
1734 "Illegal integer vector type");
1743template <
typename ValType>
1746 unsigned CheckStride,
1748 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1752 if (*
I != -1 && *
I != ExpectedIndex)
1754 ExpectedIndex += ExpectedIndexStride;
1758 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1770 int Size = Mask.size();
1779 int VectorSizeInBits =
V1.getValueSizeInBits();
1780 int ScalarSizeInBits = VectorSizeInBits /
Size;
1781 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1782 (void)ScalarSizeInBits;
1784 for (
int i = 0; i <
Size; ++i) {
1790 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1807 RepeatedMask.
assign(LaneSize, -1);
1808 int Size = Mask.size();
1809 for (
int i = 0; i <
Size; ++i) {
1810 assert(Mask[i] == -1 || Mask[i] >= 0);
1813 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1820 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1821 if (RepeatedMask[i % LaneSize] < 0)
1823 RepeatedMask[i % LaneSize] = LocalM;
1824 else if (RepeatedMask[i % LaneSize] != LocalM)
1841 int NumElts = RepeatedMask.
size();
1843 int Scale = 16 / NumElts;
1845 for (
int i = 0; i < NumElts; ++i) {
1846 int M = RepeatedMask[i];
1847 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1848 "Unexpected mask index.");
1853 int StartIdx = i - (M % NumElts);
1860 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1863 Rotation = CandidateRotation;
1864 else if (Rotation != CandidateRotation)
1879 else if (TargetV != MaskV)
1884 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1885 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1894 return Rotation * Scale;
1913 if (ByteRotation <= 0)
1920 int LoByteShift = 16 - ByteRotation;
1921 int HiByteShift = ByteRotation;
1944 const APInt &Zeroable) {
1958 for (
int i = 0; i < NumElements; i++) {
1962 if (i % Scale != 0) {
1974 M = M % NumElements;
1977 Offset = M - (i / Scale);
1980 if (
Offset % (NumElements / Scale))
1982 }
else if (InputV != V)
1985 if (M != (
Offset + (i / Scale)))
1995 unsigned VilVLoHi = LoongArchISD::VILVL;
1996 if (
Offset >= (NumElements / 2)) {
1997 VilVLoHi = LoongArchISD::VILVH;
1998 Offset -= (NumElements / 2);
2005 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2009 }
while (Scale > 1);
2015 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2016 NumExtElements *= 2) {
2036 int SplatIndex = -1;
2037 for (
const auto &M : Mask) {
2044 if (SplatIndex == -1)
2047 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2049 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2079 unsigned SubVecSize = 4;
2080 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2083 int SubMask[4] = {-1, -1, -1, -1};
2084 for (
unsigned i = 0; i < SubVecSize; ++i) {
2085 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2091 M -= 4 * (j / SubVecSize);
2092 if (M < 0 || M >= 4)
2098 if (SubMask[i] == -1)
2102 else if (M != -1 && M != SubMask[i])
2109 for (
int i = SubVecSize - 1; i >= 0; --i) {
2122 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2123 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2126 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2144 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2153 for (
int i = 0; i < WidenNumElts; ++i)
2154 WidenMask[i] = WidenNumElts - 1 - i;
2162 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2186 const auto &Begin = Mask.begin();
2187 const auto &End = Mask.end();
2204 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2226 const auto &Begin = Mask.begin();
2227 const auto &End = Mask.end();
2244 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2267 const auto &Begin = Mask.begin();
2268 const auto &End = Mask.end();
2269 unsigned HalfSize = Mask.size() / 2;
2287 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2310 const auto &Begin = Mask.begin();
2311 const auto &End = Mask.end();
2328 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2350 const auto &Begin = Mask.begin();
2351 const auto &Mid = Mask.begin() + Mask.size() / 2;
2352 const auto &End = Mask.end();
2370 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2392 const auto &Begin = Mask.begin();
2393 const auto &Mid = Mask.begin() + Mask.size() / 2;
2394 const auto &End = Mask.end();
2411 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2437 if (Mask.size() != NumElts)
2440 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2443 for (
unsigned i = 0; i < NumElts; ++i) {
2446 if (Mask[i] !=
int(
Base + i)) {
2459 int DiffMask = Mask[DiffPos];
2460 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2466 if (
unsigned(DiffMask) < NumElts) {
2471 SrcIdx =
unsigned(DiffMask) - NumElts;
2487 if (
SDValue Result = tryLowerToExtrAndIns(0))
2489 return tryLowerToExtrAndIns(NumElts);
2497 unsigned &MaskImm) {
2498 unsigned MaskSize = Mask.size();
2500 auto isValid = [&](
int M,
int Off) {
2501 return (M == -1) || (M >= Off && M < Off + 4);
2504 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2505 auto immPart = [&](
int M,
unsigned Off) {
2506 return (M == -1 ? 0 : (M - Off)) & 0x3;
2508 MaskImm |= immPart(MLo, Off) << (
I * 2);
2509 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2512 for (
unsigned i = 0; i < 4; i += 2) {
2514 int MHi = Mask[i + 1];
2516 if (MaskSize == 8) {
2517 int M2Lo = Mask[i + 4];
2518 int M2Hi = Mask[i + 5];
2519 if (M2Lo != MLo + 4 || M2Hi != MHi + 4)
2525 buildImm(MLo, MHi, 0, i);
2528 buildImm(MLo, MHi, MaskSize, i);
2558 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2563 unsigned MaskImm = 0;
2567 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2594 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2607 "Vector type is unsupported for lsx!");
2609 "Two operands have different types!");
2611 "Unexpected mask size for shuffle!");
2612 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2614 APInt KnownUndef, KnownZero;
2616 APInt Zeroable = KnownUndef | KnownZero;
2689 int SplatIndex = -1;
2690 for (
const auto &M : Mask) {
2697 if (SplatIndex == -1)
2700 const auto &Begin = Mask.begin();
2701 const auto &End = Mask.end();
2702 int HalfSize = Mask.size() / 2;
2704 if (SplatIndex >= HalfSize)
2707 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2711 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2725 if (Mask.size() == 4) {
2726 unsigned MaskImm = 0;
2727 for (
int i = 1; i >= 0; --i) {
2729 int MHi = Mask[i + 2];
2730 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2731 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2733 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2738 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2740 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2743 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2756 unsigned MaskSize = Mask.size();
2761 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2763 unsigned MaskImm = 0;
2767 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2772 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2773 unsigned MaskImm = 0;
2774 for (
unsigned i = 0; i < MaskSize; ++i) {
2777 if (Mask[i] >= (
int)MaskSize)
2779 MaskImm |= Mask[i] << (i * 2);
2782 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2794 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2798 unsigned HalfSize = NumElts / 2;
2799 bool FrontLo =
true, FrontHi =
true;
2800 bool BackLo =
true, BackHi =
true;
2802 auto inRange = [](
int val,
int low,
int high) {
2803 return (val == -1) || (val >= low && val < high);
2806 for (
unsigned i = 0; i < HalfSize; ++i) {
2807 int Fronti = Mask[i];
2808 int Backi = Mask[i + HalfSize];
2810 FrontLo &=
inRange(Fronti, 0, HalfSize);
2811 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2812 BackLo &=
inRange(Backi, 0, HalfSize);
2813 BackHi &=
inRange(Backi, HalfSize, NumElts);
2819 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2824 for (
unsigned i = 0; i < NumElts; ++i)
2829 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2851 const auto &Begin = Mask.begin();
2852 const auto &End = Mask.end();
2853 unsigned HalfSize = Mask.size() / 2;
2854 unsigned LeftSize = HalfSize / 2;
2862 Mask.size() + HalfSize - LeftSize, 1) &&
2864 Mask.size() + HalfSize + LeftSize, 1))
2875 Mask.size() + HalfSize - LeftSize, 1) &&
2877 Mask.size() + HalfSize + LeftSize, 1))
2882 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2890 const auto &Begin = Mask.begin();
2891 const auto &End = Mask.end();
2892 unsigned HalfSize = Mask.size() / 2;
2900 Mask.size() + HalfSize, 1))
2911 Mask.size() + HalfSize, 1))
2916 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2924 const auto &Begin = Mask.begin();
2925 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2926 const auto &Mid = Mask.begin() + Mask.size() / 2;
2927 const auto &RightMid = Mask.end() - Mask.size() / 4;
2928 const auto &End = Mask.end();
2929 unsigned HalfSize = Mask.size() / 2;
2951 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2959 const auto &Begin = Mask.begin();
2960 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2961 const auto &Mid = Mask.begin() + Mask.size() / 2;
2962 const auto &RightMid = Mask.end() - Mask.size() / 4;
2963 const auto &End = Mask.end();
2964 unsigned HalfSize = Mask.size() / 2;
2987 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2996 int HalfSize = NumElts / 2;
3000 if ((
int)Mask.size() != NumElts)
3003 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3005 for (
int i = 0; i < NumElts; ++i) {
3008 if (Mask[i] !=
Base + i) {
3010 if (DiffPos.
size() > 2)
3018 if (DiffPos.
size() == 1) {
3019 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3020 DiffPos.
push_back(DiffPos[0] + HalfSize);
3021 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3022 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3026 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3030 int DiffMaskLo = Mask[DiffPos[0]];
3031 int DiffMaskHi = Mask[DiffPos[1]];
3032 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3033 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3034 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3035 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3037 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3038 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3040 if (DiffMaskHi != DiffMaskLo + HalfSize)
3044 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3046 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3067 if (
SDValue Result = tryLowerToExtrAndIns(0))
3069 return tryLowerToExtrAndIns(NumElts);
3078 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3083 int MaskSize = Mask.size();
3089 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3091 for (
int i = 0; i < MaskSize; ++i) {
3092 if (Mask[i] ==
Base + i || Mask[i] == -1)
3094 if (Mask[i] != Replaced)
3105 int Idx = checkReplaceOne(0, MaskSize);
3107 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3111 Idx = checkReplaceOne(MaskSize, 0);
3113 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3124 int MaskSize = Mask.size();
3125 int HalfSize = Mask.size() / 2;
3126 const auto &Begin = Mask.begin();
3127 const auto &Mid = Mask.begin() + HalfSize;
3128 const auto &End = Mask.end();
3140 for (
auto it = Begin; it < Mid; it++) {
3143 else if ((*it >= 0 && *it < HalfSize) ||
3144 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3145 int M = *it < HalfSize ? *it : *it - HalfSize;
3150 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3152 for (
auto it = Mid; it < End; it++) {
3155 else if ((*it >= HalfSize && *it < MaskSize) ||
3156 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3157 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3162 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3166 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3194 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3196 int MaskSize = Mask.size();
3197 int HalfSize = Mask.size() / 2;
3200 HalfMaskType preMask =
None, postMask =
None;
3202 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3203 return M < 0 || (M >= 0 && M < HalfSize) ||
3204 (M >= MaskSize && M < MaskSize + HalfSize);
3206 preMask = HighLaneTy;
3207 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3208 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3209 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3211 preMask = LowLaneTy;
3213 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3214 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3215 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3217 postMask = LowLaneTy;
3218 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3219 return M < 0 || (M >= 0 && M < HalfSize) ||
3220 (M >= MaskSize && M < MaskSize + HalfSize);
3222 postMask = HighLaneTy;
3230 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3233 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3241 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3246 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3247 *it = *it < 0 ? *it : *it - HalfSize;
3249 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3250 *it = *it < 0 ? *it : *it + HalfSize;
3252 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3260 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3265 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3266 *it = *it < 0 ? *it : *it - HalfSize;
3268 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3276 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3281 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3282 *it = *it < 0 ? *it : *it + HalfSize;
3307 int Size = Mask.size();
3308 int LaneSize =
Size / 2;
3310 bool LaneCrossing[2] = {
false,
false};
3311 for (
int i = 0; i <
Size; ++i)
3312 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3313 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3316 if (!LaneCrossing[0] && !LaneCrossing[1])
3320 InLaneMask.
assign(Mask.begin(), Mask.end());
3321 for (
int i = 0; i <
Size; ++i) {
3322 int &M = InLaneMask[i];
3325 if (((M %
Size) / LaneSize) != (i / LaneSize))
3326 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3331 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3346 "Vector type is unsupported for lasx!");
3348 "Two operands have different types!");
3350 "Unexpected mask size for shuffle!");
3351 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3352 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3354 APInt KnownUndef, KnownZero;
3356 APInt Zeroable = KnownUndef | KnownZero;
3443 ArrayRef<int> OrigMask = SVOp->
getMask();
3446 MVT VT =
Op.getSimpleValueType();
3450 bool V1IsUndef =
V1.isUndef();
3451 bool V2IsUndef = V2.
isUndef();
3452 if (V1IsUndef && V2IsUndef)
3465 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3466 SmallVector<int, 8> NewMask(OrigMask);
3467 for (
int &M : NewMask)
3468 if (M >= NumElements)
3474 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3475 (void)MaskUpperLimit;
3477 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3478 "Out of bounds shuffle index");
3500 std::tie(Res, Chain) =
3501 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3502 if (Subtarget.is64Bit())
3503 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3515 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3519 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3520 CallOptions,
DL, Chain);
3526 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3532 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3533 if (Subtarget.is64Bit())
3534 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3540 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3541 MVT VT =
Op.getSimpleValueType();
3546 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3567 "Unsupported vector type for broadcast.");
3570 bool IsIdeneity =
true;
3572 for (
int i = 0; i !=
NumOps; i++) {
3574 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3586 auto ExtType = LN->getExtensionType();
3591 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3596 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3614 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3628 EVT ResTy,
unsigned first) {
3631 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3634 Node->op_begin() + first + NumElts);
3643 MVT VT =
Node->getSimpleValueType(0);
3644 EVT ResTy =
Op->getValueType(0);
3647 APInt SplatValue, SplatUndef;
3648 unsigned SplatBitSize;
3651 bool UseSameConstant =
true;
3656 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3657 (!Subtarget.hasExtLASX() || !Is256Vec))
3663 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3665 SplatBitSize <= 64) {
3667 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3671 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3678 if ((Is128Vec && ResTy == MVT::v4i32) ||
3679 (Is256Vec && ResTy == MVT::v8i32))
3685 switch (SplatBitSize) {
3689 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3692 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3695 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3698 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3706 if (ViaVecTy != ResTy)
3715 for (
unsigned i = 0; i < NumElts; ++i) {
3720 ConstantValue = Opi;
3721 else if (ConstantValue != Opi)
3722 UseSameConstant =
false;
3727 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3729 for (
unsigned i = 0; i < NumElts; ++i) {
3747 BitVector UndefElements;
3748 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3749 UndefElements.
count() == 0) {
3753 EVT FillTy = Is256Vec
3759 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3762 unsigned SplatLen = NumElts / SeqLen;
3768 if (SplatEltTy == MVT::i128)
3769 SplatTy = MVT::v4i64;
3777 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3778 : LoongArchISD::XVREPLVE0,
3779 DL, SplatTy, SrcVec);
3781 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3794 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3795 ResTy == MVT::v4f64) {
3796 unsigned NonUndefCount = 0;
3797 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3798 if (!
Node->getOperand(i).isUndef()) {
3800 if (NonUndefCount > 1)
3804 if (NonUndefCount == 1)
3817 VecTy, NumElts / 2);
3828 MVT ResVT =
Op.getSimpleValueType();
3836 unsigned NumFreezeUndef = 0;
3837 unsigned NumZero = 0;
3838 unsigned NumNonZero = 0;
3839 unsigned NonZeros = 0;
3840 SmallSet<SDValue, 4> Undefs;
3841 for (
unsigned i = 0; i != NumOperands; ++i) {
3856 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3863 if (NumNonZero > 2) {
3867 Ops.slice(0, NumOperands / 2));
3869 Ops.slice(NumOperands / 2));
3882 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3884 for (
unsigned i = 0; i != NumOperands; ++i) {
3885 if ((NonZeros & (1 << i)) == 0)
3896LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3898 MVT EltVT =
Op.getSimpleValueType();
3903 MVT GRLenVT = Subtarget.getGRLenVT();
3931 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3935 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3937 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3946 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3955LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3957 MVT VT =
Op.getSimpleValueType();
3980 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3982 for (
unsigned i = 0; i < NumElts; ++i) {
3990 for (
unsigned i = 0; i < NumElts; ++i) {
3999 for (
unsigned i = 0; i < NumElts; ++i)
4030 MVT GRLenVT = Subtarget.getGRLenVT();
4036 uint64_t
RM = CVal->getZExtValue();
4042 "rounding mode is not supported by LoongArch hardware",
4043 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4081 FCSRNo, RMValue, Chain);
4088 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4090 "On LA64, only 64-bit registers can be written.");
4091 return Op.getOperand(0);
4094 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4096 "On LA32, only 32-bit registers can be written.");
4097 return Op.getOperand(0);
4107 "be a constant integer");
4113 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4114 EVT VT =
Op.getValueType();
4117 unsigned Depth =
Op.getConstantOperandVal(0);
4118 int GRLenInBytes = Subtarget.getGRLen() / 8;
4121 int Offset = -(GRLenInBytes * 2);
4133 if (
Op.getConstantOperandVal(0) != 0) {
4135 "return address can only be determined for the current frame");
4141 MVT GRLenVT = Subtarget.getGRLenVT();
4153 auto Size = Subtarget.getGRLen() / 8;
4161 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4171 MachinePointerInfo(SV));
4178 EVT VT =
Op.getValueType();
4187 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4195 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4198 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4199 !Subtarget.hasBasicD() &&
"unexpected target features");
4203 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4207 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4217 EVT RetVT =
Op.getValueType();
4223 std::tie(Result, Chain) =
4230 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4231 !Subtarget.hasBasicD() &&
"unexpected target features");
4242 EVT RetVT =
Op.getValueType();
4248 std::tie(Result, Chain) =
4257 EVT VT =
Op.getValueType();
4261 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4262 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4264 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4266 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4269 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4283 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4284 !Subtarget.hasBasicD()) {
4286 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4296 if (!Subtarget.hasExtLSX())
4301 EVT VT =
Op.getValueType();
4302 EVT SrcVT = Src.getValueType();
4307 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4310 if (SrcVT == MVT::f32)
4332 N->getOffset(), Flags);
4340template <
class NodeTy>
4343 bool IsLocal)
const {
4354 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4435 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4437 const GlobalValue *GV =
N->getGlobal();
4449 unsigned Opc,
bool UseGOT,
4453 MVT GRLenVT = Subtarget.getGRLenVT();
4467 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4505 Args.emplace_back(Load, CallTy);
4508 TargetLowering::CallLoweringInfo CLI(DAG);
4523 const GlobalValue *GV =
N->getGlobal();
4537LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4544 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4547 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4560 return getDynamicTLSAddr(
N, DAG,
4561 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4562 : LoongArch::PseudoLA_TLS_GD,
4569 return getDynamicTLSAddr(
N, DAG,
4570 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4571 : LoongArch::PseudoLA_TLS_LD,
4576 return getStaticTLSAddr(
N, DAG,
4577 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4578 : LoongArch::PseudoLA_TLS_IE,
4585 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4589 return getTLSDescAddr(
N, DAG,
4590 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4591 : LoongArch::PseudoLA_TLS_DESC,
4595template <
unsigned N>
4600 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4601 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4603 ": argument out of range.");
4610LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4612 switch (
Op.getConstantOperandVal(0)) {
4615 case Intrinsic::thread_pointer: {
4619 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4620 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4621 case Intrinsic::loongarch_lsx_vreplvei_d:
4622 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4624 case Intrinsic::loongarch_lsx_vreplvei_w:
4625 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4626 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4627 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4628 case Intrinsic::loongarch_lasx_xvpickve_d:
4629 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4631 case Intrinsic::loongarch_lasx_xvinsve0_d:
4633 case Intrinsic::loongarch_lsx_vsat_b:
4634 case Intrinsic::loongarch_lsx_vsat_bu:
4635 case Intrinsic::loongarch_lsx_vrotri_b:
4636 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4637 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4638 case Intrinsic::loongarch_lsx_vsrlri_b:
4639 case Intrinsic::loongarch_lsx_vsrari_b:
4640 case Intrinsic::loongarch_lsx_vreplvei_h:
4641 case Intrinsic::loongarch_lasx_xvsat_b:
4642 case Intrinsic::loongarch_lasx_xvsat_bu:
4643 case Intrinsic::loongarch_lasx_xvrotri_b:
4644 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4645 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4646 case Intrinsic::loongarch_lasx_xvsrlri_b:
4647 case Intrinsic::loongarch_lasx_xvsrari_b:
4648 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4649 case Intrinsic::loongarch_lasx_xvpickve_w:
4650 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4652 case Intrinsic::loongarch_lasx_xvinsve0_w:
4654 case Intrinsic::loongarch_lsx_vsat_h:
4655 case Intrinsic::loongarch_lsx_vsat_hu:
4656 case Intrinsic::loongarch_lsx_vrotri_h:
4657 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4658 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4659 case Intrinsic::loongarch_lsx_vsrlri_h:
4660 case Intrinsic::loongarch_lsx_vsrari_h:
4661 case Intrinsic::loongarch_lsx_vreplvei_b:
4662 case Intrinsic::loongarch_lasx_xvsat_h:
4663 case Intrinsic::loongarch_lasx_xvsat_hu:
4664 case Intrinsic::loongarch_lasx_xvrotri_h:
4665 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4666 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4667 case Intrinsic::loongarch_lasx_xvsrlri_h:
4668 case Intrinsic::loongarch_lasx_xvsrari_h:
4669 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4671 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4672 case Intrinsic::loongarch_lsx_vsrani_b_h:
4673 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4674 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4675 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4676 case Intrinsic::loongarch_lsx_vssrani_b_h:
4677 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4678 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4679 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4680 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4681 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4682 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4683 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4684 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4685 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4686 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4687 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4688 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4689 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4690 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4691 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4692 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4693 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4694 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4696 case Intrinsic::loongarch_lsx_vsat_w:
4697 case Intrinsic::loongarch_lsx_vsat_wu:
4698 case Intrinsic::loongarch_lsx_vrotri_w:
4699 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4700 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4701 case Intrinsic::loongarch_lsx_vsrlri_w:
4702 case Intrinsic::loongarch_lsx_vsrari_w:
4703 case Intrinsic::loongarch_lsx_vslei_bu:
4704 case Intrinsic::loongarch_lsx_vslei_hu:
4705 case Intrinsic::loongarch_lsx_vslei_wu:
4706 case Intrinsic::loongarch_lsx_vslei_du:
4707 case Intrinsic::loongarch_lsx_vslti_bu:
4708 case Intrinsic::loongarch_lsx_vslti_hu:
4709 case Intrinsic::loongarch_lsx_vslti_wu:
4710 case Intrinsic::loongarch_lsx_vslti_du:
4711 case Intrinsic::loongarch_lsx_vbsll_v:
4712 case Intrinsic::loongarch_lsx_vbsrl_v:
4713 case Intrinsic::loongarch_lasx_xvsat_w:
4714 case Intrinsic::loongarch_lasx_xvsat_wu:
4715 case Intrinsic::loongarch_lasx_xvrotri_w:
4716 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4717 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4718 case Intrinsic::loongarch_lasx_xvsrlri_w:
4719 case Intrinsic::loongarch_lasx_xvsrari_w:
4720 case Intrinsic::loongarch_lasx_xvslei_bu:
4721 case Intrinsic::loongarch_lasx_xvslei_hu:
4722 case Intrinsic::loongarch_lasx_xvslei_wu:
4723 case Intrinsic::loongarch_lasx_xvslei_du:
4724 case Intrinsic::loongarch_lasx_xvslti_bu:
4725 case Intrinsic::loongarch_lasx_xvslti_hu:
4726 case Intrinsic::loongarch_lasx_xvslti_wu:
4727 case Intrinsic::loongarch_lasx_xvslti_du:
4728 case Intrinsic::loongarch_lasx_xvbsll_v:
4729 case Intrinsic::loongarch_lasx_xvbsrl_v:
4731 case Intrinsic::loongarch_lsx_vseqi_b:
4732 case Intrinsic::loongarch_lsx_vseqi_h:
4733 case Intrinsic::loongarch_lsx_vseqi_w:
4734 case Intrinsic::loongarch_lsx_vseqi_d:
4735 case Intrinsic::loongarch_lsx_vslei_b:
4736 case Intrinsic::loongarch_lsx_vslei_h:
4737 case Intrinsic::loongarch_lsx_vslei_w:
4738 case Intrinsic::loongarch_lsx_vslei_d:
4739 case Intrinsic::loongarch_lsx_vslti_b:
4740 case Intrinsic::loongarch_lsx_vslti_h:
4741 case Intrinsic::loongarch_lsx_vslti_w:
4742 case Intrinsic::loongarch_lsx_vslti_d:
4743 case Intrinsic::loongarch_lasx_xvseqi_b:
4744 case Intrinsic::loongarch_lasx_xvseqi_h:
4745 case Intrinsic::loongarch_lasx_xvseqi_w:
4746 case Intrinsic::loongarch_lasx_xvseqi_d:
4747 case Intrinsic::loongarch_lasx_xvslei_b:
4748 case Intrinsic::loongarch_lasx_xvslei_h:
4749 case Intrinsic::loongarch_lasx_xvslei_w:
4750 case Intrinsic::loongarch_lasx_xvslei_d:
4751 case Intrinsic::loongarch_lasx_xvslti_b:
4752 case Intrinsic::loongarch_lasx_xvslti_h:
4753 case Intrinsic::loongarch_lasx_xvslti_w:
4754 case Intrinsic::loongarch_lasx_xvslti_d:
4756 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4757 case Intrinsic::loongarch_lsx_vsrani_h_w:
4758 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4759 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4760 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4761 case Intrinsic::loongarch_lsx_vssrani_h_w:
4762 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4763 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4764 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4765 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4766 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4767 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4768 case Intrinsic::loongarch_lsx_vfrstpi_b:
4769 case Intrinsic::loongarch_lsx_vfrstpi_h:
4770 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4771 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4772 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4773 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4774 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4775 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4776 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4777 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4778 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4779 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4780 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4781 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4782 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4783 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4785 case Intrinsic::loongarch_lsx_vsat_d:
4786 case Intrinsic::loongarch_lsx_vsat_du:
4787 case Intrinsic::loongarch_lsx_vrotri_d:
4788 case Intrinsic::loongarch_lsx_vsrlri_d:
4789 case Intrinsic::loongarch_lsx_vsrari_d:
4790 case Intrinsic::loongarch_lasx_xvsat_d:
4791 case Intrinsic::loongarch_lasx_xvsat_du:
4792 case Intrinsic::loongarch_lasx_xvrotri_d:
4793 case Intrinsic::loongarch_lasx_xvsrlri_d:
4794 case Intrinsic::loongarch_lasx_xvsrari_d:
4796 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4797 case Intrinsic::loongarch_lsx_vsrani_w_d:
4798 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4799 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4800 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4801 case Intrinsic::loongarch_lsx_vssrani_w_d:
4802 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4803 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4804 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4805 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4806 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4807 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4808 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4809 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4810 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4811 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4812 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4813 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4814 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4815 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4816 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4817 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4818 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4819 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4821 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4822 case Intrinsic::loongarch_lsx_vsrani_d_q:
4823 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4824 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4825 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4826 case Intrinsic::loongarch_lsx_vssrani_d_q:
4827 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4828 case Intrinsic::loongarch_lsx_vssrani_du_q:
4829 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4830 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4831 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4832 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4833 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4834 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4835 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4836 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4837 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4838 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4839 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4840 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4841 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4842 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4843 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4844 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4846 case Intrinsic::loongarch_lsx_vnori_b:
4847 case Intrinsic::loongarch_lsx_vshuf4i_b:
4848 case Intrinsic::loongarch_lsx_vshuf4i_h:
4849 case Intrinsic::loongarch_lsx_vshuf4i_w:
4850 case Intrinsic::loongarch_lasx_xvnori_b:
4851 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4852 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4853 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4854 case Intrinsic::loongarch_lasx_xvpermi_d:
4856 case Intrinsic::loongarch_lsx_vshuf4i_d:
4857 case Intrinsic::loongarch_lsx_vpermi_w:
4858 case Intrinsic::loongarch_lsx_vbitseli_b:
4859 case Intrinsic::loongarch_lsx_vextrins_b:
4860 case Intrinsic::loongarch_lsx_vextrins_h:
4861 case Intrinsic::loongarch_lsx_vextrins_w:
4862 case Intrinsic::loongarch_lsx_vextrins_d:
4863 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4864 case Intrinsic::loongarch_lasx_xvpermi_w:
4865 case Intrinsic::loongarch_lasx_xvpermi_q:
4866 case Intrinsic::loongarch_lasx_xvbitseli_b:
4867 case Intrinsic::loongarch_lasx_xvextrins_b:
4868 case Intrinsic::loongarch_lasx_xvextrins_h:
4869 case Intrinsic::loongarch_lasx_xvextrins_w:
4870 case Intrinsic::loongarch_lasx_xvextrins_d:
4872 case Intrinsic::loongarch_lsx_vrepli_b:
4873 case Intrinsic::loongarch_lsx_vrepli_h:
4874 case Intrinsic::loongarch_lsx_vrepli_w:
4875 case Intrinsic::loongarch_lsx_vrepli_d:
4876 case Intrinsic::loongarch_lasx_xvrepli_b:
4877 case Intrinsic::loongarch_lasx_xvrepli_h:
4878 case Intrinsic::loongarch_lasx_xvrepli_w:
4879 case Intrinsic::loongarch_lasx_xvrepli_d:
4881 case Intrinsic::loongarch_lsx_vldi:
4882 case Intrinsic::loongarch_lasx_xvldi:
4898LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4901 MVT GRLenVT = Subtarget.getGRLenVT();
4902 EVT VT =
Op.getValueType();
4904 const StringRef ErrorMsgOOR =
"argument out of range";
4905 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4906 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4908 switch (
Op.getConstantOperandVal(1)) {
4911 case Intrinsic::loongarch_crc_w_b_w:
4912 case Intrinsic::loongarch_crc_w_h_w:
4913 case Intrinsic::loongarch_crc_w_w_w:
4914 case Intrinsic::loongarch_crc_w_d_w:
4915 case Intrinsic::loongarch_crcc_w_b_w:
4916 case Intrinsic::loongarch_crcc_w_h_w:
4917 case Intrinsic::loongarch_crcc_w_w_w:
4918 case Intrinsic::loongarch_crcc_w_d_w:
4920 case Intrinsic::loongarch_csrrd_w:
4921 case Intrinsic::loongarch_csrrd_d: {
4922 unsigned Imm =
Op.getConstantOperandVal(2);
4925 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4928 case Intrinsic::loongarch_csrwr_w:
4929 case Intrinsic::loongarch_csrwr_d: {
4930 unsigned Imm =
Op.getConstantOperandVal(3);
4933 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4934 {Chain,
Op.getOperand(2),
4937 case Intrinsic::loongarch_csrxchg_w:
4938 case Intrinsic::loongarch_csrxchg_d: {
4939 unsigned Imm =
Op.getConstantOperandVal(4);
4942 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4943 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4946 case Intrinsic::loongarch_iocsrrd_d: {
4948 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4951#define IOCSRRD_CASE(NAME, NODE) \
4952 case Intrinsic::loongarch_##NAME: { \
4953 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4954 {Chain, Op.getOperand(2)}); \
4960 case Intrinsic::loongarch_cpucfg: {
4961 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4962 {Chain,
Op.getOperand(2)});
4964 case Intrinsic::loongarch_lddir_d: {
4965 unsigned Imm =
Op.getConstantOperandVal(3);
4970 case Intrinsic::loongarch_movfcsr2gr: {
4971 if (!Subtarget.hasBasicF())
4973 unsigned Imm =
Op.getConstantOperandVal(2);
4976 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4979 case Intrinsic::loongarch_lsx_vld:
4980 case Intrinsic::loongarch_lsx_vldrepl_b:
4981 case Intrinsic::loongarch_lasx_xvld:
4982 case Intrinsic::loongarch_lasx_xvldrepl_b:
4986 case Intrinsic::loongarch_lsx_vldrepl_h:
4987 case Intrinsic::loongarch_lasx_xvldrepl_h:
4991 Op,
"argument out of range or not a multiple of 2", DAG)
4993 case Intrinsic::loongarch_lsx_vldrepl_w:
4994 case Intrinsic::loongarch_lasx_xvldrepl_w:
4998 Op,
"argument out of range or not a multiple of 4", DAG)
5000 case Intrinsic::loongarch_lsx_vldrepl_d:
5001 case Intrinsic::loongarch_lasx_xvldrepl_d:
5005 Op,
"argument out of range or not a multiple of 8", DAG)
5016 return Op.getOperand(0);
5022 MVT GRLenVT = Subtarget.getGRLenVT();
5024 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5026 const StringRef ErrorMsgOOR =
"argument out of range";
5027 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5028 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5029 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5031 switch (IntrinsicEnum) {
5035 case Intrinsic::loongarch_cacop_d:
5036 case Intrinsic::loongarch_cacop_w: {
5037 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5039 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5048 case Intrinsic::loongarch_dbar: {
5055 case Intrinsic::loongarch_ibar: {
5062 case Intrinsic::loongarch_break: {
5069 case Intrinsic::loongarch_movgr2fcsr: {
5070 if (!Subtarget.hasBasicF())
5080 case Intrinsic::loongarch_syscall: {
5087#define IOCSRWR_CASE(NAME, NODE) \
5088 case Intrinsic::loongarch_##NAME: { \
5089 SDValue Op3 = Op.getOperand(3); \
5090 return Subtarget.is64Bit() \
5091 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5092 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5093 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5094 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5101 case Intrinsic::loongarch_iocsrwr_d: {
5102 return !Subtarget.is64Bit()
5109#define ASRT_LE_GT_CASE(NAME) \
5110 case Intrinsic::loongarch_##NAME: { \
5111 return !Subtarget.is64Bit() \
5112 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5117#undef ASRT_LE_GT_CASE
5118 case Intrinsic::loongarch_ldpte_d: {
5119 unsigned Imm =
Op.getConstantOperandVal(3);
5120 return !Subtarget.is64Bit()
5125 case Intrinsic::loongarch_lsx_vst:
5126 case Intrinsic::loongarch_lasx_xvst:
5130 case Intrinsic::loongarch_lasx_xvstelm_b:
5135 case Intrinsic::loongarch_lsx_vstelm_b:
5140 case Intrinsic::loongarch_lasx_xvstelm_h:
5145 Op,
"argument out of range or not a multiple of 2", DAG)
5147 case Intrinsic::loongarch_lsx_vstelm_h:
5152 Op,
"argument out of range or not a multiple of 2", DAG)
5154 case Intrinsic::loongarch_lasx_xvstelm_w:
5159 Op,
"argument out of range or not a multiple of 4", DAG)
5161 case Intrinsic::loongarch_lsx_vstelm_w:
5166 Op,
"argument out of range or not a multiple of 4", DAG)
5168 case Intrinsic::loongarch_lasx_xvstelm_d:
5173 Op,
"argument out of range or not a multiple of 8", DAG)
5175 case Intrinsic::loongarch_lsx_vstelm_d:
5180 Op,
"argument out of range or not a multiple of 8", DAG)
5191 EVT VT =
Lo.getValueType();
5232 EVT VT =
Lo.getValueType();
5286 return LoongArchISD::DIV_W;
5288 return LoongArchISD::DIV_WU;
5290 return LoongArchISD::MOD_W;
5292 return LoongArchISD::MOD_WU;
5294 return LoongArchISD::SLL_W;
5296 return LoongArchISD::SRA_W;
5298 return LoongArchISD::SRL_W;
5301 return LoongArchISD::ROTR_W;
5303 return LoongArchISD::CTZ_W;
5305 return LoongArchISD::CLZ_W;
5324 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5325 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5329 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5335 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5362 StringRef ErrorMsg,
bool WithChain =
true) {
5367 Results.push_back(
N->getOperand(0));
5370template <
unsigned N>
5375 const StringRef ErrorMsgOOR =
"argument out of range";
5376 unsigned Imm =
Node->getConstantOperandVal(2);
5410 switch (
N->getConstantOperandVal(0)) {
5413 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5415 LoongArchISD::VPICK_SEXT_ELT);
5417 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5418 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5420 LoongArchISD::VPICK_SEXT_ELT);
5422 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5424 LoongArchISD::VPICK_SEXT_ELT);
5426 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5428 LoongArchISD::VPICK_ZEXT_ELT);
5430 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5431 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5433 LoongArchISD::VPICK_ZEXT_ELT);
5435 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5437 LoongArchISD::VPICK_ZEXT_ELT);
5439 case Intrinsic::loongarch_lsx_bz_b:
5440 case Intrinsic::loongarch_lsx_bz_h:
5441 case Intrinsic::loongarch_lsx_bz_w:
5442 case Intrinsic::loongarch_lsx_bz_d:
5443 case Intrinsic::loongarch_lasx_xbz_b:
5444 case Intrinsic::loongarch_lasx_xbz_h:
5445 case Intrinsic::loongarch_lasx_xbz_w:
5446 case Intrinsic::loongarch_lasx_xbz_d:
5448 LoongArchISD::VALL_ZERO);
5450 case Intrinsic::loongarch_lsx_bz_v:
5451 case Intrinsic::loongarch_lasx_xbz_v:
5453 LoongArchISD::VANY_ZERO);
5455 case Intrinsic::loongarch_lsx_bnz_b:
5456 case Intrinsic::loongarch_lsx_bnz_h:
5457 case Intrinsic::loongarch_lsx_bnz_w:
5458 case Intrinsic::loongarch_lsx_bnz_d:
5459 case Intrinsic::loongarch_lasx_xbnz_b:
5460 case Intrinsic::loongarch_lasx_xbnz_h:
5461 case Intrinsic::loongarch_lasx_xbnz_w:
5462 case Intrinsic::loongarch_lasx_xbnz_d:
5464 LoongArchISD::VALL_NONZERO);
5466 case Intrinsic::loongarch_lsx_bnz_v:
5467 case Intrinsic::loongarch_lasx_xbnz_v:
5469 LoongArchISD::VANY_NONZERO);
5477 assert(
N->getValueType(0) == MVT::i128 &&
5478 "AtomicCmpSwap on types less than 128 should be legal");
5482 switch (
MemOp->getMergedOrdering()) {
5486 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5490 Opcode = LoongArch::PseudoCmpXchg128;
5497 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5498 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5499 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5500 NewVal.first, NewVal.second,
N->getOperand(0)};
5503 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5514 EVT VT =
N->getValueType(0);
5515 switch (
N->getOpcode()) {
5520 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5521 "Unexpected custom legalisation");
5528 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5529 "Unexpected custom legalisation");
5531 Subtarget.hasDiv32() && VT == MVT::i32
5538 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5539 "Unexpected custom legalisation");
5547 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5548 "Unexpected custom legalisation");
5555 MVT VT =
N->getSimpleValueType(0);
5556 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5557 "Unexpected custom legalisation");
5559 "Unexpected type action!");
5564 Ld->getPointerInfo(), Ld->getBaseAlign(),
5565 Ld->getMemOperand()->getFlags());
5576 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5577 "Unexpected custom legalisation");
5584 if (Src.getValueType() == MVT::f16)
5595 EVT OpVT = Src.getValueType();
5599 std::tie(Result, Chain) =
5606 EVT SrcVT = Src.getValueType();
5607 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5608 Subtarget.hasBasicF()) {
5610 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5612 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5614 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5622 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5623 "Unexpected custom legalisation");
5626 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5631 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5632 "Unexpected custom legalisation");
5638 if (OpVT == MVT::v2f64) {
5648 assert((VT == MVT::i16 || VT == MVT::i32) &&
5649 "Unexpected custom legalization");
5650 MVT GRLenVT = Subtarget.getGRLenVT();
5657 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5662 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5670 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5671 "Unexpected custom legalization");
5672 MVT GRLenVT = Subtarget.getGRLenVT();
5679 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5682 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5690 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5691 "Unexpected custom legalisation");
5698 MVT GRLenVT = Subtarget.getGRLenVT();
5699 const StringRef ErrorMsgOOR =
"argument out of range";
5700 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5701 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5703 switch (
N->getConstantOperandVal(1)) {
5706 case Intrinsic::loongarch_movfcsr2gr: {
5707 if (!Subtarget.hasBasicF()) {
5717 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5724#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5725 case Intrinsic::loongarch_##NAME: { \
5726 SDValue NODE = DAG.getNode( \
5727 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5728 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5729 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5730 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5731 Results.push_back(NODE.getValue(1)); \
5740#undef CRC_CASE_EXT_BINARYOP
5742#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5743 case Intrinsic::loongarch_##NAME: { \
5744 SDValue NODE = DAG.getNode( \
5745 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5747 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5748 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5749 Results.push_back(NODE.getValue(1)); \
5754#undef CRC_CASE_EXT_UNARYOP
5755#define CSR_CASE(ID) \
5756 case Intrinsic::loongarch_##ID: { \
5757 if (!Subtarget.is64Bit()) \
5758 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5766 case Intrinsic::loongarch_csrrd_w: {
5773 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5780 case Intrinsic::loongarch_csrwr_w: {
5781 unsigned Imm =
N->getConstantOperandVal(3);
5787 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5795 case Intrinsic::loongarch_csrxchg_w: {
5796 unsigned Imm =
N->getConstantOperandVal(4);
5802 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5811#define IOCSRRD_CASE(NAME, NODE) \
5812 case Intrinsic::loongarch_##NAME: { \
5813 SDValue IOCSRRDResults = \
5814 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5815 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5816 Results.push_back( \
5817 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5818 Results.push_back(IOCSRRDResults.getValue(1)); \
5825 case Intrinsic::loongarch_cpucfg: {
5827 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5834 case Intrinsic::loongarch_lddir_d: {
5835 if (!Subtarget.is64Bit()) {
5845 if (Subtarget.is64Bit())
5847 "On LA64, only 64-bit registers can be read.");
5850 "On LA32, only 32-bit registers can be read.");
5852 Results.push_back(
N->getOperand(0));
5863 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5876 MVT VT =
N->getSimpleValueType(0);
5882 EVT InVT = In.getValueType();
5892 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5897 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
5900 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5909 for (
unsigned I = 0;
I < MinElts; ++
I)
5910 TruncMask[
I] = Scale *
I;
5912 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5913 MVT SVT = In.getSimpleValueType().getScalarType();
5919 "Illegal vector type in truncation");
5931 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
5934 EVT DstVT =
N->getValueType(0);
5936 MVT SrcVT = Src.getSimpleValueType();
5950 unsigned WidenSrcElts = 128 / SrcEltBits;
5957 unsigned FirstStageEltBits = 128 / NumElts;
5961 SrcVT = FirstStageVT;
5962 SrcEltBits = FirstStageEltBits;
5969 while (SrcEltBits < DstEltBits) {
5970 unsigned NextEltBits = SrcEltBits * 2;
5973 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
5991 Blocks = std::move(NextBlocks);
5992 SrcVT = NextBlockVT;
5993 SrcEltBits = NextEltBits;
6010 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6012 MVT VT =
N->getSimpleValueType(0);
6031 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6035 unsigned MinSizeInBits) {
6043 unsigned SplatBitSize;
6046 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6047 HasAnyUndefs, MinSizeInBits,
6059 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6070 unsigned EltIdx = IdxC->getZExtValue();
6072 Start = (int)EltIdx - (
int)(i * 2);
6073 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6079 else if (Src != CurSrc)
6083 if (!Src || Start < 0)
6093 if (!Subtarget.hasExtLSX())
6096 unsigned Opc =
N->getOpcode();
6099 EVT VT =
N->getValueType(0);
6106 unsigned ExtOpc =
LHS.getOpcode();
6114 if (ExtOpc !=
RHS.getOpcode())
6117 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6120 unsigned OddIdx, EvenIdx;
6124 if (!LHSVec || !RHSVec)
6126 if (OddIdx != 1 || EvenIdx != 0)
6136 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6149 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6151 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6153 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6165 EVT VT =
N->getValueType(0);
6231 if (
And.getOperand(0) ==
X) {
6260 if (ShiftVal != (SplatVal + 1))
6269 : LoongArchISD::VSRAR,
6279 SDValue FirstOperand =
N->getOperand(0);
6280 SDValue SecondOperand =
N->getOperand(1);
6281 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6282 EVT ValTy =
N->getValueType(0);
6285 unsigned SMIdx, SMLen;
6294 if (!Subtarget.has32S())
6350 NewOperand = FirstOperand;
6353 msb = lsb + SMLen - 1;
6357 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6371 EVT DstVT =
N.getValueType();
6378 EVT SrcVT = Src.getValueType();
6382 if (
N.getConstantOperandVal(1) != 0)
6398 if (NumElts % 2 != 0)
6404 for (
unsigned I = 0;
I != NumElts; ++
I) {
6417 SrcVT = Src.getValueType();
6427 }
else if (ThisSrc != Src) {
6431 unsigned Half = NumElts / 2;
6432 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6433 if (CI->getZExtValue() != ExpectedIdx)
6443 if (!Subtarget.hasExtLSX())
6448 EVT VT =
N->getValueType(0);
6455 unsigned ExtOpc =
LHS.getOpcode();
6463 if (!
LHS.hasOneUse())
6489 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6498 if (!Subtarget.has32S())
6510 SDValue FirstOperand =
N->getOperand(0);
6512 EVT ValTy =
N->getValueType(0);
6515 unsigned MaskIdx, MaskLen;
6530 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6531 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6555 switch (Src.getOpcode()) {
6558 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6568 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6581 switch (Src.getOpcode()) {
6591 Src.getOpcode(),
DL, SExtVT,
6597 DL, SExtVT, Src.getOperand(0),
6609 EVT VT =
N->getValueType(0);
6611 EVT SrcVT = Src.getValueType();
6613 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6618 EVT CmpVT = Src.getOperand(0).getValueType();
6623 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6636 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6641 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6646 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6651 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6653 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6658 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6660 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6665 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6682 EVT VT =
N->getValueType(0);
6684 EVT SrcVT = Src.getValueType();
6701 bool UseLASX =
false;
6702 bool PropagateSExt =
false;
6704 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6705 EVT CmpVT = Src.getOperand(0).getValueType();
6714 SExtVT = MVT::v2i64;
6717 SExtVT = MVT::v4i32;
6719 SExtVT = MVT::v4i64;
6721 PropagateSExt =
true;
6725 SExtVT = MVT::v8i16;
6727 SExtVT = MVT::v8i32;
6729 PropagateSExt =
true;
6733 SExtVT = MVT::v16i8;
6735 SExtVT = MVT::v16i16;
6737 PropagateSExt =
true;
6741 SExtVT = MVT::v32i8;
6749 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6750 if (Src.getSimpleValueType() == MVT::v32i8) {
6758 }
else if (UseLASX) {
6764 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6777 EVT ValTy =
N->getValueType(0);
6778 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6782 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6784 bool SwapAndRetried =
false;
6787 if (!Subtarget.has32S())
6793 if (ValBits != 32 && ValBits != 64)
6808 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6811 (MaskIdx0 + MaskLen0 <= ValBits)) {
6832 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6833 (MaskIdx0 + MaskLen0 <= ValBits)) {
6850 (MaskIdx0 + MaskLen0 <= 64) &&
6858 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6859 : (MaskIdx0 + MaskLen0 - 1),
6875 (MaskIdx0 + MaskLen0 <= ValBits)) {
6898 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6899 : (MaskIdx0 + MaskLen0 - 1),
6914 unsigned MaskIdx, MaskLen;
6915 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6924 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6942 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
6948 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6956 if (!SwapAndRetried) {
6958 SwapAndRetried =
true;
6962 SwapAndRetried =
false;
6979 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6988 if (!SwapAndRetried) {
6990 SwapAndRetried =
true;
7000 switch (V.getNode()->getOpcode()) {
7012 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7020 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7097 SDNode *AndNode =
N->getOperand(0).getNode();
7105 SDValue CmpInputValue =
N->getOperand(1);
7114 if (!CN || !CN->
isZero())
7116 AndInputValue1 = AndInputValue1.
getOperand(0);
7120 if (AndInputValue2 != CmpInputValue)
7153 TruncInputValue1, TruncInputValue2);
7155 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7168 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7171 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7196 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7224 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7257 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7258 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7274 EVT VT =
N->getValueType(0);
7277 if (TrueV == FalseV)
7308 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7309 {LHS, RHS, CC, TrueV, FalseV});
7314template <
unsigned N>
7318 bool IsSigned =
false) {
7322 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7323 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7325 ": argument out of range.");
7331template <
unsigned N>
7335 EVT ResTy =
Node->getValueType(0);
7339 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7340 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7342 ": argument out of range.");
7347 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7353 EVT ResTy =
Node->getValueType(0);
7361 EVT ResTy =
Node->getValueType(0);
7370template <
unsigned N>
7373 EVT ResTy =
Node->getValueType(0);
7378 ": argument out of range.");
7388template <
unsigned N>
7391 EVT ResTy =
Node->getValueType(0);
7396 ": argument out of range.");
7405template <
unsigned N>
7408 EVT ResTy =
Node->getValueType(0);
7413 ": argument out of range.");
7422template <
unsigned W>
7425 unsigned Imm =
N->getConstantOperandVal(2);
7427 const StringRef ErrorMsg =
"argument out of range";
7429 return DAG.
getUNDEF(
N->getValueType(0));
7435 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7443 switch (
N->getConstantOperandVal(0)) {
7446 case Intrinsic::loongarch_lsx_vadd_b:
7447 case Intrinsic::loongarch_lsx_vadd_h:
7448 case Intrinsic::loongarch_lsx_vadd_w:
7449 case Intrinsic::loongarch_lsx_vadd_d:
7450 case Intrinsic::loongarch_lasx_xvadd_b:
7451 case Intrinsic::loongarch_lasx_xvadd_h:
7452 case Intrinsic::loongarch_lasx_xvadd_w:
7453 case Intrinsic::loongarch_lasx_xvadd_d:
7456 case Intrinsic::loongarch_lsx_vaddi_bu:
7457 case Intrinsic::loongarch_lsx_vaddi_hu:
7458 case Intrinsic::loongarch_lsx_vaddi_wu:
7459 case Intrinsic::loongarch_lsx_vaddi_du:
7460 case Intrinsic::loongarch_lasx_xvaddi_bu:
7461 case Intrinsic::loongarch_lasx_xvaddi_hu:
7462 case Intrinsic::loongarch_lasx_xvaddi_wu:
7463 case Intrinsic::loongarch_lasx_xvaddi_du:
7466 case Intrinsic::loongarch_lsx_vsub_b:
7467 case Intrinsic::loongarch_lsx_vsub_h:
7468 case Intrinsic::loongarch_lsx_vsub_w:
7469 case Intrinsic::loongarch_lsx_vsub_d:
7470 case Intrinsic::loongarch_lasx_xvsub_b:
7471 case Intrinsic::loongarch_lasx_xvsub_h:
7472 case Intrinsic::loongarch_lasx_xvsub_w:
7473 case Intrinsic::loongarch_lasx_xvsub_d:
7476 case Intrinsic::loongarch_lsx_vsubi_bu:
7477 case Intrinsic::loongarch_lsx_vsubi_hu:
7478 case Intrinsic::loongarch_lsx_vsubi_wu:
7479 case Intrinsic::loongarch_lsx_vsubi_du:
7480 case Intrinsic::loongarch_lasx_xvsubi_bu:
7481 case Intrinsic::loongarch_lasx_xvsubi_hu:
7482 case Intrinsic::loongarch_lasx_xvsubi_wu:
7483 case Intrinsic::loongarch_lasx_xvsubi_du:
7486 case Intrinsic::loongarch_lsx_vneg_b:
7487 case Intrinsic::loongarch_lsx_vneg_h:
7488 case Intrinsic::loongarch_lsx_vneg_w:
7489 case Intrinsic::loongarch_lsx_vneg_d:
7490 case Intrinsic::loongarch_lasx_xvneg_b:
7491 case Intrinsic::loongarch_lasx_xvneg_h:
7492 case Intrinsic::loongarch_lasx_xvneg_w:
7493 case Intrinsic::loongarch_lasx_xvneg_d:
7497 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7499 SDLoc(
N),
N->getValueType(0)),
7501 case Intrinsic::loongarch_lsx_vmax_b:
7502 case Intrinsic::loongarch_lsx_vmax_h:
7503 case Intrinsic::loongarch_lsx_vmax_w:
7504 case Intrinsic::loongarch_lsx_vmax_d:
7505 case Intrinsic::loongarch_lasx_xvmax_b:
7506 case Intrinsic::loongarch_lasx_xvmax_h:
7507 case Intrinsic::loongarch_lasx_xvmax_w:
7508 case Intrinsic::loongarch_lasx_xvmax_d:
7511 case Intrinsic::loongarch_lsx_vmax_bu:
7512 case Intrinsic::loongarch_lsx_vmax_hu:
7513 case Intrinsic::loongarch_lsx_vmax_wu:
7514 case Intrinsic::loongarch_lsx_vmax_du:
7515 case Intrinsic::loongarch_lasx_xvmax_bu:
7516 case Intrinsic::loongarch_lasx_xvmax_hu:
7517 case Intrinsic::loongarch_lasx_xvmax_wu:
7518 case Intrinsic::loongarch_lasx_xvmax_du:
7521 case Intrinsic::loongarch_lsx_vmaxi_b:
7522 case Intrinsic::loongarch_lsx_vmaxi_h:
7523 case Intrinsic::loongarch_lsx_vmaxi_w:
7524 case Intrinsic::loongarch_lsx_vmaxi_d:
7525 case Intrinsic::loongarch_lasx_xvmaxi_b:
7526 case Intrinsic::loongarch_lasx_xvmaxi_h:
7527 case Intrinsic::loongarch_lasx_xvmaxi_w:
7528 case Intrinsic::loongarch_lasx_xvmaxi_d:
7531 case Intrinsic::loongarch_lsx_vmaxi_bu:
7532 case Intrinsic::loongarch_lsx_vmaxi_hu:
7533 case Intrinsic::loongarch_lsx_vmaxi_wu:
7534 case Intrinsic::loongarch_lsx_vmaxi_du:
7535 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7536 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7537 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7538 case Intrinsic::loongarch_lasx_xvmaxi_du:
7541 case Intrinsic::loongarch_lsx_vmin_b:
7542 case Intrinsic::loongarch_lsx_vmin_h:
7543 case Intrinsic::loongarch_lsx_vmin_w:
7544 case Intrinsic::loongarch_lsx_vmin_d:
7545 case Intrinsic::loongarch_lasx_xvmin_b:
7546 case Intrinsic::loongarch_lasx_xvmin_h:
7547 case Intrinsic::loongarch_lasx_xvmin_w:
7548 case Intrinsic::loongarch_lasx_xvmin_d:
7551 case Intrinsic::loongarch_lsx_vmin_bu:
7552 case Intrinsic::loongarch_lsx_vmin_hu:
7553 case Intrinsic::loongarch_lsx_vmin_wu:
7554 case Intrinsic::loongarch_lsx_vmin_du:
7555 case Intrinsic::loongarch_lasx_xvmin_bu:
7556 case Intrinsic::loongarch_lasx_xvmin_hu:
7557 case Intrinsic::loongarch_lasx_xvmin_wu:
7558 case Intrinsic::loongarch_lasx_xvmin_du:
7561 case Intrinsic::loongarch_lsx_vmini_b:
7562 case Intrinsic::loongarch_lsx_vmini_h:
7563 case Intrinsic::loongarch_lsx_vmini_w:
7564 case Intrinsic::loongarch_lsx_vmini_d:
7565 case Intrinsic::loongarch_lasx_xvmini_b:
7566 case Intrinsic::loongarch_lasx_xvmini_h:
7567 case Intrinsic::loongarch_lasx_xvmini_w:
7568 case Intrinsic::loongarch_lasx_xvmini_d:
7571 case Intrinsic::loongarch_lsx_vmini_bu:
7572 case Intrinsic::loongarch_lsx_vmini_hu:
7573 case Intrinsic::loongarch_lsx_vmini_wu:
7574 case Intrinsic::loongarch_lsx_vmini_du:
7575 case Intrinsic::loongarch_lasx_xvmini_bu:
7576 case Intrinsic::loongarch_lasx_xvmini_hu:
7577 case Intrinsic::loongarch_lasx_xvmini_wu:
7578 case Intrinsic::loongarch_lasx_xvmini_du:
7581 case Intrinsic::loongarch_lsx_vmul_b:
7582 case Intrinsic::loongarch_lsx_vmul_h:
7583 case Intrinsic::loongarch_lsx_vmul_w:
7584 case Intrinsic::loongarch_lsx_vmul_d:
7585 case Intrinsic::loongarch_lasx_xvmul_b:
7586 case Intrinsic::loongarch_lasx_xvmul_h:
7587 case Intrinsic::loongarch_lasx_xvmul_w:
7588 case Intrinsic::loongarch_lasx_xvmul_d:
7591 case Intrinsic::loongarch_lsx_vmadd_b:
7592 case Intrinsic::loongarch_lsx_vmadd_h:
7593 case Intrinsic::loongarch_lsx_vmadd_w:
7594 case Intrinsic::loongarch_lsx_vmadd_d:
7595 case Intrinsic::loongarch_lasx_xvmadd_b:
7596 case Intrinsic::loongarch_lasx_xvmadd_h:
7597 case Intrinsic::loongarch_lasx_xvmadd_w:
7598 case Intrinsic::loongarch_lasx_xvmadd_d: {
7599 EVT ResTy =
N->getValueType(0);
7604 case Intrinsic::loongarch_lsx_vmsub_b:
7605 case Intrinsic::loongarch_lsx_vmsub_h:
7606 case Intrinsic::loongarch_lsx_vmsub_w:
7607 case Intrinsic::loongarch_lsx_vmsub_d:
7608 case Intrinsic::loongarch_lasx_xvmsub_b:
7609 case Intrinsic::loongarch_lasx_xvmsub_h:
7610 case Intrinsic::loongarch_lasx_xvmsub_w:
7611 case Intrinsic::loongarch_lasx_xvmsub_d: {
7612 EVT ResTy =
N->getValueType(0);
7617 case Intrinsic::loongarch_lsx_vdiv_b:
7618 case Intrinsic::loongarch_lsx_vdiv_h:
7619 case Intrinsic::loongarch_lsx_vdiv_w:
7620 case Intrinsic::loongarch_lsx_vdiv_d:
7621 case Intrinsic::loongarch_lasx_xvdiv_b:
7622 case Intrinsic::loongarch_lasx_xvdiv_h:
7623 case Intrinsic::loongarch_lasx_xvdiv_w:
7624 case Intrinsic::loongarch_lasx_xvdiv_d:
7627 case Intrinsic::loongarch_lsx_vdiv_bu:
7628 case Intrinsic::loongarch_lsx_vdiv_hu:
7629 case Intrinsic::loongarch_lsx_vdiv_wu:
7630 case Intrinsic::loongarch_lsx_vdiv_du:
7631 case Intrinsic::loongarch_lasx_xvdiv_bu:
7632 case Intrinsic::loongarch_lasx_xvdiv_hu:
7633 case Intrinsic::loongarch_lasx_xvdiv_wu:
7634 case Intrinsic::loongarch_lasx_xvdiv_du:
7637 case Intrinsic::loongarch_lsx_vmod_b:
7638 case Intrinsic::loongarch_lsx_vmod_h:
7639 case Intrinsic::loongarch_lsx_vmod_w:
7640 case Intrinsic::loongarch_lsx_vmod_d:
7641 case Intrinsic::loongarch_lasx_xvmod_b:
7642 case Intrinsic::loongarch_lasx_xvmod_h:
7643 case Intrinsic::loongarch_lasx_xvmod_w:
7644 case Intrinsic::loongarch_lasx_xvmod_d:
7647 case Intrinsic::loongarch_lsx_vmod_bu:
7648 case Intrinsic::loongarch_lsx_vmod_hu:
7649 case Intrinsic::loongarch_lsx_vmod_wu:
7650 case Intrinsic::loongarch_lsx_vmod_du:
7651 case Intrinsic::loongarch_lasx_xvmod_bu:
7652 case Intrinsic::loongarch_lasx_xvmod_hu:
7653 case Intrinsic::loongarch_lasx_xvmod_wu:
7654 case Intrinsic::loongarch_lasx_xvmod_du:
7657 case Intrinsic::loongarch_lsx_vand_v:
7658 case Intrinsic::loongarch_lasx_xvand_v:
7661 case Intrinsic::loongarch_lsx_vor_v:
7662 case Intrinsic::loongarch_lasx_xvor_v:
7665 case Intrinsic::loongarch_lsx_vxor_v:
7666 case Intrinsic::loongarch_lasx_xvxor_v:
7669 case Intrinsic::loongarch_lsx_vnor_v:
7670 case Intrinsic::loongarch_lasx_xvnor_v: {
7675 case Intrinsic::loongarch_lsx_vandi_b:
7676 case Intrinsic::loongarch_lasx_xvandi_b:
7679 case Intrinsic::loongarch_lsx_vori_b:
7680 case Intrinsic::loongarch_lasx_xvori_b:
7683 case Intrinsic::loongarch_lsx_vxori_b:
7684 case Intrinsic::loongarch_lasx_xvxori_b:
7687 case Intrinsic::loongarch_lsx_vsll_b:
7688 case Intrinsic::loongarch_lsx_vsll_h:
7689 case Intrinsic::loongarch_lsx_vsll_w:
7690 case Intrinsic::loongarch_lsx_vsll_d:
7691 case Intrinsic::loongarch_lasx_xvsll_b:
7692 case Intrinsic::loongarch_lasx_xvsll_h:
7693 case Intrinsic::loongarch_lasx_xvsll_w:
7694 case Intrinsic::loongarch_lasx_xvsll_d:
7697 case Intrinsic::loongarch_lsx_vslli_b:
7698 case Intrinsic::loongarch_lasx_xvslli_b:
7701 case Intrinsic::loongarch_lsx_vslli_h:
7702 case Intrinsic::loongarch_lasx_xvslli_h:
7705 case Intrinsic::loongarch_lsx_vslli_w:
7706 case Intrinsic::loongarch_lasx_xvslli_w:
7709 case Intrinsic::loongarch_lsx_vslli_d:
7710 case Intrinsic::loongarch_lasx_xvslli_d:
7713 case Intrinsic::loongarch_lsx_vsrl_b:
7714 case Intrinsic::loongarch_lsx_vsrl_h:
7715 case Intrinsic::loongarch_lsx_vsrl_w:
7716 case Intrinsic::loongarch_lsx_vsrl_d:
7717 case Intrinsic::loongarch_lasx_xvsrl_b:
7718 case Intrinsic::loongarch_lasx_xvsrl_h:
7719 case Intrinsic::loongarch_lasx_xvsrl_w:
7720 case Intrinsic::loongarch_lasx_xvsrl_d:
7723 case Intrinsic::loongarch_lsx_vsrli_b:
7724 case Intrinsic::loongarch_lasx_xvsrli_b:
7727 case Intrinsic::loongarch_lsx_vsrli_h:
7728 case Intrinsic::loongarch_lasx_xvsrli_h:
7731 case Intrinsic::loongarch_lsx_vsrli_w:
7732 case Intrinsic::loongarch_lasx_xvsrli_w:
7735 case Intrinsic::loongarch_lsx_vsrli_d:
7736 case Intrinsic::loongarch_lasx_xvsrli_d:
7739 case Intrinsic::loongarch_lsx_vsra_b:
7740 case Intrinsic::loongarch_lsx_vsra_h:
7741 case Intrinsic::loongarch_lsx_vsra_w:
7742 case Intrinsic::loongarch_lsx_vsra_d:
7743 case Intrinsic::loongarch_lasx_xvsra_b:
7744 case Intrinsic::loongarch_lasx_xvsra_h:
7745 case Intrinsic::loongarch_lasx_xvsra_w:
7746 case Intrinsic::loongarch_lasx_xvsra_d:
7749 case Intrinsic::loongarch_lsx_vsrai_b:
7750 case Intrinsic::loongarch_lasx_xvsrai_b:
7753 case Intrinsic::loongarch_lsx_vsrai_h:
7754 case Intrinsic::loongarch_lasx_xvsrai_h:
7757 case Intrinsic::loongarch_lsx_vsrai_w:
7758 case Intrinsic::loongarch_lasx_xvsrai_w:
7761 case Intrinsic::loongarch_lsx_vsrai_d:
7762 case Intrinsic::loongarch_lasx_xvsrai_d:
7765 case Intrinsic::loongarch_lsx_vclz_b:
7766 case Intrinsic::loongarch_lsx_vclz_h:
7767 case Intrinsic::loongarch_lsx_vclz_w:
7768 case Intrinsic::loongarch_lsx_vclz_d:
7769 case Intrinsic::loongarch_lasx_xvclz_b:
7770 case Intrinsic::loongarch_lasx_xvclz_h:
7771 case Intrinsic::loongarch_lasx_xvclz_w:
7772 case Intrinsic::loongarch_lasx_xvclz_d:
7774 case Intrinsic::loongarch_lsx_vpcnt_b:
7775 case Intrinsic::loongarch_lsx_vpcnt_h:
7776 case Intrinsic::loongarch_lsx_vpcnt_w:
7777 case Intrinsic::loongarch_lsx_vpcnt_d:
7778 case Intrinsic::loongarch_lasx_xvpcnt_b:
7779 case Intrinsic::loongarch_lasx_xvpcnt_h:
7780 case Intrinsic::loongarch_lasx_xvpcnt_w:
7781 case Intrinsic::loongarch_lasx_xvpcnt_d:
7783 case Intrinsic::loongarch_lsx_vbitclr_b:
7784 case Intrinsic::loongarch_lsx_vbitclr_h:
7785 case Intrinsic::loongarch_lsx_vbitclr_w:
7786 case Intrinsic::loongarch_lsx_vbitclr_d:
7787 case Intrinsic::loongarch_lasx_xvbitclr_b:
7788 case Intrinsic::loongarch_lasx_xvbitclr_h:
7789 case Intrinsic::loongarch_lasx_xvbitclr_w:
7790 case Intrinsic::loongarch_lasx_xvbitclr_d:
7792 case Intrinsic::loongarch_lsx_vbitclri_b:
7793 case Intrinsic::loongarch_lasx_xvbitclri_b:
7795 case Intrinsic::loongarch_lsx_vbitclri_h:
7796 case Intrinsic::loongarch_lasx_xvbitclri_h:
7798 case Intrinsic::loongarch_lsx_vbitclri_w:
7799 case Intrinsic::loongarch_lasx_xvbitclri_w:
7801 case Intrinsic::loongarch_lsx_vbitclri_d:
7802 case Intrinsic::loongarch_lasx_xvbitclri_d:
7804 case Intrinsic::loongarch_lsx_vbitset_b:
7805 case Intrinsic::loongarch_lsx_vbitset_h:
7806 case Intrinsic::loongarch_lsx_vbitset_w:
7807 case Intrinsic::loongarch_lsx_vbitset_d:
7808 case Intrinsic::loongarch_lasx_xvbitset_b:
7809 case Intrinsic::loongarch_lasx_xvbitset_h:
7810 case Intrinsic::loongarch_lasx_xvbitset_w:
7811 case Intrinsic::loongarch_lasx_xvbitset_d: {
7812 EVT VecTy =
N->getValueType(0);
7818 case Intrinsic::loongarch_lsx_vbitseti_b:
7819 case Intrinsic::loongarch_lasx_xvbitseti_b:
7821 case Intrinsic::loongarch_lsx_vbitseti_h:
7822 case Intrinsic::loongarch_lasx_xvbitseti_h:
7824 case Intrinsic::loongarch_lsx_vbitseti_w:
7825 case Intrinsic::loongarch_lasx_xvbitseti_w:
7827 case Intrinsic::loongarch_lsx_vbitseti_d:
7828 case Intrinsic::loongarch_lasx_xvbitseti_d:
7830 case Intrinsic::loongarch_lsx_vbitrev_b:
7831 case Intrinsic::loongarch_lsx_vbitrev_h:
7832 case Intrinsic::loongarch_lsx_vbitrev_w:
7833 case Intrinsic::loongarch_lsx_vbitrev_d:
7834 case Intrinsic::loongarch_lasx_xvbitrev_b:
7835 case Intrinsic::loongarch_lasx_xvbitrev_h:
7836 case Intrinsic::loongarch_lasx_xvbitrev_w:
7837 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7838 EVT VecTy =
N->getValueType(0);
7844 case Intrinsic::loongarch_lsx_vbitrevi_b:
7845 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7847 case Intrinsic::loongarch_lsx_vbitrevi_h:
7848 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7850 case Intrinsic::loongarch_lsx_vbitrevi_w:
7851 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7853 case Intrinsic::loongarch_lsx_vbitrevi_d:
7854 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7856 case Intrinsic::loongarch_lsx_vfadd_s:
7857 case Intrinsic::loongarch_lsx_vfadd_d:
7858 case Intrinsic::loongarch_lasx_xvfadd_s:
7859 case Intrinsic::loongarch_lasx_xvfadd_d:
7862 case Intrinsic::loongarch_lsx_vfsub_s:
7863 case Intrinsic::loongarch_lsx_vfsub_d:
7864 case Intrinsic::loongarch_lasx_xvfsub_s:
7865 case Intrinsic::loongarch_lasx_xvfsub_d:
7868 case Intrinsic::loongarch_lsx_vfmul_s:
7869 case Intrinsic::loongarch_lsx_vfmul_d:
7870 case Intrinsic::loongarch_lasx_xvfmul_s:
7871 case Intrinsic::loongarch_lasx_xvfmul_d:
7874 case Intrinsic::loongarch_lsx_vfdiv_s:
7875 case Intrinsic::loongarch_lsx_vfdiv_d:
7876 case Intrinsic::loongarch_lasx_xvfdiv_s:
7877 case Intrinsic::loongarch_lasx_xvfdiv_d:
7880 case Intrinsic::loongarch_lsx_vfmadd_s:
7881 case Intrinsic::loongarch_lsx_vfmadd_d:
7882 case Intrinsic::loongarch_lasx_xvfmadd_s:
7883 case Intrinsic::loongarch_lasx_xvfmadd_d:
7885 N->getOperand(2),
N->getOperand(3));
7886 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7888 N->getOperand(1),
N->getOperand(2),
7890 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7891 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7893 N->getOperand(1),
N->getOperand(2),
7895 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7896 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7898 N->getOperand(1),
N->getOperand(2),
7900 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7902 N->getOperand(1),
N->getOperand(2),
7904 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7905 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7906 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7907 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7908 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7909 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7910 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7911 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7912 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7915 case Intrinsic::loongarch_lsx_vreplve_b:
7916 case Intrinsic::loongarch_lsx_vreplve_h:
7917 case Intrinsic::loongarch_lsx_vreplve_w:
7918 case Intrinsic::loongarch_lsx_vreplve_d:
7919 case Intrinsic::loongarch_lasx_xvreplve_b:
7920 case Intrinsic::loongarch_lasx_xvreplve_h:
7921 case Intrinsic::loongarch_lasx_xvreplve_w:
7922 case Intrinsic::loongarch_lasx_xvreplve_d:
7923 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7927 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7931 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7932 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7936 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7940 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7944 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
7945 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
7949 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
7953 case Intrinsic::loongarch_lsx_bz_b:
7954 case Intrinsic::loongarch_lsx_bz_h:
7955 case Intrinsic::loongarch_lsx_bz_w:
7956 case Intrinsic::loongarch_lsx_bz_d:
7957 case Intrinsic::loongarch_lasx_xbz_b:
7958 case Intrinsic::loongarch_lasx_xbz_h:
7959 case Intrinsic::loongarch_lasx_xbz_w:
7960 case Intrinsic::loongarch_lasx_xbz_d:
7962 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
7965 case Intrinsic::loongarch_lsx_bz_v:
7966 case Intrinsic::loongarch_lasx_xbz_v:
7968 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7971 case Intrinsic::loongarch_lsx_bnz_b:
7972 case Intrinsic::loongarch_lsx_bnz_h:
7973 case Intrinsic::loongarch_lsx_bnz_w:
7974 case Intrinsic::loongarch_lsx_bnz_d:
7975 case Intrinsic::loongarch_lasx_xbnz_b:
7976 case Intrinsic::loongarch_lasx_xbnz_h:
7977 case Intrinsic::loongarch_lasx_xbnz_w:
7978 case Intrinsic::loongarch_lasx_xbnz_d:
7980 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7983 case Intrinsic::loongarch_lsx_bnz_v:
7984 case Intrinsic::loongarch_lasx_xbnz_v:
7986 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7989 case Intrinsic::loongarch_lasx_concat_128_s:
7990 case Intrinsic::loongarch_lasx_concat_128_d:
7991 case Intrinsic::loongarch_lasx_concat_128:
7993 N->getOperand(1),
N->getOperand(2));
8005 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8017 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8019 "Unexpected value type!");
8028 MVT VT =
N->getSimpleValueType(0);
8049 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8062 APInt V =
C->getValueAPF().bitcastToAPInt();
8077 MVT VT =
N->getSimpleValueType(0);
8136 EVT VT =
N->getValueType(0);
8138 EVT SrcVT = Src.getValueType();
8144 if (SrcEltBits >= DstEltBits)
8151 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8158 EVT VT =
N->getValueType(0);
8164 if (VT != MVT::f32 && VT != MVT::f64)
8166 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8168 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8191 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
8201 EVT VT =
N->getValueType(0);
8218 if (!Subtarget.hasExtLSX())
8222 EVT DstVT =
N->getValueType(0);
8224 EVT SrcVT = Src.getValueType();
8234 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8239 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8242 if (DstEltBits < 32) {
8248 if (SrcEltBits != 64 || DstEltBits != 32)
8253 if (Subtarget.hasExtLASX())
8261 unsigned BlockNumElts = BlockBits / 64;
8264 Src.getOperand(0).getValueType() == BlockVT) {
8265 for (
unsigned i = 0; i < Src.getNumOperands(); i++)
8267 }
else if (SrcBits > BlockBits) {
8269 for (
unsigned i = 0; i < SrcBits / BlockBits; i++)
8274 BlockBits = SrcBits;
8278 MVT NativeVT = BlockBits == 256 ? MVT::v8i32 : MVT::v4i32;
8280 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8285 if (BlockBits == 256) {
8295 if (Blocks.
size() == 1)
8352 Subtarget.hasExtLASX() && N1.
hasOneUse())
8364 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8374 EVT VT =
N.getValueType();
8391 switch (
N.getOpcode()) {
8407 EVT VT =
N->getValueType(0);
8422 EVT VT =
N->getValueType(0);
8424 if (VT.
isVector() &&
N->getNumOperands() == 2)
8437 EVT VT =
N->getValueType(0);
8449 SDValue TrueVal =
N->getOperand(1);
8450 SDValue FalseVal =
N->getOperand(2);
8484 if (FalseVal.getOpcode() !=
ISD::ADD)
8487 SDValue Add0 = FalseVal.getOperand(0);
8488 SDValue Add1 = FalseVal.getOperand(1);
8558 : LoongArchISD::VSRAR,
8565 switch (
N->getOpcode()) {
8595 case LoongArchISD::BITREV_W:
8597 case LoongArchISD::BR_CC:
8599 case LoongArchISD::SELECT_CC:
8603 case LoongArchISD::MOVGR2FR_W_LA64:
8605 case LoongArchISD::MOVFR2GR_S_LA64:
8607 case LoongArchISD::CRC_W_B_W:
8608 case LoongArchISD::CRC_W_H_W:
8609 case LoongArchISD::CRCC_W_B_W:
8610 case LoongArchISD::CRCC_W_H_W:
8611 case LoongArchISD::VMSKLTZ:
8612 case LoongArchISD::XVMSKLTZ:
8614 case LoongArchISD::SPLIT_PAIR_F64:
8616 case LoongArchISD::VANDN:
8622 case LoongArchISD::VPACKEV:
8623 case LoongArchISD::VPERMI:
8649 MF->
insert(It, BreakMBB);
8653 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8654 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
8666 MBB->addSuccessor(BreakMBB);
8667 MBB->addSuccessor(SinkMBB);
8673 BreakMBB->addSuccessor(SinkMBB);
8685 switch (
MI.getOpcode()) {
8688 case LoongArch::PseudoVBZ:
8689 CondOpc = LoongArch::VSETEQZ_V;
8691 case LoongArch::PseudoVBZ_B:
8692 CondOpc = LoongArch::VSETANYEQZ_B;
8694 case LoongArch::PseudoVBZ_H:
8695 CondOpc = LoongArch::VSETANYEQZ_H;
8697 case LoongArch::PseudoVBZ_W:
8698 CondOpc = LoongArch::VSETANYEQZ_W;
8700 case LoongArch::PseudoVBZ_D:
8701 CondOpc = LoongArch::VSETANYEQZ_D;
8703 case LoongArch::PseudoVBNZ:
8704 CondOpc = LoongArch::VSETNEZ_V;
8706 case LoongArch::PseudoVBNZ_B:
8707 CondOpc = LoongArch::VSETALLNEZ_B;
8709 case LoongArch::PseudoVBNZ_H:
8710 CondOpc = LoongArch::VSETALLNEZ_H;
8712 case LoongArch::PseudoVBNZ_W:
8713 CondOpc = LoongArch::VSETALLNEZ_W;
8715 case LoongArch::PseudoVBNZ_D:
8716 CondOpc = LoongArch::VSETALLNEZ_D;
8718 case LoongArch::PseudoXVBZ:
8719 CondOpc = LoongArch::XVSETEQZ_V;
8721 case LoongArch::PseudoXVBZ_B:
8722 CondOpc = LoongArch::XVSETANYEQZ_B;
8724 case LoongArch::PseudoXVBZ_H:
8725 CondOpc = LoongArch::XVSETANYEQZ_H;
8727 case LoongArch::PseudoXVBZ_W:
8728 CondOpc = LoongArch::XVSETANYEQZ_W;
8730 case LoongArch::PseudoXVBZ_D:
8731 CondOpc = LoongArch::XVSETANYEQZ_D;
8733 case LoongArch::PseudoXVBNZ:
8734 CondOpc = LoongArch::XVSETNEZ_V;
8736 case LoongArch::PseudoXVBNZ_B:
8737 CondOpc = LoongArch::XVSETALLNEZ_B;
8739 case LoongArch::PseudoXVBNZ_H:
8740 CondOpc = LoongArch::XVSETALLNEZ_H;
8742 case LoongArch::PseudoXVBNZ_W:
8743 CondOpc = LoongArch::XVSETALLNEZ_W;
8745 case LoongArch::PseudoXVBNZ_D:
8746 CondOpc = LoongArch::XVSETALLNEZ_D;
8761 F->insert(It, FalseBB);
8762 F->insert(It, TrueBB);
8763 F->insert(It, SinkBB);
8766 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
8795 MI.getOperand(0).getReg())
8802 MI.eraseFromParent();
8810 unsigned BroadcastOp;
8812 switch (
MI.getOpcode()) {
8815 case LoongArch::PseudoXVINSGR2VR_B:
8817 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8818 InsOp = LoongArch::XVEXTRINS_B;
8820 case LoongArch::PseudoXVINSGR2VR_H:
8822 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8823 InsOp = LoongArch::XVEXTRINS_H;
8835 unsigned Idx =
MI.getOperand(3).getImm();
8843 .
addReg(XSrc, {}, LoongArch::sub_128);
8845 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8846 : LoongArch::VINSGR2VR_B),
8854 .
addImm(LoongArch::sub_128);
8861 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8864 .
addImm(Idx >= HalfSize ? 48 : 18);
8869 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8872 MI.eraseFromParent();
8879 assert(Subtarget.hasExtLSX());
8887 unsigned BroadcastOp, CTOp, PickOp;
8888 switch (
MI.getOpcode()) {
8891 case LoongArch::PseudoCTPOP_B:
8892 BroadcastOp = LoongArch::VREPLGR2VR_B;
8893 CTOp = LoongArch::VPCNT_B;
8894 PickOp = LoongArch::VPICKVE2GR_B;
8896 case LoongArch::PseudoCTPOP_H:
8897 case LoongArch::PseudoCTPOP_H_LA32:
8898 BroadcastOp = LoongArch::VREPLGR2VR_H;
8899 CTOp = LoongArch::VPCNT_H;
8900 PickOp = LoongArch::VPICKVE2GR_H;
8902 case LoongArch::PseudoCTPOP_W:
8903 case LoongArch::PseudoCTPOP_W_LA32:
8904 BroadcastOp = LoongArch::VREPLGR2VR_W;
8905 CTOp = LoongArch::VPCNT_W;
8906 PickOp = LoongArch::VPICKVE2GR_W;
8908 case LoongArch::PseudoCTPOP_D:
8909 BroadcastOp = LoongArch::VREPLGR2VR_D;
8910 CTOp = LoongArch::VPCNT_D;
8911 PickOp = LoongArch::VPICKVE2GR_D;
8921 MI.eraseFromParent();
8935 unsigned EleBits = 8;
8936 unsigned NotOpc = 0;
8939 switch (
MI.getOpcode()) {
8942 case LoongArch::PseudoVMSKLTZ_B:
8943 MskOpc = LoongArch::VMSKLTZ_B;
8945 case LoongArch::PseudoVMSKLTZ_H:
8946 MskOpc = LoongArch::VMSKLTZ_H;
8949 case LoongArch::PseudoVMSKLTZ_W:
8950 MskOpc = LoongArch::VMSKLTZ_W;
8953 case LoongArch::PseudoVMSKLTZ_D:
8954 MskOpc = LoongArch::VMSKLTZ_D;
8957 case LoongArch::PseudoVMSKGEZ_B:
8958 MskOpc = LoongArch::VMSKGEZ_B;
8960 case LoongArch::PseudoVMSKEQZ_B:
8961 MskOpc = LoongArch::VMSKNZ_B;
8962 NotOpc = LoongArch::VNOR_V;
8964 case LoongArch::PseudoVMSKNEZ_B:
8965 MskOpc = LoongArch::VMSKNZ_B;
8967 case LoongArch::PseudoXVMSKLTZ_B:
8968 MskOpc = LoongArch::XVMSKLTZ_B;
8969 RC = &LoongArch::LASX256RegClass;
8971 case LoongArch::PseudoXVMSKLTZ_H:
8972 MskOpc = LoongArch::XVMSKLTZ_H;
8973 RC = &LoongArch::LASX256RegClass;
8976 case LoongArch::PseudoXVMSKLTZ_W:
8977 MskOpc = LoongArch::XVMSKLTZ_W;
8978 RC = &LoongArch::LASX256RegClass;
8981 case LoongArch::PseudoXVMSKLTZ_D:
8982 MskOpc = LoongArch::XVMSKLTZ_D;
8983 RC = &LoongArch::LASX256RegClass;
8986 case LoongArch::PseudoXVMSKGEZ_B:
8987 MskOpc = LoongArch::XVMSKGEZ_B;
8988 RC = &LoongArch::LASX256RegClass;
8990 case LoongArch::PseudoXVMSKEQZ_B:
8991 MskOpc = LoongArch::XVMSKNZ_B;
8992 NotOpc = LoongArch::XVNOR_V;
8993 RC = &LoongArch::LASX256RegClass;
8995 case LoongArch::PseudoXVMSKNEZ_B:
8996 MskOpc = LoongArch::XVMSKNZ_B;
8997 RC = &LoongArch::LASX256RegClass;
9012 if (
TRI->getRegSizeInBits(*RC) > 128) {
9022 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
9023 : LoongArch::BSTRINS_W),
9027 .
addImm(256 / EleBits - 1)
9035 MI.eraseFromParent();
9042 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9043 "Unexpected instruction");
9055 MI.eraseFromParent();
9062 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9063 "Unexpected instruction");
9079 MI.eraseFromParent();
9084 switch (
MI.getOpcode()) {
9087 case LoongArch::Select_GPR_Using_CC_GPR:
9123 if (
MI.getOperand(2).isReg())
9124 RHS =
MI.getOperand(2).getReg();
9125 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9129 SelectDests.
insert(
MI.getOperand(0).getReg());
9133 SequenceMBBI !=
E; ++SequenceMBBI) {
9134 if (SequenceMBBI->isDebugInstr())
9137 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9138 !SequenceMBBI->getOperand(2).isReg() ||
9139 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9140 SequenceMBBI->getOperand(3).getImm() != CC ||
9141 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9142 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9144 LastSelectPseudo = &*SequenceMBBI;
9146 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9149 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9150 SequenceMBBI->mayLoadOrStore() ||
9151 SequenceMBBI->usesCustomInsertionHook())
9154 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9169 F->insert(
I, IfFalseMBB);
9170 F->insert(
I, TailMBB);
9173 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9179 TailMBB->
push_back(DebugInstr->removeFromParent());
9183 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9193 if (
MI.getOperand(2).isImm())
9205 auto SelectMBBI =
MI.getIterator();
9206 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9208 while (SelectMBBI != SelectEnd) {
9209 auto Next = std::next(SelectMBBI);
9213 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9214 .
addReg(SelectMBBI->getOperand(4).getReg())
9216 .
addReg(SelectMBBI->getOperand(5).getReg())
9223 F->getProperties().resetNoPHIs();
9229 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9232 switch (
MI.getOpcode()) {
9235 case LoongArch::DIV_W:
9236 case LoongArch::DIV_WU:
9237 case LoongArch::MOD_W:
9238 case LoongArch::MOD_WU:
9239 case LoongArch::DIV_D:
9240 case LoongArch::DIV_DU:
9241 case LoongArch::MOD_D:
9242 case LoongArch::MOD_DU:
9245 case LoongArch::WRFCSR: {
9247 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9248 .
addReg(
MI.getOperand(1).getReg());
9249 MI.eraseFromParent();
9252 case LoongArch::RDFCSR: {
9253 MachineInstr *ReadFCSR =
9255 MI.getOperand(0).getReg())
9256 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9258 MI.eraseFromParent();
9261 case LoongArch::Select_GPR_Using_CC_GPR:
9263 case LoongArch::BuildPairF64Pseudo:
9265 case LoongArch::SplitPairF64Pseudo:
9267 case LoongArch::PseudoVBZ:
9268 case LoongArch::PseudoVBZ_B:
9269 case LoongArch::PseudoVBZ_H:
9270 case LoongArch::PseudoVBZ_W:
9271 case LoongArch::PseudoVBZ_D:
9272 case LoongArch::PseudoVBNZ:
9273 case LoongArch::PseudoVBNZ_B:
9274 case LoongArch::PseudoVBNZ_H:
9275 case LoongArch::PseudoVBNZ_W:
9276 case LoongArch::PseudoVBNZ_D:
9277 case LoongArch::PseudoXVBZ:
9278 case LoongArch::PseudoXVBZ_B:
9279 case LoongArch::PseudoXVBZ_H:
9280 case LoongArch::PseudoXVBZ_W:
9281 case LoongArch::PseudoXVBZ_D:
9282 case LoongArch::PseudoXVBNZ:
9283 case LoongArch::PseudoXVBNZ_B:
9284 case LoongArch::PseudoXVBNZ_H:
9285 case LoongArch::PseudoXVBNZ_W:
9286 case LoongArch::PseudoXVBNZ_D:
9288 case LoongArch::PseudoXVINSGR2VR_B:
9289 case LoongArch::PseudoXVINSGR2VR_H:
9291 case LoongArch::PseudoCTPOP_B:
9292 case LoongArch::PseudoCTPOP_H:
9293 case LoongArch::PseudoCTPOP_W:
9294 case LoongArch::PseudoCTPOP_D:
9295 case LoongArch::PseudoCTPOP_H_LA32:
9296 case LoongArch::PseudoCTPOP_W_LA32:
9298 case LoongArch::PseudoVMSKLTZ_B:
9299 case LoongArch::PseudoVMSKLTZ_H:
9300 case LoongArch::PseudoVMSKLTZ_W:
9301 case LoongArch::PseudoVMSKLTZ_D:
9302 case LoongArch::PseudoVMSKGEZ_B:
9303 case LoongArch::PseudoVMSKEQZ_B:
9304 case LoongArch::PseudoVMSKNEZ_B:
9305 case LoongArch::PseudoXVMSKLTZ_B:
9306 case LoongArch::PseudoXVMSKLTZ_H:
9307 case LoongArch::PseudoXVMSKLTZ_W:
9308 case LoongArch::PseudoXVMSKLTZ_D:
9309 case LoongArch::PseudoXVMSKGEZ_B:
9310 case LoongArch::PseudoXVMSKEQZ_B:
9311 case LoongArch::PseudoXVMSKNEZ_B:
9313 case TargetOpcode::STATEPOINT:
9319 MI.addOperand(*
MI.getMF(),
9321 LoongArch::R1,
true,
9324 if (!Subtarget.is64Bit())
9327 case LoongArch::PROBED_STACKALLOC_DYN:
9334 unsigned *
Fast)
const {
9335 if (!Subtarget.hasUAL())
9353 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9354 LoongArch::R10, LoongArch::R11};
9369 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9370 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9371 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9372 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9373 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9374 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9380 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9381 LoongArch::F6, LoongArch::F7};
9384 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9385 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9388 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9389 LoongArch::VR6, LoongArch::VR7};
9392 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9393 LoongArch::XR6, LoongArch::XR7};
9396 switch (State.getCallingConv()) {
9398 if (!State.isVarArg())
9402 return State.AllocateReg(
ArgGPRs);
9410 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9412 unsigned GRLenInBytes = GRLen / 8;
9423 State.AllocateStack(GRLenInBytes, StackAlign),
9426 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9437 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9445 unsigned ValNo,
MVT ValVT,
9448 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9449 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9450 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9455 if (IsRet && ValNo > 1)
9459 bool UseGPRForFloat =
true;
9469 UseGPRForFloat = ArgFlags.
isVarArg();
9482 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9485 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9486 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9488 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9494 State.getPendingArgFlags();
9497 "PendingLocs and PendingArgFlags out of sync");
9501 UseGPRForFloat =
true;
9503 if (UseGPRForFloat && ValVT == MVT::f32) {
9506 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9509 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9512 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9554 PendingLocs.
size() <= 2) {
9555 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9560 PendingLocs.
clear();
9561 PendingArgFlags.
clear();
9568 unsigned StoreSizeBytes = GRLen / 8;
9571 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9573 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9577 UseGPRForFloat =
false;
9578 StoreSizeBytes = 16;
9579 StackAlign =
Align(16);
9582 UseGPRForFloat =
false;
9583 StoreSizeBytes = 32;
9584 StackAlign =
Align(32);
9590 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9594 if (!PendingLocs.
empty()) {
9596 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9597 for (
auto &It : PendingLocs) {
9599 It.convertToReg(
Reg);
9604 PendingLocs.clear();
9605 PendingArgFlags.
clear();
9608 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9609 "Expected an GRLenVT at this stage");
9626void LoongArchTargetLowering::analyzeInputArgs(
9629 LoongArchCCAssignFn Fn)
const {
9631 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9632 MVT ArgVT = Ins[i].VT;
9633 Type *ArgTy =
nullptr;
9635 ArgTy = FType->getReturnType();
9636 else if (Ins[i].isOrigArg())
9637 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9641 CCInfo, IsRet, ArgTy)) {
9642 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9649void LoongArchTargetLowering::analyzeOutputArgs(
9652 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9653 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9654 MVT ArgVT = Outs[i].VT;
9655 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
9659 CCInfo, IsRet, OrigTy)) {
9660 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
9679 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
9701 if (In.isOrigArg()) {
9706 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
9707 (
BitWidth < 32 && In.Flags.isZExt())) {
9757 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9770 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9774 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
9788 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
9800 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
9804 LoongArch::R23, LoongArch::R24, LoongArch::R25,
9805 LoongArch::R26, LoongArch::R27, LoongArch::R28,
9806 LoongArch::R29, LoongArch::R30, LoongArch::R31};
9813 if (LocVT == MVT::f32) {
9816 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9817 LoongArch::F26, LoongArch::F27};
9824 if (LocVT == MVT::f64) {
9827 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9828 LoongArch::F30_64, LoongArch::F31_64};
9859 "GHC calling convention requires the F and D extensions");
9864 MVT GRLenVT = Subtarget.getGRLenVT();
9865 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9874 return CI->isMustTailCall();
9879 std::vector<SDValue> OutChains;
9888 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9890 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
9907 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
9916 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
9917 assert(ArgPartOffset == 0);
9918 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
9920 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
9944 int VaArgOffset, VarArgsSaveSize;
9948 if (ArgRegs.
size() == Idx) {
9950 VarArgsSaveSize = 0;
9952 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
9953 VaArgOffset = -VarArgsSaveSize;
9959 LoongArchFI->setVarArgsFrameIndex(FI);
9967 VarArgsSaveSize += GRLenInBytes;
9972 for (
unsigned I = Idx;
I < ArgRegs.
size();
9973 ++
I, VaArgOffset += GRLenInBytes) {
9974 const Register Reg = RegInfo.createVirtualRegister(RC);
9975 RegInfo.addLiveIn(ArgRegs[
I], Reg);
9983 ->setValue((
Value *)
nullptr);
9984 OutChains.push_back(Store);
9986 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
9991 if (!OutChains.empty()) {
9992 OutChains.push_back(Chain);
10007 if (
N->getNumValues() != 1)
10009 if (!
N->hasNUsesOfValue(1, 0))
10012 SDNode *Copy = *
N->user_begin();
10018 if (Copy->getGluedNode())
10022 bool HasRet =
false;
10024 if (
Node->getOpcode() != LoongArchISD::RET)
10032 Chain = Copy->getOperand(0);
10037bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10041 auto CalleeCC = CLI.CallConv;
10042 auto &Outs = CLI.Outs;
10044 auto CallerCC = Caller.getCallingConv();
10046 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10055 for (
auto &Arg : Outs)
10056 if (Arg.Flags.isByVal())
10072 for (
auto &VA : ArgLocs)
10078 auto IsCallerStructRet = Caller.hasStructRetAttr();
10079 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10080 if (IsCallerStructRet || IsCalleeStructRet)
10085 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10086 if (CalleeCC != CallerCC) {
10087 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10088 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10114 MVT GRLenVT = Subtarget.getGRLenVT();
10126 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10130 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10136 "site marked musttail");
10143 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10145 if (!Flags.isByVal())
10149 unsigned Size = Flags.getByValSize();
10150 Align Alignment = Flags.getNonZeroByValAlign();
10157 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10159 false,
nullptr, std::nullopt,
10171 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10174 SDValue ArgValue = OutVals[OutIdx];
10182 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10183 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10195 if (!StackPtr.getNode())
10207 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10221 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10241 const Argument *FormalArg =
nullptr;
10242 unsigned FilteredIdx = 0;
10243 for (
const auto &CallArg : CLI.
CB->
args()) {
10244 if (CallArg->getType()->isEmptyTy())
10246 if (FilteredIdx == CallArgIdx) {
10255 unsigned FormalArgIdx = CallArgIdx;
10257 FormalArgIdx = FormalArg->
getArgNo();
10261 if (Arg.getType()->isEmptyTy())
10263 if (FilteredIdx == CallArgIdx) {
10264 FormalArgIdx = Arg.getArgNo();
10277 SDValue IncomingPtr = CopyOp;
10294 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10295 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10296 SDValue PartValue = OutVals[OutIdx + 1];
10297 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10308 ArgValue = IncomingPtr;
10312 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10324 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10325 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10326 assert(ArgPartOffset == 0);
10331 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10332 SDValue PartValue = OutVals[OutIdx + 1];
10333 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10345 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10347 for (
const auto &Part : Parts) {
10348 SDValue PartValue = Part.first;
10349 SDValue PartOffset = Part.second;
10356 ArgValue = SpillSlot;
10363 if (Flags.isByVal())
10364 ArgValue = ByValArgs[j++];
10372 "Tail call not allowed if stack is used for passing parameters");
10375 if (!StackPtr.getNode())
10388 if (!MemOpChains.
empty())
10394 for (
auto &Reg : RegsToPass) {
10395 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10417 Ops.push_back(Chain);
10418 Ops.push_back(Callee);
10422 for (
auto &Reg : RegsToPass)
10423 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10428 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10429 assert(Mask &&
"Missing call preserved mask for calling convention");
10435 Ops.push_back(Glue);
10444 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10447 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10450 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10451 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10473 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10476 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10477 auto &VA = RVLocs[i];
10485 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10486 assert(VA.needsCustom());
10491 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10492 RetValue, RetValue2);
10505 const Type *RetTy)
const {
10507 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10509 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10513 Outs[i].Flags, CCInfo,
true,
nullptr))
10539 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10540 SDValue Val = OutVals[OutIdx];
10549 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10553 Register RegHi = RVLocs[++i].getLocReg();
10578 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10586 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10589 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10591 RequiredImm = (0b10101 << 8) | (V >> 8);
10592 return {
true, RequiredImm};
10593 }
else if (SplatBitSize == 32) {
10595 if (!(V & 0xFFFF00FF)) {
10596 RequiredImm = (0b10001 << 8) | (V >> 8);
10597 return {
true, RequiredImm};
10600 if (!(V & 0xFF00FFFF)) {
10601 RequiredImm = (0b10010 << 8) | (V >> 16);
10602 return {
true, RequiredImm};
10605 if (!(V & 0x00FFFFFF)) {
10606 RequiredImm = (0b10011 << 8) | (V >> 24);
10607 return {
true, RequiredImm};
10610 if ((V & 0xFFFF00FF) == 0xFF) {
10611 RequiredImm = (0b10110 << 8) | (V >> 8);
10612 return {
true, RequiredImm};
10615 if ((V & 0xFF00FFFF) == 0xFFFF) {
10616 RequiredImm = (0b10111 << 8) | (V >> 16);
10617 return {
true, RequiredImm};
10620 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
10622 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10623 return {
true, RequiredImm};
10625 }
else if (SplatBitSize == 64) {
10627 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
10628 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
10630 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
10631 return {
true, RequiredImm};
10634 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
10635 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
10637 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
10638 return {
true, RequiredImm};
10641 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
10643 for (
int i = 0; i < 8; ++i) {
10645 if (
byte == 0 ||
byte == 0xFF)
10646 res |= ((
byte & 1) << i);
10651 return {
true, res};
10653 auto [IsSame, Suffix] = sameBitsPreByte(V);
10655 RequiredImm = (0b11001 << 8) | Suffix;
10656 return {
true, RequiredImm};
10659 return {
false, RequiredImm};
10664 if (!Subtarget.hasExtLSX())
10667 if (VT == MVT::f32) {
10668 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
10669 return (masked == 0x3e000000 || masked == 0x40000000);
10672 if (VT == MVT::f64) {
10673 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
10674 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
10680bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
10681 bool ForCodeSize)
const {
10683 if (VT == MVT::f32 && !Subtarget.hasBasicF())
10685 if (VT == MVT::f64 && !Subtarget.hasBasicD())
10698bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
10708 Type *Ty =
I->getOperand(0)->getType();
10710 unsigned Size = Ty->getIntegerBitWidth();
10730 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
10735 if (Subtarget.hasExtLASX())
10737 else if (Subtarget.hasExtLSX())
10744 EVT VT =
Y.getValueType();
10747 return Subtarget.hasExtLSX() && VT.
isInteger();
10758 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
10759 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
10760 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
10761 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
10764 Info.memVT = MVT::i32;
10765 Info.ptrVal =
I.getArgOperand(0);
10767 Info.align =
Align(4);
10786 "Unable to expand");
10787 unsigned MinWordSize = 4;
10799 Value *AlignedAddr = Builder.CreateIntrinsic(
10800 Intrinsic::ptrmask, {PtrTy, IntTy},
10801 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
10804 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
10805 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
10806 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
10807 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
10808 Value *Mask = Builder.CreateShl(
10809 ConstantInt::get(WordType,
10810 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
10812 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
10813 Value *ValOperand_Shifted =
10814 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
10815 ShiftAmt,
"ValOperand_Shifted");
10818 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
10820 NewOperand = ValOperand_Shifted;
10823 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
10826 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
10827 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
10828 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
10847 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
10855 if (Subtarget.hasLAMCAS()) {
10877 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
10879 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
10881 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
10883 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
10885 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
10887 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
10889 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
10891 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
10901 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
10903 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
10905 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
10907 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
10909 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
10911 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
10913 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
10915 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
10927 if (Subtarget.hasLAMCAS())
10939 unsigned GRLen = Subtarget.getGRLen();
10941 Value *FailureOrdering =
10942 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
10943 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
10945 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
10946 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
10947 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
10948 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10951 Value *Result = Builder.CreateIntrinsic(
10952 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
10954 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10970 Builder.CreateNot(Mask,
"Inv_Mask"),
10977 unsigned GRLen = Subtarget.getGRLen();
10986 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
10987 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10988 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11001 unsigned ValWidth =
11004 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11005 Result = Builder.CreateCall(LlwOpScwLoop,
11006 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11009 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11013 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11036 const Constant *PersonalityFn)
const {
11037 return LoongArch::R4;
11041 const Constant *PersonalityFn)
const {
11042 return LoongArch::R5;
11053 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11054 return RefinementSteps;
11059 assert(Subtarget.hasFrecipe() &&
11060 "Reciprocal estimate queried on unsupported target");
11071 return Subtarget.hasBasicD();
11075 return Subtarget.hasExtLSX();
11079 return Subtarget.hasExtLASX();
11088 int &RefinementSteps,
11089 bool &UseOneConstNR,
11090 bool Reciprocal)
const {
11092 "Enabled should never be Disabled here");
11094 if (!Subtarget.hasFrecipe())
11109 UseOneConstNR =
false;
11115 if (Reciprocal || RefinementSteps > 0)
11125 int &RefinementSteps)
const {
11127 "Enabled should never be Disabled here");
11129 if (!Subtarget.hasFrecipe())
11143 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11151LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11171 if (Constraint.
size() == 1) {
11172 switch (Constraint[0]) {
11188 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11197 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11204std::pair<unsigned, const TargetRegisterClass *>
11205LoongArchTargetLowering::getRegForInlineAsmConstraint(
11209 if (Constraint.
size() == 1) {
11210 switch (Constraint[0]) {
11215 return std::make_pair(0U, &LoongArch::GPRRegClass);
11217 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11219 if (Subtarget.hasBasicF() && VT == MVT::f32)
11220 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11221 if (Subtarget.hasBasicD() && VT == MVT::f64)
11222 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11223 if (Subtarget.hasExtLSX() &&
11224 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11225 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11226 if (Subtarget.hasExtLASX() &&
11227 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11228 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11248 bool IsFP = Constraint[2] ==
'f';
11249 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11250 std::pair<unsigned, const TargetRegisterClass *>
R;
11255 unsigned RegNo =
R.first;
11256 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11257 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11258 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11259 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11269void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11273 if (Constraint.
size() == 1) {
11274 switch (Constraint[0]) {
11278 uint64_t CVal =
C->getSExtValue();
11281 Subtarget.getGRLenVT()));
11287 uint64_t CVal =
C->getSExtValue();
11290 Subtarget.getGRLenVT()));
11296 if (
C->getZExtValue() == 0)
11303 uint64_t CVal =
C->getZExtValue();
11316#define GET_REGISTER_MATCHER
11317#include "LoongArchGenAsmMatcher.inc"
11323 std::string NewRegName = Name.second.str();
11329 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11330 if (!ReservedRegs.
test(Reg))
11347 const APInt &Imm = ConstNode->getAPIntValue();
11349 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
11350 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
11353 if (ConstNode->hasOneUse() &&
11354 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
11355 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
11361 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
11362 unsigned Shifts = Imm.countr_zero();
11368 APInt ImmPop = Imm.ashr(Shifts);
11369 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11373 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
11374 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
11375 (ImmSmall - Imm).isPowerOf2())
11385 Type *Ty,
unsigned AS,
11404 switch (AM.
Scale) {
11440 EVT MemVT = LD->getMemoryVT();
11441 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11452 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11461 if (
Y.getValueType().isVector())
11473 Type *Ty,
bool IsSigned)
const {
11474 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11483 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11484 Type.getSizeInBits() < Subtarget.getGRLen()))
11494 Align &PrefAlign)
const {
11498 if (Subtarget.is64Bit()) {
11500 PrefAlign =
Align(8);
11503 PrefAlign =
Align(4);
11518bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11520 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
11521 bool IsABIRegCopy = CC.has_value();
11524 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11525 PartVT == MVT::f32) {
11540SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11542 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11543 bool IsABIRegCopy = CC.has_value();
11545 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11546 PartVT == MVT::f32) {
11563 if (VT == MVT::f16 && Subtarget.hasBasicF())
11569unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11572 if (VT == MVT::f16 && Subtarget.hasBasicF())
11581 unsigned Opc =
Op.getOpcode();
11586 case LoongArchISD::VPICK_ZEXT_ELT: {
11600 unsigned Depth)
const {
11601 EVT VT =
Op.getValueType();
11603 unsigned Opc =
Op.getOpcode();
11607 case LoongArchISD::CRC_W_B_W:
11608 case LoongArchISD::CRC_W_H_W:
11609 case LoongArchISD::CRCC_W_B_W:
11610 case LoongArchISD::CRCC_W_H_W: {
11612 APInt DemandedSrcBits =
11614 Opc == LoongArchISD::CRCC_W_B_W)
11618 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
11620 case LoongArchISD::VMSKLTZ:
11621 case LoongArchISD::XVMSKLTZ: {
11623 MVT SrcVT = Src.getSimpleValueType();
11628 if (OriginalDemandedBits.
countr_zero() >= NumElts)
11632 APInt KnownUndef, KnownZero;
11648 if (KnownSrc.
One[SrcBits - 1])
11650 else if (KnownSrc.
Zero[SrcBits - 1])
11655 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
11662 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
11685 unsigned Index)
const {
11694 unsigned Index)
const {
11698 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
11713 Align StackAlign)
const {
11717 unsigned StackProbeSize =
11721 return StackProbeSize ? StackProbeSize : StackAlign.
value();
11725LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
11739 const EVT VT =
Op.getValueType();
11750 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
11760 const Register TargetReg =
MI.getOperand(0).getReg();
11763 const bool IsLA64 = Subtarget.is64Bit();
11764 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
11771 MF.
insert(MBBInsertPoint, LoopTestMBB);
11774 MF.
insert(MBBInsertPoint, ExitMBB);
11785 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
11791 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
11797 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
11812 MBB->addSuccessor(LoopTestMBB);
11814 MI.eraseFromParent();
11816 return ExitMBB->
begin()->getParent();
static MCRegister MatchRegisterName(StringRef Name)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSELECT_CCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue performUINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performHorizWideningCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static SDValue ExtendSrcToDst(SDNode *N, SelectionDAG &DAG, unsigned ExtendOp)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static SDValue performDemandedBitsCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue matchLowHalfOf128BitLanes(SDValue N)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue matchDeinterleaveBuildVector(SDValue N, unsigned &StartIndex)
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
LLVM_READONLY bool isOne() const
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type count() const
Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
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...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void setIncomingIndirectArg(unsigned ArgIndex, Register Reg)
void addSExt32Register(Register Reg)
Register getIncomingIndirectArg(unsigned ArgIndex) const
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
unsigned getBitWidth() const
Get the bit width of this value.
void resetAll()
Resets the known state of all bits.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)