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)
114 if (Subtarget.hasBasicF())
172 if (Subtarget.is64Bit()) {
200 if (!Subtarget.is64Bit()) {
206 if (Subtarget.hasBasicD())
218 if (Subtarget.hasBasicF()) {
252 if (Subtarget.is64Bit())
255 if (!Subtarget.hasBasicD()) {
257 if (Subtarget.is64Bit()) {
266 if (Subtarget.hasBasicD()) {
299 if (Subtarget.is64Bit())
305 if (Subtarget.hasExtLSX()) {
320 for (
MVT VT : LSXVTs) {
334 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
364 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
366 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
372 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
396 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
397 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
412 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
414 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
421 if (Subtarget.hasExtLASX()) {
422 for (
MVT VT : LASXVTs) {
437 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
466 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
468 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
470 for (
MVT VT : {MVT::v8i32, MVT::v4i64})
472 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
477 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
496 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
502 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
506 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
511 if (Subtarget.hasBasicF()) {
528 if (Subtarget.has32S())
533 if (Subtarget.hasExtLSX()) {
548 if (Subtarget.hasExtLASX()) {
573 if (Subtarget.hasLAMCAS())
576 if (Subtarget.hasSCQ()) {
596 switch (
Op.getOpcode()) {
598 return lowerATOMIC_FENCE(
Op, DAG);
600 return lowerEH_DWARF_CFA(
Op, DAG);
602 return lowerGlobalAddress(
Op, DAG);
604 return lowerGlobalTLSAddress(
Op, DAG);
606 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
608 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
610 return lowerINTRINSIC_VOID(
Op, DAG);
612 return lowerBlockAddress(
Op, DAG);
614 return lowerJumpTable(
Op, DAG);
616 return lowerShiftLeftParts(
Op, DAG);
618 return lowerShiftRightParts(
Op, DAG,
true);
620 return lowerShiftRightParts(
Op, DAG,
false);
622 return lowerConstantPool(
Op, DAG);
624 return lowerFP_TO_SINT(
Op, DAG);
626 return lowerFP_TO_UINT(
Op, DAG);
628 return lowerFP_TO_SINT_SAT(
Op, DAG);
630 return lowerBITCAST(
Op, DAG);
632 return lowerUINT_TO_FP(
Op, DAG);
634 return lowerSINT_TO_FP(
Op, DAG);
636 return lowerVASTART(
Op, DAG);
638 return lowerFRAMEADDR(
Op, DAG);
640 return lowerRETURNADDR(
Op, DAG);
642 return lowerSET_ROUNDING(
Op, DAG);
644 return lowerGET_ROUNDING(
Op, DAG);
646 return lowerWRITE_REGISTER(
Op, DAG);
648 return lowerINSERT_VECTOR_ELT(
Op, DAG);
650 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
652 return lowerBUILD_VECTOR(
Op, DAG);
654 return lowerCONCAT_VECTORS(
Op, DAG);
656 return lowerVECTOR_SHUFFLE(
Op, DAG);
658 return lowerBITREVERSE(
Op, DAG);
660 return lowerSCALAR_TO_VECTOR(
Op, DAG);
662 return lowerPREFETCH(
Op, DAG);
664 return lowerSELECT(
Op, DAG);
666 return lowerBRCOND(
Op, DAG);
668 return lowerFP_TO_FP16(
Op, DAG);
670 return lowerFP16_TO_FP(
Op, DAG);
672 return lowerFP_TO_BF16(
Op, DAG);
674 return lowerBF16_TO_FP(
Op, DAG);
676 return lowerVECREDUCE_ADD(
Op, DAG);
679 return lowerRotate(
Op, DAG);
687 return lowerVECREDUCE(
Op, DAG);
689 return lowerConstantFP(
Op, DAG);
691 return lowerSETCC(
Op, DAG);
693 return lowerFP_ROUND(
Op, DAG);
695 return lowerFP_EXTEND(
Op, DAG);
697 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
699 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
701 return lowerANY_EXTEND(
Op, DAG);
710 EVT VT = V.getValueType();
716 return V.getOperand(0);
720 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
722 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
732 if (!V->isOnlyUserOf(SplatValue.getNode()))
736 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
744 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
772 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
773 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
780 if (Opcode0 != Opcode1)
783 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
790 EVT VT =
N.getValueType();
804 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
805 SSVT0 == MVT::v4f64) {
824 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
825 N->getOpcode() == LoongArchISD::VPERMI) &&
826 Opcode0 == LoongArchISD::VFCVT) {
831 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
834 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
835 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
841 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
856 SDValue
In =
Op.getOperand(0);
857 MVT VT =
Op.getSimpleValueType();
858 MVT SVT =
In.getSimpleValueType();
860 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
873 EVT VT =
Op.getValueType();
874 SDValue Src =
Op->getOperand(0);
875 EVT SVT = Src.getValueType();
878 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
880 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
881 if (!V2F32ToV2F64 && !V4F32ToV4F64)
885 auto CheckVecHighPart = [](SDValue
Op) {
888 SDValue SOp =
Op.getOperand(0);
908 if (SDValue V = CheckVecHighPart(Src)) {
910 "Unexpected wide vector");
911 Opcode = LoongArchISD::VFCVTH;
914 Opcode = LoongArchISD::VFCVTL;
916 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
921 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
927 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
939 EVT VT =
Op.getValueType();
944 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
945 (VT == MVT::f64 && Subtarget.hasBasicD()));
963 if (VT == MVT::f32) {
964 assert(Subtarget.is64Bit());
967 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, VT, NewVal);
970 assert(VT == MVT::f64 && !Subtarget.is64Bit());
973 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
981 EVT ResultVT =
Op.getValueType();
982 EVT OperandVT =
Op.getOperand(0).getValueType();
987 if (ResultVT == SetCCResultVT)
990 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
991 "SETCC operands must have the same type!");
995 Op.getOperand(1),
Op.getOperand(2));
997 if (ResultVT.
bitsGT(SetCCResultVT))
999 else if (ResultVT.
bitsLT(SetCCResultVT))
1011SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1014 SDValue Src =
Op.getOperand(0);
1015 MVT SrcVT = Src.getSimpleValueType();
1016 MVT DstVT =
Op.getSimpleValueType();
1026 SDValue LoInterleaved =
1027 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1038 assert(Subtarget.hasExtLASX());
1057 MVT OpVT =
Op.getSimpleValueType();
1058 SDValue Val =
Op.getOperand(0);
1064 unsigned LegalVecSize = 128;
1065 bool isLASX256Vector =
1075 if (isLASX256Vector) {
1081 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1082 EleBits = std::min(EleBits, 64u);
1085 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1088 if (isLASX256Vector) {
1089 SDValue Tmp = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, Val,
1114 MVT OpVT =
Op.getSimpleValueType();
1115 SDValue Val =
Op.getOperand(0);
1127 MVT GRLenVT = Subtarget.getGRLenVT();
1129 for (
int i = NumEles; i > 1; i /= 2) {
1130 SDValue ShiftAmt = DAG.
getConstant(i * EleBits / 16,
DL, GRLenVT);
1131 SDValue Tmp = DAG.
getNode(LoongArchISD::VBSRL,
DL, VecTy, Val, ShiftAmt);
1132 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1141 unsigned IsData =
Op.getConstantOperandVal(4);
1146 return Op.getOperand(0);
1153 MVT VT =
Op.getSimpleValueType();
1157 SDValue
R =
Op.getOperand(0);
1158 SDValue Amt =
Op.getOperand(1);
1159 unsigned Opcode =
Op.getOpcode();
1162 auto checkCstSplat = [](SDValue
V, APInt &CstSplatValue) {
1165 if (SDValue SplatValue =
1168 CstSplatValue =
C->getAPIntValue();
1176 APInt CstSplatValue;
1177 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1181 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1197 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1213 if (
LHS == LHS2 &&
RHS == RHS2) {
1218 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1226 return std::nullopt;
1234 MVT VT =
N->getSimpleValueType(0);
1265 if (~TrueVal == FalseVal) {
1305 unsigned SelOpNo = 0;
1315 unsigned ConstSelOpNo = 1;
1316 unsigned OtherSelOpNo = 2;
1323 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1328 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1334 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1336 std::swap(NewConstOps[0], NewConstOps[1]);
1348 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1350 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1353 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1354 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1374 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1388 int64_t
C = RHSC->getSExtValue();
1427 SDValue CondV =
Op.getOperand(0);
1428 SDValue TrueV =
Op.getOperand(1);
1429 SDValue FalseV =
Op.getOperand(2);
1431 MVT VT =
Op.getSimpleValueType();
1432 MVT GRLenVT = Subtarget.getGRLenVT();
1437 if (
Op.hasOneUse()) {
1438 unsigned UseOpc =
Op->user_begin()->getOpcode();
1440 SDNode *BinOp = *
Op->user_begin();
1447 return lowerSELECT(NewSel, DAG);
1462 SDValue
Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
1464 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1487 if (TrueVal - 1 == FalseVal)
1489 if (TrueVal + 1 == FalseVal)
1496 RHS == TrueV &&
LHS == FalseV) {
1520 SDValue
Ops[] = {
LHS,
RHS, TargetCC, TrueV, FalseV};
1521 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1526 SDValue CondV =
Op.getOperand(1);
1528 MVT GRLenVT = Subtarget.getGRLenVT();
1539 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1540 Op.getOperand(0),
LHS,
RHS, TargetCC,
1543 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1544 Op.getOperand(0), CondV,
Op.getOperand(2));
1548 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1554LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1557 MVT OpVT =
Op.getSimpleValueType();
1560 SDValue Val =
Op.getOperand(0);
1568 EVT ResTy =
Op->getValueType(0);
1569 SDValue Src =
Op->getOperand(0);
1573 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1583 for (
unsigned int i = 0; i < NewEltNum; i++) {
1586 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1587 ? (
unsigned)LoongArchISD::BITREV_8B
1605 for (
unsigned int i = 0; i < NewEltNum; i++)
1606 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1607 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1625 if (EltBits > 32 || EltBits == 1)
1653 int MaskOffset,
const APInt &Zeroable) {
1654 int Size = Mask.size();
1655 unsigned SizeInBits =
Size * ScalarSizeInBits;
1657 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1658 for (
int i = 0; i <
Size; i += Scale)
1659 for (
int j = 0; j < Shift; ++j)
1660 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1668 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1669 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1674 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1675 for (
int i = 0; i !=
Size; i += Scale) {
1676 unsigned Pos =
Left ? i + Shift : i;
1677 unsigned Low =
Left ? i : i + Shift;
1678 unsigned Len = Scale - Shift;
1683 int ShiftEltBits = ScalarSizeInBits * Scale;
1684 bool ByteShift = ShiftEltBits > 64;
1685 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1686 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1687 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1691 Scale = ByteShift ? Scale / 2 : Scale;
1697 return (
int)ShiftAmt;
1700 unsigned MaxWidth = 128;
1701 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1702 for (
int Shift = 1; Shift != Scale; ++Shift)
1703 for (
bool Left : {
true,
false})
1704 if (CheckZeros(Shift, Scale,
Left)) {
1705 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1730 const APInt &Zeroable) {
1731 int Size = Mask.size();
1745 Mask,
Size, Zeroable);
1753 "Illegal integer vector type");
1762template <
typename ValType>
1765 unsigned CheckStride,
1767 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1771 if (*
I != -1 && *
I != ExpectedIndex)
1773 ExpectedIndex += ExpectedIndexStride;
1777 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1789 int Size = Mask.size();
1798 int VectorSizeInBits =
V1.getValueSizeInBits();
1799 int ScalarSizeInBits = VectorSizeInBits /
Size;
1800 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1801 (void)ScalarSizeInBits;
1803 for (
int i = 0; i <
Size; ++i) {
1809 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1826 RepeatedMask.
assign(LaneSize, -1);
1827 int Size = Mask.size();
1828 for (
int i = 0; i <
Size; ++i) {
1829 assert(Mask[i] == -1 || Mask[i] >= 0);
1832 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1839 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1840 if (RepeatedMask[i % LaneSize] < 0)
1842 RepeatedMask[i % LaneSize] = LocalM;
1843 else if (RepeatedMask[i % LaneSize] != LocalM)
1860 int NumElts = RepeatedMask.
size();
1862 int Scale = 16 / NumElts;
1864 for (
int i = 0; i < NumElts; ++i) {
1865 int M = RepeatedMask[i];
1866 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1867 "Unexpected mask index.");
1872 int StartIdx = i - (M % NumElts);
1879 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1882 Rotation = CandidateRotation;
1883 else if (Rotation != CandidateRotation)
1898 else if (TargetV != MaskV)
1903 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1904 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1913 return Rotation * Scale;
1932 if (ByteRotation <= 0)
1939 int LoByteShift = 16 - ByteRotation;
1940 int HiByteShift = ByteRotation;
1963 const APInt &Zeroable) {
1977 for (
int i = 0; i < NumElements; i++) {
1981 if (i % Scale != 0) {
1993 M = M % NumElements;
1996 Offset = M - (i / Scale);
1999 if (
Offset % (NumElements / Scale))
2001 }
else if (InputV != V)
2004 if (M != (
Offset + (i / Scale)))
2014 unsigned VilVLoHi = LoongArchISD::VILVL;
2015 if (
Offset >= (NumElements / 2)) {
2016 VilVLoHi = LoongArchISD::VILVH;
2017 Offset -= (NumElements / 2);
2025 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2029 }
while (Scale > 1);
2035 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2036 NumExtElements *= 2) {
2056 int SplatIndex = -1;
2057 for (
const auto &M : Mask) {
2064 if (SplatIndex == -1)
2067 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2069 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2099 unsigned SubVecSize = 4;
2100 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2103 int SubMask[4] = {-1, -1, -1, -1};
2104 for (
unsigned i = 0; i < SubVecSize; ++i) {
2105 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2111 M -= 4 * (j / SubVecSize);
2112 if (M < 0 || M >= 4)
2118 if (SubMask[i] == -1)
2122 else if (M != -1 && M != SubMask[i])
2129 for (
int i = SubVecSize - 1; i >= 0; --i) {
2142 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2143 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2146 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2164 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2173 for (
int i = 0; i < WidenNumElts; ++i)
2174 WidenMask[i] = WidenNumElts - 1 - i;
2182 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2206 const auto &Begin = Mask.begin();
2207 const auto &
End = Mask.end();
2224 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2246 const auto &Begin = Mask.begin();
2247 const auto &
End = Mask.end();
2264 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2287 const auto &Begin = Mask.begin();
2288 const auto &
End = Mask.end();
2289 unsigned HalfSize = Mask.size() / 2;
2307 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2330 const auto &Begin = Mask.begin();
2331 const auto &
End = Mask.end();
2348 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2370 const auto &Begin = Mask.begin();
2371 const auto &Mid = Mask.begin() + Mask.size() / 2;
2372 const auto &
End = Mask.end();
2390 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2412 const auto &Begin = Mask.begin();
2413 const auto &Mid = Mask.begin() + Mask.size() / 2;
2414 const auto &
End = Mask.end();
2431 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2457 if (Mask.size() != NumElts)
2460 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2463 for (
unsigned i = 0; i < NumElts; ++i) {
2466 if (Mask[i] !=
int(
Base + i)) {
2479 int DiffMask = Mask[DiffPos];
2480 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2486 if (
unsigned(DiffMask) < NumElts) {
2491 SrcIdx =
unsigned(DiffMask) - NumElts;
2507 if (
SDValue Result = tryLowerToExtrAndIns(0))
2509 return tryLowerToExtrAndIns(NumElts);
2517 unsigned &MaskImm) {
2518 unsigned MaskSize = Mask.size();
2521 return (M == -1) || (M >=
Off && M <
Off + 4);
2524 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2525 auto immPart = [&](
int M,
unsigned Off) {
2526 return (M == -1 ? 0 : (M -
Off)) & 0x3;
2528 MaskImm |= immPart(MLo,
Off) << (
I * 2);
2529 MaskImm |= immPart(MHi,
Off) << ((
I + 1) * 2);
2532 for (
unsigned i = 0; i < 4; i += 2) {
2534 int MHi = Mask[i + 1];
2536 if (MaskSize == 8) {
2537 auto isValid2 = [&](
int &M,
int M2) {
2544 if ((M2 % MaskSize) < 4)
2552 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2558 buildImm(MLo, MHi, 0, i);
2561 buildImm(MLo, MHi, MaskSize, i);
2591 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2596 unsigned MaskImm = 0;
2600 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2627 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2640 "Vector type is unsupported for lsx!");
2642 "Two operands have different types!");
2644 "Unexpected mask size for shuffle!");
2645 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2647 APInt KnownUndef, KnownZero;
2649 APInt Zeroable = KnownUndef | KnownZero;
2722 int SplatIndex = -1;
2723 for (
const auto &M : Mask) {
2730 if (SplatIndex == -1)
2733 const auto &Begin = Mask.begin();
2734 const auto &
End = Mask.end();
2735 int HalfSize = Mask.size() / 2;
2737 if (SplatIndex >= HalfSize)
2740 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2744 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2758 if (Mask.size() == 4) {
2759 unsigned MaskImm = 0;
2760 for (
int i = 1; i >= 0; --i) {
2762 int MHi = Mask[i + 2];
2763 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2764 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2766 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2771 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2773 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2776 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2797 return DAG.
getNode(LoongArchISD::XVREPLVE0,
DL, VT,
V1);
2806 unsigned MaskSize = Mask.size();
2811 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2813 unsigned MaskImm = 0;
2817 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2822 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2823 unsigned MaskImm = 0;
2824 for (
unsigned i = 0; i < MaskSize; ++i) {
2827 if (Mask[i] >= (
int)MaskSize)
2829 MaskImm |= Mask[i] << (i * 2);
2832 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2844 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2848 unsigned HalfSize = NumElts / 2;
2849 bool FrontLo =
true, FrontHi =
true;
2850 bool BackLo =
true, BackHi =
true;
2852 auto inRange = [](
int val,
int low,
int high) {
2853 return (val == -1) || (val >= low && val < high);
2856 for (
unsigned i = 0; i < HalfSize; ++i) {
2857 int Fronti = Mask[i];
2858 int Backi = Mask[i + HalfSize];
2860 FrontLo &=
inRange(Fronti, 0, HalfSize);
2861 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2862 BackLo &=
inRange(Backi, 0, HalfSize);
2863 BackHi &=
inRange(Backi, HalfSize, NumElts);
2869 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2874 for (
unsigned i = 0; i < NumElts; ++i)
2879 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2901 const auto &Begin = Mask.begin();
2902 const auto &
End = Mask.end();
2903 unsigned HalfSize = Mask.size() / 2;
2904 unsigned LeftSize = HalfSize / 2;
2912 Mask.size() + HalfSize - LeftSize, 1) &&
2914 Mask.size() + HalfSize + LeftSize, 1))
2925 Mask.size() + HalfSize - LeftSize, 1) &&
2927 Mask.size() + HalfSize + LeftSize, 1))
2932 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2940 const auto &Begin = Mask.begin();
2941 const auto &
End = Mask.end();
2942 unsigned HalfSize = Mask.size() / 2;
2950 Mask.size() + HalfSize, 1))
2961 Mask.size() + HalfSize, 1))
2966 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2974 const auto &Begin = Mask.begin();
2975 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2976 const auto &Mid = Mask.begin() + Mask.size() / 2;
2977 const auto &RightMid = Mask.end() - Mask.size() / 4;
2978 const auto &
End = Mask.end();
2979 unsigned HalfSize = Mask.size() / 2;
3001 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
3009 const auto &Begin = Mask.begin();
3010 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3011 const auto &Mid = Mask.begin() + Mask.size() / 2;
3012 const auto &RightMid = Mask.end() - Mask.size() / 4;
3013 const auto &
End = Mask.end();
3014 unsigned HalfSize = Mask.size() / 2;
3037 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3046 int HalfSize = NumElts / 2;
3050 if ((
int)Mask.size() != NumElts)
3053 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3055 for (
int i = 0; i < NumElts; ++i) {
3058 if (Mask[i] !=
Base + i) {
3060 if (DiffPos.
size() > 2)
3068 if (DiffPos.
size() == 1) {
3069 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3070 DiffPos.
push_back(DiffPos[0] + HalfSize);
3071 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3072 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3076 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3080 int DiffMaskLo = Mask[DiffPos[0]];
3081 int DiffMaskHi = Mask[DiffPos[1]];
3082 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3083 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3084 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3085 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3087 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3088 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3090 if (DiffMaskHi != DiffMaskLo + HalfSize)
3094 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3096 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3117 if (
SDValue Result = tryLowerToExtrAndIns(0))
3119 return tryLowerToExtrAndIns(NumElts);
3128 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3133 int MaskSize = Mask.size();
3139 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3141 for (
int i = 0; i < MaskSize; ++i) {
3142 if (Mask[i] ==
Base + i || Mask[i] == -1)
3144 if (Mask[i] != Replaced)
3155 int Idx = checkReplaceOne(0, MaskSize);
3157 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3161 Idx = checkReplaceOne(MaskSize, 0);
3163 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3174 int MaskSize = Mask.size();
3175 int HalfSize = Mask.size() / 2;
3176 const auto &Begin = Mask.begin();
3177 const auto &Mid = Mask.begin() + HalfSize;
3178 const auto &
End = Mask.end();
3190 for (
auto it = Begin; it < Mid; it++) {
3193 else if ((*it >= 0 && *it < HalfSize) ||
3194 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3195 int M = *it < HalfSize ? *it : *it - HalfSize;
3200 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3202 for (
auto it = Mid; it <
End; it++) {
3205 else if ((*it >= HalfSize && *it < MaskSize) ||
3206 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3207 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3212 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3216 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3244 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3246 int MaskSize = Mask.size();
3247 int HalfSize = Mask.size() / 2;
3250 HalfMaskType preMask =
None, postMask =
None;
3252 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3253 return M < 0 || (M >= 0 && M < HalfSize) ||
3254 (M >= MaskSize && M < MaskSize + HalfSize);
3256 preMask = HighLaneTy;
3257 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3258 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3259 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3261 preMask = LowLaneTy;
3263 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3264 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3265 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3267 postMask = LowLaneTy;
3268 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3269 return M < 0 || (M >= 0 && M < HalfSize) ||
3270 (M >= MaskSize && M < MaskSize + HalfSize);
3272 postMask = HighLaneTy;
3280 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3283 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3291 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3296 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3297 *it = *it < 0 ? *it : *it - HalfSize;
3299 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3300 *it = *it < 0 ? *it : *it + HalfSize;
3302 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3310 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3315 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3316 *it = *it < 0 ? *it : *it - HalfSize;
3318 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3326 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3331 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3332 *it = *it < 0 ? *it : *it + HalfSize;
3359 int Lo = LaneMask[0] < 0 ? 0 : LaneMask[0];
3360 int Hi = LaneMask[1] < 0 ? 1 : LaneMask[1];
3362 LoongArchISD::XVPERMIQ,
DL, VT, V2,
V1,
3395 int Size = Mask.size();
3396 int LaneSize =
Size / 2;
3400 int LaneSrcs[2][2] = {{-1, -1}, {-1, -1}};
3402 bool LaneCrossing =
false;
3403 for (
int i = 0; i <
Size; ++i) {
3407 int Lane = i / LaneSize;
3408 int SrcLane = M / LaneSize;
3412 int Op = (SrcLane % 2) != Lane;
3414 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3416 if (LaneSrcs[Lane][
Op] >= 0 && LaneSrcs[Lane][
Op] != SrcLane)
3418 LaneSrcs[Lane][
Op] = SrcLane;
3419 InLaneMask[i] =
Op *
Size + Lane * LaneSize + M % LaneSize;
3430 for (
int i = LaneSize; i <
Size; ++i)
3431 if (SwappedMask[i] >= 0)
3432 SwappedMask[i] = (SwappedMask[i] +
Size) % (2 *
Size);
3434 std::swap(LaneSrcs[1][0], LaneSrcs[1][1]);
3435 InLaneMask = SwappedMask;
3441 for (
int Op = 0;
Op < 2; ++
Op) {
3443 for (
int Lane = 0; Lane < 2; ++Lane)
3444 if (LaneSrcs[Lane][
Op] >= 0)
3445 for (
int i = 0; i < LaneSize; ++i)
3446 LaneMask[Lane * LaneSize + i] = LaneSrcs[Lane][
Op] * LaneSize + i;
3452 if (SVN->getMask() == Mask)
3468 "Vector type is unsupported for lasx!");
3470 "Two operands have different types!");
3472 "Unexpected mask size for shuffle!");
3473 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3474 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3476 APInt KnownUndef, KnownZero;
3478 APInt Zeroable = KnownUndef | KnownZero;
3569 ArrayRef<int> OrigMask = SVOp->
getMask();
3570 SDValue
V1 =
Op.getOperand(0);
3571 SDValue V2 =
Op.getOperand(1);
3572 MVT VT =
Op.getSimpleValueType();
3576 bool V1IsUndef =
V1.isUndef();
3577 bool V2IsUndef = V2.
isUndef();
3578 if (V1IsUndef && V2IsUndef)
3591 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3592 SmallVector<int, 8> NewMask(OrigMask);
3593 for (
int &M : NewMask)
3594 if (M >= NumElements)
3600 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3601 (void)MaskUpperLimit;
3603 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3604 "Out of bounds shuffle index");
3622 SDValue Op0 =
Op.getOperand(0);
3623 SDValue Chain = SDValue();
3626 std::tie(Res, Chain) =
3627 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3628 if (Subtarget.is64Bit())
3629 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3639 SDValue Op0 =
Op.getOperand(0);
3640 SDValue Chain = SDValue();
3641 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3645 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3646 CallOptions,
DL, Chain);
3652 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3658 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3659 if (Subtarget.is64Bit())
3660 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3666 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3667 MVT VT =
Op.getSimpleValueType();
3672 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3693 "Unsupported vector type for broadcast.");
3696 bool IsIdeneity =
true;
3698 for (
int i = 0; i !=
NumOps; i++) {
3700 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3712 auto ExtType = LN->getExtensionType();
3717 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3722 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3740 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3754 EVT ResTy,
unsigned first) {
3757 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3760 Node->op_begin() + first + NumElts);
3769 MVT VT =
Node->getSimpleValueType(0);
3770 EVT ResTy =
Op->getValueType(0);
3773 APInt SplatValue, SplatUndef;
3774 unsigned SplatBitSize;
3777 bool UseSameConstant =
true;
3778 SDValue ConstantValue;
3782 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3783 (!Subtarget.hasExtLASX() || !Is256Vec))
3789 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3791 SplatBitSize <= 64) {
3793 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3797 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3804 if ((Is128Vec && ResTy == MVT::v4i32) ||
3805 (Is256Vec && ResTy == MVT::v8i32))
3811 switch (SplatBitSize) {
3815 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3818 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3821 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3824 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3832 if (ViaVecTy != ResTy)
3841 for (
unsigned i = 0; i < NumElts; ++i) {
3842 SDValue Opi =
Node->getOperand(i);
3846 ConstantValue = Opi;
3847 else if (ConstantValue != Opi)
3848 UseSameConstant =
false;
3853 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3855 for (
unsigned i = 0; i < NumElts; ++i) {
3856 SDValue Opi =
Node->getOperand(i);
3873 BitVector UndefElements;
3874 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3875 UndefElements.
count() == 0) {
3879 EVT FillTy = Is256Vec
3885 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3888 unsigned SplatLen = NumElts / SeqLen;
3894 if (SplatEltTy == MVT::i128)
3895 SplatTy = MVT::v4i64;
3903 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3904 : LoongArchISD::XVREPLVE0,
3905 DL, SplatTy, SrcVec);
3907 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3920 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3921 ResTy == MVT::v4f64) {
3922 unsigned NonUndefCount = 0;
3923 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3924 if (!
Node->getOperand(i).isUndef()) {
3926 if (NonUndefCount > 1)
3930 if (NonUndefCount == 1)
3943 VecTy, NumElts / 2);
3954 MVT ResVT =
Op.getSimpleValueType();
3962 unsigned NumFreezeUndef = 0;
3963 unsigned NumZero = 0;
3964 unsigned NumNonZero = 0;
3965 unsigned NonZeros = 0;
3966 SmallSet<SDValue, 4> Undefs;
3967 for (
unsigned i = 0; i != NumOperands; ++i) {
3968 SDValue SubVec =
Op.getOperand(i);
3982 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3989 if (NumNonZero > 2) {
3993 Ops.slice(0, NumOperands / 2));
3995 Ops.slice(NumOperands / 2));
4005 for (SDValue U : Undefs)
4008 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
4010 for (
unsigned i = 0; i != NumOperands; ++i) {
4011 if ((NonZeros & (1 << i)) == 0)
4022LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
4024 MVT EltVT =
Op.getSimpleValueType();
4025 SDValue Vec =
Op->getOperand(0);
4027 SDValue
Idx =
Op->getOperand(1);
4029 MVT GRLenVT = Subtarget.getGRLenVT();
4057 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
4061 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
4063 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
4071 SDValue SplatValue =
4072 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
4081LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
4083 MVT VT =
Op.getSimpleValueType();
4088 SDValue Op0 =
Op.getOperand(0);
4089 SDValue Op1 =
Op.getOperand(1);
4090 SDValue Op2 =
Op.getOperand(2);
4106 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4108 for (
unsigned i = 0; i < NumElts; ++i) {
4116 for (
unsigned i = 0; i < NumElts; ++i) {
4125 for (
unsigned i = 0; i < NumElts; ++i)
4178 MVT GRLenVT = Subtarget.getGRLenVT();
4180 SDValue Chain =
Op.getOperand(0);
4181 SDValue RMValue =
Op.getOperand(1);
4190 "rounding mode is not supported by LoongArch hardware",
4191 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4208 FCSRNo, RMValue, Chain);
4209 return SDValue(RN, 0);
4214 MVT GRLenVT = Subtarget.getGRLenVT();
4216 SDValue Chain =
Op->getOperand(0);
4221 MVT::Other, FCSRNo, Chain);
4222 SDValue RMValue = SDValue(FCSR, 0);
4223 Chain = SDValue(FCSR, 1);
4237 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4239 "On LA64, only 64-bit registers can be written.");
4240 return Op.getOperand(0);
4243 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4245 "On LA32, only 32-bit registers can be written.");
4246 return Op.getOperand(0);
4256 "be a constant integer");
4262 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4263 EVT VT =
Op.getValueType();
4266 unsigned Depth =
Op.getConstantOperandVal(0);
4267 int GRLenInBytes = Subtarget.getGRLen() / 8;
4270 int Offset = -(GRLenInBytes * 2);
4282 if (
Op.getConstantOperandVal(0) != 0) {
4284 "return address can only be determined for the current frame");
4290 MVT GRLenVT = Subtarget.getGRLenVT();
4302 auto Size = Subtarget.getGRLen() / 8;
4310 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4313 SDValue FI = DAG.
getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
4320 MachinePointerInfo(SV));
4326 SDValue Op0 =
Op.getOperand(0);
4327 EVT VT =
Op.getValueType();
4342 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4350 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4353 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4354 !Subtarget.hasBasicD() &&
"unexpected target features");
4358 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4362 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4372 EVT RetVT =
Op.getValueType();
4376 SDValue Chain = SDValue();
4378 std::tie(Result, Chain) =
4385 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4386 !Subtarget.hasBasicD() &&
"unexpected target features");
4389 SDValue Op0 =
Op.getOperand(0);
4397 EVT RetVT =
Op.getValueType();
4401 SDValue Chain = SDValue();
4403 std::tie(Result, Chain) =
4412 EVT VT =
Op.getValueType();
4413 SDValue Op0 =
Op.getOperand(0);
4416 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4417 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4419 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4421 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4424 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4433 SDValue Op0 =
Op.getOperand(0);
4438 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4439 !Subtarget.hasBasicD()) {
4440 SDValue Dst = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f32, Op0);
4441 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4445 SDValue Trunc = DAG.
getNode(LoongArchISD::FTINT,
DL, FPTy, Op0);
4455 SDValue Src =
Op.getOperand(0);
4456 EVT VT =
Op.getValueType();
4457 EVT SrcVT = Src.getValueType();
4458 unsigned SatWidth =
cast<VTSDNode>(
Op.getOperand(1))->getVT().getSizeInBits();
4468 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4471 if (SatWidth == 32) {
4472 SDValue Ftint = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f32, Src);
4473 if (Subtarget.is64Bit())
4474 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, VT, Ftint);
4478 if (SatWidth == 64 && Subtarget.is64Bit() && Subtarget.hasBasicD()) {
4479 SDValue Ftint = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f64, Src);
4488 if (!Subtarget.hasExtLSX())
4492 SDValue Src =
Op.getOperand(0);
4493 EVT VT =
Op.getValueType();
4494 EVT SrcVT = Src.getValueType();
4499 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4502 if (SrcVT == MVT::f32)
4524 N->getOffset(), Flags);
4532template <
class NodeTy>
4535 bool IsLocal)
const {
4546 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4627 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4629 const GlobalValue *GV =
N->getGlobal();
4641 unsigned Opc,
bool UseGOT,
4645 MVT GRLenVT = Subtarget.getGRLenVT();
4653 SDValue
Offset =
Opc == LoongArch::PseudoLA_TLS_IE_LARGE
4655 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4659 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4693 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4700 TargetLowering::CallLoweringInfo CLI(DAG);
4715 const GlobalValue *GV =
N->getGlobal();
4725 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4729LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4736 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4739 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4752 return getDynamicTLSAddr(
N, DAG,
4753 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4754 : LoongArch::PseudoLA_TLS_GD,
4761 return getDynamicTLSAddr(
N, DAG,
4762 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4763 : LoongArch::PseudoLA_TLS_LD,
4768 return getStaticTLSAddr(
N, DAG,
4769 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4770 : LoongArch::PseudoLA_TLS_IE,
4777 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4781 return getTLSDescAddr(
N, DAG,
4782 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4783 : LoongArch::PseudoLA_TLS_DESC,
4787template <
unsigned N>
4792 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4793 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4795 ": argument out of range.");
4802LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4804 switch (
Op.getConstantOperandVal(0)) {
4807 case Intrinsic::thread_pointer: {
4811 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4812 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4813 case Intrinsic::loongarch_lsx_vreplvei_d:
4814 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4816 case Intrinsic::loongarch_lsx_vreplvei_w:
4817 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4818 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4819 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4820 case Intrinsic::loongarch_lasx_xvpickve_d:
4821 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4823 case Intrinsic::loongarch_lasx_xvinsve0_d:
4825 case Intrinsic::loongarch_lsx_vsat_b:
4826 case Intrinsic::loongarch_lsx_vsat_bu:
4827 case Intrinsic::loongarch_lsx_vrotri_b:
4828 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4829 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4830 case Intrinsic::loongarch_lsx_vsrlri_b:
4831 case Intrinsic::loongarch_lsx_vsrari_b:
4832 case Intrinsic::loongarch_lsx_vreplvei_h:
4833 case Intrinsic::loongarch_lasx_xvsat_b:
4834 case Intrinsic::loongarch_lasx_xvsat_bu:
4835 case Intrinsic::loongarch_lasx_xvrotri_b:
4836 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4837 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4838 case Intrinsic::loongarch_lasx_xvsrlri_b:
4839 case Intrinsic::loongarch_lasx_xvsrari_b:
4840 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4841 case Intrinsic::loongarch_lasx_xvpickve_w:
4842 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4844 case Intrinsic::loongarch_lasx_xvinsve0_w:
4846 case Intrinsic::loongarch_lsx_vsat_h:
4847 case Intrinsic::loongarch_lsx_vsat_hu:
4848 case Intrinsic::loongarch_lsx_vrotri_h:
4849 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4850 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4851 case Intrinsic::loongarch_lsx_vsrlri_h:
4852 case Intrinsic::loongarch_lsx_vsrari_h:
4853 case Intrinsic::loongarch_lsx_vreplvei_b:
4854 case Intrinsic::loongarch_lasx_xvsat_h:
4855 case Intrinsic::loongarch_lasx_xvsat_hu:
4856 case Intrinsic::loongarch_lasx_xvrotri_h:
4857 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4858 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4859 case Intrinsic::loongarch_lasx_xvsrlri_h:
4860 case Intrinsic::loongarch_lasx_xvsrari_h:
4861 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4863 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4864 case Intrinsic::loongarch_lsx_vsrani_b_h:
4865 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4866 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4867 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4868 case Intrinsic::loongarch_lsx_vssrani_b_h:
4869 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4870 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4871 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4872 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4873 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4874 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4875 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4876 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4877 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4878 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4879 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4880 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4881 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4882 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4883 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4884 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4885 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4886 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4888 case Intrinsic::loongarch_lsx_vsat_w:
4889 case Intrinsic::loongarch_lsx_vsat_wu:
4890 case Intrinsic::loongarch_lsx_vrotri_w:
4891 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4892 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4893 case Intrinsic::loongarch_lsx_vsrlri_w:
4894 case Intrinsic::loongarch_lsx_vsrari_w:
4895 case Intrinsic::loongarch_lsx_vslei_bu:
4896 case Intrinsic::loongarch_lsx_vslei_hu:
4897 case Intrinsic::loongarch_lsx_vslei_wu:
4898 case Intrinsic::loongarch_lsx_vslei_du:
4899 case Intrinsic::loongarch_lsx_vslti_bu:
4900 case Intrinsic::loongarch_lsx_vslti_hu:
4901 case Intrinsic::loongarch_lsx_vslti_wu:
4902 case Intrinsic::loongarch_lsx_vslti_du:
4903 case Intrinsic::loongarch_lsx_vbsll_v:
4904 case Intrinsic::loongarch_lsx_vbsrl_v:
4905 case Intrinsic::loongarch_lasx_xvsat_w:
4906 case Intrinsic::loongarch_lasx_xvsat_wu:
4907 case Intrinsic::loongarch_lasx_xvrotri_w:
4908 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4909 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4910 case Intrinsic::loongarch_lasx_xvsrlri_w:
4911 case Intrinsic::loongarch_lasx_xvsrari_w:
4912 case Intrinsic::loongarch_lasx_xvslei_bu:
4913 case Intrinsic::loongarch_lasx_xvslei_hu:
4914 case Intrinsic::loongarch_lasx_xvslei_wu:
4915 case Intrinsic::loongarch_lasx_xvslei_du:
4916 case Intrinsic::loongarch_lasx_xvslti_bu:
4917 case Intrinsic::loongarch_lasx_xvslti_hu:
4918 case Intrinsic::loongarch_lasx_xvslti_wu:
4919 case Intrinsic::loongarch_lasx_xvslti_du:
4920 case Intrinsic::loongarch_lasx_xvbsll_v:
4921 case Intrinsic::loongarch_lasx_xvbsrl_v:
4923 case Intrinsic::loongarch_lsx_vseqi_b:
4924 case Intrinsic::loongarch_lsx_vseqi_h:
4925 case Intrinsic::loongarch_lsx_vseqi_w:
4926 case Intrinsic::loongarch_lsx_vseqi_d:
4927 case Intrinsic::loongarch_lsx_vslei_b:
4928 case Intrinsic::loongarch_lsx_vslei_h:
4929 case Intrinsic::loongarch_lsx_vslei_w:
4930 case Intrinsic::loongarch_lsx_vslei_d:
4931 case Intrinsic::loongarch_lsx_vslti_b:
4932 case Intrinsic::loongarch_lsx_vslti_h:
4933 case Intrinsic::loongarch_lsx_vslti_w:
4934 case Intrinsic::loongarch_lsx_vslti_d:
4935 case Intrinsic::loongarch_lasx_xvseqi_b:
4936 case Intrinsic::loongarch_lasx_xvseqi_h:
4937 case Intrinsic::loongarch_lasx_xvseqi_w:
4938 case Intrinsic::loongarch_lasx_xvseqi_d:
4939 case Intrinsic::loongarch_lasx_xvslei_b:
4940 case Intrinsic::loongarch_lasx_xvslei_h:
4941 case Intrinsic::loongarch_lasx_xvslei_w:
4942 case Intrinsic::loongarch_lasx_xvslei_d:
4943 case Intrinsic::loongarch_lasx_xvslti_b:
4944 case Intrinsic::loongarch_lasx_xvslti_h:
4945 case Intrinsic::loongarch_lasx_xvslti_w:
4946 case Intrinsic::loongarch_lasx_xvslti_d:
4948 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4949 case Intrinsic::loongarch_lsx_vsrani_h_w:
4950 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4951 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4952 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4953 case Intrinsic::loongarch_lsx_vssrani_h_w:
4954 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4955 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4956 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4957 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4958 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4959 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4960 case Intrinsic::loongarch_lsx_vfrstpi_b:
4961 case Intrinsic::loongarch_lsx_vfrstpi_h:
4962 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4963 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4964 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4965 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4966 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4967 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4968 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4969 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4970 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4971 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4972 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4973 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4974 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4975 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4977 case Intrinsic::loongarch_lsx_vsat_d:
4978 case Intrinsic::loongarch_lsx_vsat_du:
4979 case Intrinsic::loongarch_lsx_vrotri_d:
4980 case Intrinsic::loongarch_lsx_vsrlri_d:
4981 case Intrinsic::loongarch_lsx_vsrari_d:
4982 case Intrinsic::loongarch_lasx_xvsat_d:
4983 case Intrinsic::loongarch_lasx_xvsat_du:
4984 case Intrinsic::loongarch_lasx_xvrotri_d:
4985 case Intrinsic::loongarch_lasx_xvsrlri_d:
4986 case Intrinsic::loongarch_lasx_xvsrari_d:
4988 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4989 case Intrinsic::loongarch_lsx_vsrani_w_d:
4990 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4991 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4992 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4993 case Intrinsic::loongarch_lsx_vssrani_w_d:
4994 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4995 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4996 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4997 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4998 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4999 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
5000 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
5001 case Intrinsic::loongarch_lasx_xvsrani_w_d:
5002 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
5003 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
5004 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
5005 case Intrinsic::loongarch_lasx_xvssrani_w_d:
5006 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
5007 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
5008 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
5009 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
5010 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
5011 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
5013 case Intrinsic::loongarch_lsx_vsrlni_d_q:
5014 case Intrinsic::loongarch_lsx_vsrani_d_q:
5015 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
5016 case Intrinsic::loongarch_lsx_vsrarni_d_q:
5017 case Intrinsic::loongarch_lsx_vssrlni_d_q:
5018 case Intrinsic::loongarch_lsx_vssrani_d_q:
5019 case Intrinsic::loongarch_lsx_vssrlni_du_q:
5020 case Intrinsic::loongarch_lsx_vssrani_du_q:
5021 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
5022 case Intrinsic::loongarch_lsx_vssrarni_d_q:
5023 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
5024 case Intrinsic::loongarch_lsx_vssrarni_du_q:
5025 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
5026 case Intrinsic::loongarch_lasx_xvsrani_d_q:
5027 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
5028 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
5029 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
5030 case Intrinsic::loongarch_lasx_xvssrani_d_q:
5031 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
5032 case Intrinsic::loongarch_lasx_xvssrani_du_q:
5033 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
5034 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
5035 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
5036 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
5038 case Intrinsic::loongarch_lsx_vnori_b:
5039 case Intrinsic::loongarch_lsx_vshuf4i_b:
5040 case Intrinsic::loongarch_lsx_vshuf4i_h:
5041 case Intrinsic::loongarch_lsx_vshuf4i_w:
5042 case Intrinsic::loongarch_lasx_xvnori_b:
5043 case Intrinsic::loongarch_lasx_xvshuf4i_b:
5044 case Intrinsic::loongarch_lasx_xvshuf4i_h:
5045 case Intrinsic::loongarch_lasx_xvshuf4i_w:
5046 case Intrinsic::loongarch_lasx_xvpermi_d:
5048 case Intrinsic::loongarch_lsx_vshuf4i_d:
5049 case Intrinsic::loongarch_lsx_vpermi_w:
5050 case Intrinsic::loongarch_lsx_vbitseli_b:
5051 case Intrinsic::loongarch_lsx_vextrins_b:
5052 case Intrinsic::loongarch_lsx_vextrins_h:
5053 case Intrinsic::loongarch_lsx_vextrins_w:
5054 case Intrinsic::loongarch_lsx_vextrins_d:
5055 case Intrinsic::loongarch_lasx_xvshuf4i_d:
5056 case Intrinsic::loongarch_lasx_xvpermi_w:
5057 case Intrinsic::loongarch_lasx_xvpermi_q:
5058 case Intrinsic::loongarch_lasx_xvbitseli_b:
5059 case Intrinsic::loongarch_lasx_xvextrins_b:
5060 case Intrinsic::loongarch_lasx_xvextrins_h:
5061 case Intrinsic::loongarch_lasx_xvextrins_w:
5062 case Intrinsic::loongarch_lasx_xvextrins_d:
5064 case Intrinsic::loongarch_lsx_vrepli_b:
5065 case Intrinsic::loongarch_lsx_vrepli_h:
5066 case Intrinsic::loongarch_lsx_vrepli_w:
5067 case Intrinsic::loongarch_lsx_vrepli_d:
5068 case Intrinsic::loongarch_lasx_xvrepli_b:
5069 case Intrinsic::loongarch_lasx_xvrepli_h:
5070 case Intrinsic::loongarch_lasx_xvrepli_w:
5071 case Intrinsic::loongarch_lasx_xvrepli_d:
5073 case Intrinsic::loongarch_lsx_vldi:
5074 case Intrinsic::loongarch_lasx_xvldi:
5090LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
5093 MVT GRLenVT = Subtarget.getGRLenVT();
5094 EVT VT =
Op.getValueType();
5095 SDValue Chain =
Op.getOperand(0);
5096 const StringRef ErrorMsgOOR =
"argument out of range";
5097 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5098 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5100 switch (
Op.getConstantOperandVal(1)) {
5103 case Intrinsic::loongarch_crc_w_b_w:
5104 case Intrinsic::loongarch_crc_w_h_w:
5105 case Intrinsic::loongarch_crc_w_w_w:
5106 case Intrinsic::loongarch_crc_w_d_w:
5107 case Intrinsic::loongarch_crcc_w_b_w:
5108 case Intrinsic::loongarch_crcc_w_h_w:
5109 case Intrinsic::loongarch_crcc_w_w_w:
5110 case Intrinsic::loongarch_crcc_w_d_w:
5112 case Intrinsic::loongarch_csrrd_w:
5113 case Intrinsic::loongarch_csrrd_d: {
5114 unsigned Imm =
Op.getConstantOperandVal(2);
5117 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5120 case Intrinsic::loongarch_csrwr_w:
5121 case Intrinsic::loongarch_csrwr_d: {
5122 unsigned Imm =
Op.getConstantOperandVal(3);
5125 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5126 {Chain,
Op.getOperand(2),
5129 case Intrinsic::loongarch_csrxchg_w:
5130 case Intrinsic::loongarch_csrxchg_d: {
5131 unsigned Imm =
Op.getConstantOperandVal(4);
5134 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5135 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5138 case Intrinsic::loongarch_iocsrrd_d: {
5140 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5143#define IOCSRRD_CASE(NAME, NODE) \
5144 case Intrinsic::loongarch_##NAME: { \
5145 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5146 {Chain, Op.getOperand(2)}); \
5152 case Intrinsic::loongarch_cpucfg: {
5153 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5154 {Chain,
Op.getOperand(2)});
5156 case Intrinsic::loongarch_lddir_d: {
5157 unsigned Imm =
Op.getConstantOperandVal(3);
5162 case Intrinsic::loongarch_movfcsr2gr: {
5163 if (!Subtarget.hasBasicF())
5165 unsigned Imm =
Op.getConstantOperandVal(2);
5168 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5171 case Intrinsic::loongarch_lsx_vld:
5172 case Intrinsic::loongarch_lsx_vldrepl_b:
5173 case Intrinsic::loongarch_lasx_xvld:
5174 case Intrinsic::loongarch_lasx_xvldrepl_b:
5178 case Intrinsic::loongarch_lsx_vldrepl_h:
5179 case Intrinsic::loongarch_lasx_xvldrepl_h:
5183 Op,
"argument out of range or not a multiple of 2", DAG)
5185 case Intrinsic::loongarch_lsx_vldrepl_w:
5186 case Intrinsic::loongarch_lasx_xvldrepl_w:
5190 Op,
"argument out of range or not a multiple of 4", DAG)
5192 case Intrinsic::loongarch_lsx_vldrepl_d:
5193 case Intrinsic::loongarch_lasx_xvldrepl_d:
5197 Op,
"argument out of range or not a multiple of 8", DAG)
5208 return Op.getOperand(0);
5214 MVT GRLenVT = Subtarget.getGRLenVT();
5215 SDValue Chain =
Op.getOperand(0);
5216 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5217 SDValue Op2 =
Op.getOperand(2);
5218 const StringRef ErrorMsgOOR =
"argument out of range";
5219 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5220 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5221 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5223 switch (IntrinsicEnum) {
5227 case Intrinsic::loongarch_cacop_d:
5228 case Intrinsic::loongarch_cacop_w: {
5229 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5231 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5240 case Intrinsic::loongarch_dbar: {
5247 case Intrinsic::loongarch_ibar: {
5254 case Intrinsic::loongarch_break: {
5261 case Intrinsic::loongarch_movgr2fcsr: {
5262 if (!Subtarget.hasBasicF())
5272 case Intrinsic::loongarch_syscall: {
5279#define IOCSRWR_CASE(NAME, NODE) \
5280 case Intrinsic::loongarch_##NAME: { \
5281 SDValue Op3 = Op.getOperand(3); \
5282 return Subtarget.is64Bit() \
5283 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5284 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5285 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5286 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5293 case Intrinsic::loongarch_iocsrwr_d: {
5294 return !Subtarget.is64Bit()
5301#define ASRT_LE_GT_CASE(NAME) \
5302 case Intrinsic::loongarch_##NAME: { \
5303 return !Subtarget.is64Bit() \
5304 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5309#undef ASRT_LE_GT_CASE
5310 case Intrinsic::loongarch_ldpte_d: {
5311 unsigned Imm =
Op.getConstantOperandVal(3);
5312 return !Subtarget.is64Bit()
5317 case Intrinsic::loongarch_lsx_vst:
5318 case Intrinsic::loongarch_lasx_xvst:
5322 case Intrinsic::loongarch_lasx_xvstelm_b:
5327 case Intrinsic::loongarch_lsx_vstelm_b:
5332 case Intrinsic::loongarch_lasx_xvstelm_h:
5337 Op,
"argument out of range or not a multiple of 2", DAG)
5339 case Intrinsic::loongarch_lsx_vstelm_h:
5344 Op,
"argument out of range or not a multiple of 2", DAG)
5346 case Intrinsic::loongarch_lasx_xvstelm_w:
5351 Op,
"argument out of range or not a multiple of 4", DAG)
5353 case Intrinsic::loongarch_lsx_vstelm_w:
5358 Op,
"argument out of range or not a multiple of 4", DAG)
5360 case Intrinsic::loongarch_lasx_xvstelm_d:
5365 Op,
"argument out of range or not a multiple of 8", DAG)
5367 case Intrinsic::loongarch_lsx_vstelm_d:
5372 Op,
"argument out of range or not a multiple of 8", DAG)
5380 SDValue
Lo =
Op.getOperand(0);
5381 SDValue
Hi =
Op.getOperand(1);
5382 SDValue Shamt =
Op.getOperand(2);
5383 EVT VT =
Lo.getValueType();
5394 SDValue MinusGRLen =
5396 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5402 SDValue ShiftRightLo =
5413 SDValue Parts[2] = {
Lo,
Hi};
5421 SDValue
Lo =
Op.getOperand(0);
5422 SDValue
Hi =
Op.getOperand(1);
5423 SDValue Shamt =
Op.getOperand(2);
5424 EVT VT =
Lo.getValueType();
5446 SDValue MinusGRLen =
5448 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5454 SDValue ShiftLeftHi =
5457 SDValue HiTrue = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, Shamt);
5458 SDValue LoFalse = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, ShamtMinusGRLen);
5467 SDValue Parts[2] = {
Lo,
Hi};
5478 return LoongArchISD::DIV_W;
5480 return LoongArchISD::DIV_WU;
5482 return LoongArchISD::MOD_W;
5484 return LoongArchISD::MOD_WU;
5486 return LoongArchISD::SLL_W;
5488 return LoongArchISD::SRA_W;
5490 return LoongArchISD::SRL_W;
5493 return LoongArchISD::ROTR_W;
5495 return LoongArchISD::CTZ_W;
5497 return LoongArchISD::CLZ_W;
5516 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5517 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5521 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5527 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5554 StringRef ErrorMsg,
bool WithChain =
true) {
5559 Results.push_back(
N->getOperand(0));
5562template <
unsigned N>
5567 const StringRef ErrorMsgOOR =
"argument out of range";
5568 unsigned Imm =
Node->getConstantOperandVal(2);
5602 switch (
N->getConstantOperandVal(0)) {
5605 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5607 LoongArchISD::VPICK_SEXT_ELT);
5609 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5610 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5612 LoongArchISD::VPICK_SEXT_ELT);
5614 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5616 LoongArchISD::VPICK_SEXT_ELT);
5618 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5620 LoongArchISD::VPICK_ZEXT_ELT);
5622 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5623 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5625 LoongArchISD::VPICK_ZEXT_ELT);
5627 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5629 LoongArchISD::VPICK_ZEXT_ELT);
5631 case Intrinsic::loongarch_lsx_bz_b:
5632 case Intrinsic::loongarch_lsx_bz_h:
5633 case Intrinsic::loongarch_lsx_bz_w:
5634 case Intrinsic::loongarch_lsx_bz_d:
5635 case Intrinsic::loongarch_lasx_xbz_b:
5636 case Intrinsic::loongarch_lasx_xbz_h:
5637 case Intrinsic::loongarch_lasx_xbz_w:
5638 case Intrinsic::loongarch_lasx_xbz_d:
5640 LoongArchISD::VALL_ZERO);
5642 case Intrinsic::loongarch_lsx_bz_v:
5643 case Intrinsic::loongarch_lasx_xbz_v:
5645 LoongArchISD::VANY_ZERO);
5647 case Intrinsic::loongarch_lsx_bnz_b:
5648 case Intrinsic::loongarch_lsx_bnz_h:
5649 case Intrinsic::loongarch_lsx_bnz_w:
5650 case Intrinsic::loongarch_lsx_bnz_d:
5651 case Intrinsic::loongarch_lasx_xbnz_b:
5652 case Intrinsic::loongarch_lasx_xbnz_h:
5653 case Intrinsic::loongarch_lasx_xbnz_w:
5654 case Intrinsic::loongarch_lasx_xbnz_d:
5656 LoongArchISD::VALL_NONZERO);
5658 case Intrinsic::loongarch_lsx_bnz_v:
5659 case Intrinsic::loongarch_lasx_xbnz_v:
5661 LoongArchISD::VANY_NONZERO);
5669 assert(
N->getValueType(0) == MVT::i128 &&
5670 "AtomicCmpSwap on types less than 128 should be legal");
5674 switch (
MemOp->getMergedOrdering()) {
5678 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5682 Opcode = LoongArch::PseudoCmpXchg128;
5689 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5690 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5691 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5692 NewVal.first, NewVal.second,
N->getOperand(0)};
5695 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5706 EVT VT =
N->getValueType(0);
5707 switch (
N->getOpcode()) {
5712 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5713 "Unexpected custom legalisation");
5720 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5721 "Unexpected custom legalisation");
5723 Subtarget.hasDiv32() && VT == MVT::i32
5730 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5731 "Unexpected custom legalisation");
5739 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5740 "Unexpected custom legalisation");
5747 MVT VT =
N->getSimpleValueType(0);
5748 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5749 "Unexpected custom legalisation");
5751 "Unexpected type action!");
5756 Ld->getPointerInfo(), Ld->getBaseAlign(),
5757 Ld->getMemOperand()->getFlags());
5768 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5769 "Unexpected custom legalisation");
5776 if (Src.getValueType() == MVT::f16)
5787 EVT OpVT = Src.getValueType();
5791 std::tie(Result, Chain) =
5798 EVT SrcVT = Src.getValueType();
5799 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5800 Subtarget.hasBasicF()) {
5802 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5804 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5806 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5814 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5815 "Unexpected custom legalisation");
5818 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5823 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5824 "Unexpected custom legalisation");
5830 if (OpVT == MVT::v2f64) {
5840 assert((VT == MVT::i16 || VT == MVT::i32) &&
5841 "Unexpected custom legalization");
5842 MVT GRLenVT = Subtarget.getGRLenVT();
5849 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5854 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5862 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5863 "Unexpected custom legalization");
5864 MVT GRLenVT = Subtarget.getGRLenVT();
5871 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5874 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5882 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5883 "Unexpected custom legalisation");
5890 MVT GRLenVT = Subtarget.getGRLenVT();
5891 const StringRef ErrorMsgOOR =
"argument out of range";
5892 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5893 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5895 switch (
N->getConstantOperandVal(1)) {
5898 case Intrinsic::loongarch_movfcsr2gr: {
5899 if (!Subtarget.hasBasicF()) {
5909 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5916#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5917 case Intrinsic::loongarch_##NAME: { \
5918 SDValue NODE = DAG.getNode( \
5919 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5920 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5921 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5922 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5923 Results.push_back(NODE.getValue(1)); \
5932#undef CRC_CASE_EXT_BINARYOP
5934#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5935 case Intrinsic::loongarch_##NAME: { \
5936 SDValue NODE = DAG.getNode( \
5937 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5939 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5940 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5941 Results.push_back(NODE.getValue(1)); \
5946#undef CRC_CASE_EXT_UNARYOP
5947#define CSR_CASE(ID) \
5948 case Intrinsic::loongarch_##ID: { \
5949 if (!Subtarget.is64Bit()) \
5950 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5958 case Intrinsic::loongarch_csrrd_w: {
5965 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5972 case Intrinsic::loongarch_csrwr_w: {
5973 unsigned Imm =
N->getConstantOperandVal(3);
5979 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5987 case Intrinsic::loongarch_csrxchg_w: {
5988 unsigned Imm =
N->getConstantOperandVal(4);
5994 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
6003#define IOCSRRD_CASE(NAME, NODE) \
6004 case Intrinsic::loongarch_##NAME: { \
6005 SDValue IOCSRRDResults = \
6006 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
6007 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
6008 Results.push_back( \
6009 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
6010 Results.push_back(IOCSRRDResults.getValue(1)); \
6017 case Intrinsic::loongarch_cpucfg: {
6019 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
6026 case Intrinsic::loongarch_lddir_d: {
6027 if (!Subtarget.is64Bit()) {
6037 if (Subtarget.is64Bit())
6039 "On LA64, only 64-bit registers can be read.");
6042 "On LA32, only 32-bit registers can be read.");
6044 Results.push_back(
N->getOperand(0));
6055 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
6068 MVT VT =
N->getSimpleValueType(0);
6074 EVT InVT = In.getValueType();
6084 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6089 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
6092 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6101 for (
unsigned I = 0;
I < MinElts; ++
I)
6102 TruncMask[
I] = Scale *
I;
6104 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
6105 MVT SVT = In.getSimpleValueType().getScalarType();
6111 "Illegal vector type in truncation");
6123 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
6126 EVT DstVT =
N->getValueType(0);
6128 MVT SrcVT = Src.getSimpleValueType();
6142 unsigned WidenSrcElts = 128 / SrcEltBits;
6149 unsigned FirstStageEltBits = 128 / NumElts;
6153 SrcVT = FirstStageVT;
6154 SrcEltBits = FirstStageEltBits;
6161 while (SrcEltBits < DstEltBits) {
6162 unsigned NextEltBits = SrcEltBits * 2;
6165 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6183 Blocks = std::move(NextBlocks);
6184 SrcVT = NextBlockVT;
6185 SrcEltBits = NextEltBits;
6202 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6204 MVT VT =
N->getSimpleValueType(0);
6223 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6227 unsigned MinSizeInBits) {
6235 unsigned SplatBitSize;
6238 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6239 HasAnyUndefs, MinSizeInBits,
6251 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6262 unsigned EltIdx = IdxC->getZExtValue();
6264 Start = (int)EltIdx - (
int)(i * 2);
6265 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6271 else if (Src != CurSrc)
6275 if (!Src || Start < 0)
6285 if (!Subtarget.hasExtLSX())
6288 unsigned Opc =
N->getOpcode();
6291 EVT VT =
N->getValueType(0);
6298 unsigned ExtOpc =
LHS.getOpcode();
6306 if (ExtOpc !=
RHS.getOpcode())
6309 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6312 unsigned OddIdx, EvenIdx;
6316 if (!LHSVec || !RHSVec)
6318 if (OddIdx != 1 || EvenIdx != 0)
6328 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6341 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6343 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6345 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6357 EVT VT =
N->getValueType(0);
6423 if (
And.getOperand(0) ==
X) {
6452 if (ShiftVal != (SplatVal + 1))
6461 : LoongArchISD::VSRAR,
6471 SDValue FirstOperand =
N->getOperand(0);
6472 SDValue SecondOperand =
N->getOperand(1);
6473 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6474 EVT ValTy =
N->getValueType(0);
6477 unsigned SMIdx, SMLen;
6486 if (!Subtarget.has32S())
6542 NewOperand = FirstOperand;
6545 msb = lsb + SMLen - 1;
6549 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6563 EVT DstVT =
N.getValueType();
6572 EVT SrcVT = Src.getValueType();
6580 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6591 if (NumElts % 2 != 0)
6597 for (
unsigned I = 0;
I != NumElts; ++
I) {
6612 SrcVT = Src.getValueType();
6622 }
else if (ThisSrc != Src) {
6626 unsigned Half = NumElts / 2;
6627 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6628 ExpectedIdx += isLow ? 0 : Half;
6630 if (CI->getZExtValue() != ExpectedIdx)
6642 EVT VT =
N->getValueType(0);
6649 unsigned ExtOpc =
LHS.getOpcode();
6657 if (!
LHS.hasOneUse())
6661 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6677 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6686 if (!Subtarget.has32S())
6698 SDValue FirstOperand =
N->getOperand(0);
6700 EVT ValTy =
N->getValueType(0);
6703 unsigned MaskIdx, MaskLen;
6718 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6719 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6743 switch (Src.getOpcode()) {
6746 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6756 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6769 switch (Src.getOpcode()) {
6779 Src.getOpcode(),
DL, SExtVT,
6785 DL, SExtVT, Src.getOperand(0),
6797 EVT VT =
N->getValueType(0);
6799 EVT SrcVT = Src.getValueType();
6801 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6806 EVT CmpVT = Src.getOperand(0).getValueType();
6811 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6824 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6829 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6834 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6839 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6841 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6846 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6848 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6853 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6870 EVT VT =
N->getValueType(0);
6872 EVT SrcVT = Src.getValueType();
6889 bool UseLASX =
false;
6890 bool PropagateSExt =
false;
6892 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6893 EVT CmpVT = Src.getOperand(0).getValueType();
6902 SExtVT = MVT::v2i64;
6905 SExtVT = MVT::v4i32;
6907 SExtVT = MVT::v4i64;
6909 PropagateSExt =
true;
6913 SExtVT = MVT::v8i16;
6915 SExtVT = MVT::v8i32;
6917 PropagateSExt =
true;
6921 SExtVT = MVT::v16i8;
6923 SExtVT = MVT::v16i16;
6925 PropagateSExt =
true;
6929 SExtVT = MVT::v32i8;
6937 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6938 if (Src.getSimpleValueType() == MVT::v32i8) {
6946 }
else if (UseLASX) {
6952 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6965 EVT ValTy =
N->getValueType(0);
6966 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6970 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6972 bool SwapAndRetried =
false;
6975 if (!Subtarget.has32S())
6981 if (ValBits != 32 && ValBits != 64)
6996 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6999 (MaskIdx0 + MaskLen0 <= ValBits)) {
7020 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
7021 (MaskIdx0 + MaskLen0 <= ValBits)) {
7038 (MaskIdx0 + MaskLen0 <= 64) &&
7046 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7047 : (MaskIdx0 + MaskLen0 - 1),
7063 (MaskIdx0 + MaskLen0 <= ValBits)) {
7086 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7087 : (MaskIdx0 + MaskLen0 - 1),
7102 unsigned MaskIdx, MaskLen;
7103 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
7112 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7130 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7136 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7144 if (!SwapAndRetried) {
7146 SwapAndRetried =
true;
7150 SwapAndRetried =
false;
7167 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7176 if (!SwapAndRetried) {
7178 SwapAndRetried =
true;
7188 switch (V.getNode()->getOpcode()) {
7200 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7208 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7238 unsigned MskOpc =
LHS.getOpcode();
7239 if (MskOpc != LoongArchISD::VMSKLTZ && MskOpc != LoongArchISD::XVMSKLTZ)
7242 if (!
LHS.hasOneUse())
7246 EVT SrcVT = Src.getValueType();
7253 : LoongArchISD::VALLZERO,
7323 SDLoc(
N), DAG, Subtarget))
7326 SDNode *AndNode =
N->getOperand(0).getNode();
7334 SDValue CmpInputValue =
N->getOperand(1);
7343 if (!CN || !CN->
isZero())
7345 AndInputValue1 = AndInputValue1.
getOperand(0);
7349 if (AndInputValue2 != CmpInputValue)
7382 TruncInputValue1, TruncInputValue2);
7403 return {V.getOperand(0),
cast<VTSDNode>(V.getOperand(1))->getVT()};
7424static std::tuple<unsigned, SDValue, EVT>
7428 unsigned Opc = Inner.getOpcode();
7433 if (Inner.getOperand(0) ==
X)
7434 return {
Opc, Inner.getOperand(1), ExtVT};
7435 if (Inner.getOperand(1) ==
X)
7436 return {
Opc, Inner.getOperand(0), ExtVT};
7440 if (Inner.getOperand(0) ==
X)
7441 return {
Opc, Inner.getOperand(1), ExtVT};
7463 EVT VT =
N->getValueType(0);
7475 bool BinIsTrueArm) ->
SDValue {
7483 if (Delta.getNode() ==
N)
7505 if (
SDValue R = TryFold(TrueV, FalseV,
true))
7507 if (
SDValue R = TryFold(FalseV, TrueV,
false))
7521 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7524 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7549 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7577 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7604 unsigned Sht =
LHS.getConstantOperandVal(1);
7608 if ((EleBits + Sht) == Subtarget.
getGRLen()) {
7618 EVT VT =
LHS.getValueType();
7642 DL, DAG, Subtarget))
7643 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7644 N->getOperand(0), V,
7649 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7650 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
7666 EVT VT =
N->getValueType(0);
7669 if (TrueV == FalseV)
7700 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7701 {LHS, RHS, CC, TrueV, FalseV});
7706template <
unsigned N>
7710 bool IsSigned =
false) {
7714 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7715 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7717 ": argument out of range.");
7723template <
unsigned N>
7727 EVT ResTy =
Node->getValueType(0);
7731 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7732 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7734 ": argument out of range.");
7739 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7745 EVT ResTy =
Node->getValueType(0);
7753 EVT ResTy =
Node->getValueType(0);
7762template <
unsigned N>
7765 EVT ResTy =
Node->getValueType(0);
7770 ": argument out of range.");
7780template <
unsigned N>
7783 EVT ResTy =
Node->getValueType(0);
7788 ": argument out of range.");
7797template <
unsigned N>
7800 EVT ResTy =
Node->getValueType(0);
7805 ": argument out of range.");
7814template <
unsigned W>
7817 unsigned Imm =
N->getConstantOperandVal(2);
7819 const StringRef ErrorMsg =
"argument out of range";
7821 return DAG.
getUNDEF(
N->getValueType(0));
7827 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7835 switch (
N->getConstantOperandVal(0)) {
7838 case Intrinsic::loongarch_lsx_vadd_b:
7839 case Intrinsic::loongarch_lsx_vadd_h:
7840 case Intrinsic::loongarch_lsx_vadd_w:
7841 case Intrinsic::loongarch_lsx_vadd_d:
7842 case Intrinsic::loongarch_lasx_xvadd_b:
7843 case Intrinsic::loongarch_lasx_xvadd_h:
7844 case Intrinsic::loongarch_lasx_xvadd_w:
7845 case Intrinsic::loongarch_lasx_xvadd_d:
7848 case Intrinsic::loongarch_lsx_vaddi_bu:
7849 case Intrinsic::loongarch_lsx_vaddi_hu:
7850 case Intrinsic::loongarch_lsx_vaddi_wu:
7851 case Intrinsic::loongarch_lsx_vaddi_du:
7852 case Intrinsic::loongarch_lasx_xvaddi_bu:
7853 case Intrinsic::loongarch_lasx_xvaddi_hu:
7854 case Intrinsic::loongarch_lasx_xvaddi_wu:
7855 case Intrinsic::loongarch_lasx_xvaddi_du:
7858 case Intrinsic::loongarch_lsx_vsub_b:
7859 case Intrinsic::loongarch_lsx_vsub_h:
7860 case Intrinsic::loongarch_lsx_vsub_w:
7861 case Intrinsic::loongarch_lsx_vsub_d:
7862 case Intrinsic::loongarch_lasx_xvsub_b:
7863 case Intrinsic::loongarch_lasx_xvsub_h:
7864 case Intrinsic::loongarch_lasx_xvsub_w:
7865 case Intrinsic::loongarch_lasx_xvsub_d:
7868 case Intrinsic::loongarch_lsx_vsubi_bu:
7869 case Intrinsic::loongarch_lsx_vsubi_hu:
7870 case Intrinsic::loongarch_lsx_vsubi_wu:
7871 case Intrinsic::loongarch_lsx_vsubi_du:
7872 case Intrinsic::loongarch_lasx_xvsubi_bu:
7873 case Intrinsic::loongarch_lasx_xvsubi_hu:
7874 case Intrinsic::loongarch_lasx_xvsubi_wu:
7875 case Intrinsic::loongarch_lasx_xvsubi_du:
7878 case Intrinsic::loongarch_lsx_vneg_b:
7879 case Intrinsic::loongarch_lsx_vneg_h:
7880 case Intrinsic::loongarch_lsx_vneg_w:
7881 case Intrinsic::loongarch_lsx_vneg_d:
7882 case Intrinsic::loongarch_lasx_xvneg_b:
7883 case Intrinsic::loongarch_lasx_xvneg_h:
7884 case Intrinsic::loongarch_lasx_xvneg_w:
7885 case Intrinsic::loongarch_lasx_xvneg_d:
7889 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7891 SDLoc(
N),
N->getValueType(0)),
7893 case Intrinsic::loongarch_lsx_vmax_b:
7894 case Intrinsic::loongarch_lsx_vmax_h:
7895 case Intrinsic::loongarch_lsx_vmax_w:
7896 case Intrinsic::loongarch_lsx_vmax_d:
7897 case Intrinsic::loongarch_lasx_xvmax_b:
7898 case Intrinsic::loongarch_lasx_xvmax_h:
7899 case Intrinsic::loongarch_lasx_xvmax_w:
7900 case Intrinsic::loongarch_lasx_xvmax_d:
7903 case Intrinsic::loongarch_lsx_vmax_bu:
7904 case Intrinsic::loongarch_lsx_vmax_hu:
7905 case Intrinsic::loongarch_lsx_vmax_wu:
7906 case Intrinsic::loongarch_lsx_vmax_du:
7907 case Intrinsic::loongarch_lasx_xvmax_bu:
7908 case Intrinsic::loongarch_lasx_xvmax_hu:
7909 case Intrinsic::loongarch_lasx_xvmax_wu:
7910 case Intrinsic::loongarch_lasx_xvmax_du:
7913 case Intrinsic::loongarch_lsx_vmaxi_b:
7914 case Intrinsic::loongarch_lsx_vmaxi_h:
7915 case Intrinsic::loongarch_lsx_vmaxi_w:
7916 case Intrinsic::loongarch_lsx_vmaxi_d:
7917 case Intrinsic::loongarch_lasx_xvmaxi_b:
7918 case Intrinsic::loongarch_lasx_xvmaxi_h:
7919 case Intrinsic::loongarch_lasx_xvmaxi_w:
7920 case Intrinsic::loongarch_lasx_xvmaxi_d:
7923 case Intrinsic::loongarch_lsx_vmaxi_bu:
7924 case Intrinsic::loongarch_lsx_vmaxi_hu:
7925 case Intrinsic::loongarch_lsx_vmaxi_wu:
7926 case Intrinsic::loongarch_lsx_vmaxi_du:
7927 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7928 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7929 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7930 case Intrinsic::loongarch_lasx_xvmaxi_du:
7933 case Intrinsic::loongarch_lsx_vmin_b:
7934 case Intrinsic::loongarch_lsx_vmin_h:
7935 case Intrinsic::loongarch_lsx_vmin_w:
7936 case Intrinsic::loongarch_lsx_vmin_d:
7937 case Intrinsic::loongarch_lasx_xvmin_b:
7938 case Intrinsic::loongarch_lasx_xvmin_h:
7939 case Intrinsic::loongarch_lasx_xvmin_w:
7940 case Intrinsic::loongarch_lasx_xvmin_d:
7943 case Intrinsic::loongarch_lsx_vmin_bu:
7944 case Intrinsic::loongarch_lsx_vmin_hu:
7945 case Intrinsic::loongarch_lsx_vmin_wu:
7946 case Intrinsic::loongarch_lsx_vmin_du:
7947 case Intrinsic::loongarch_lasx_xvmin_bu:
7948 case Intrinsic::loongarch_lasx_xvmin_hu:
7949 case Intrinsic::loongarch_lasx_xvmin_wu:
7950 case Intrinsic::loongarch_lasx_xvmin_du:
7953 case Intrinsic::loongarch_lsx_vmini_b:
7954 case Intrinsic::loongarch_lsx_vmini_h:
7955 case Intrinsic::loongarch_lsx_vmini_w:
7956 case Intrinsic::loongarch_lsx_vmini_d:
7957 case Intrinsic::loongarch_lasx_xvmini_b:
7958 case Intrinsic::loongarch_lasx_xvmini_h:
7959 case Intrinsic::loongarch_lasx_xvmini_w:
7960 case Intrinsic::loongarch_lasx_xvmini_d:
7963 case Intrinsic::loongarch_lsx_vmini_bu:
7964 case Intrinsic::loongarch_lsx_vmini_hu:
7965 case Intrinsic::loongarch_lsx_vmini_wu:
7966 case Intrinsic::loongarch_lsx_vmini_du:
7967 case Intrinsic::loongarch_lasx_xvmini_bu:
7968 case Intrinsic::loongarch_lasx_xvmini_hu:
7969 case Intrinsic::loongarch_lasx_xvmini_wu:
7970 case Intrinsic::loongarch_lasx_xvmini_du:
7973 case Intrinsic::loongarch_lsx_vmul_b:
7974 case Intrinsic::loongarch_lsx_vmul_h:
7975 case Intrinsic::loongarch_lsx_vmul_w:
7976 case Intrinsic::loongarch_lsx_vmul_d:
7977 case Intrinsic::loongarch_lasx_xvmul_b:
7978 case Intrinsic::loongarch_lasx_xvmul_h:
7979 case Intrinsic::loongarch_lasx_xvmul_w:
7980 case Intrinsic::loongarch_lasx_xvmul_d:
7983 case Intrinsic::loongarch_lsx_vmadd_b:
7984 case Intrinsic::loongarch_lsx_vmadd_h:
7985 case Intrinsic::loongarch_lsx_vmadd_w:
7986 case Intrinsic::loongarch_lsx_vmadd_d:
7987 case Intrinsic::loongarch_lasx_xvmadd_b:
7988 case Intrinsic::loongarch_lasx_xvmadd_h:
7989 case Intrinsic::loongarch_lasx_xvmadd_w:
7990 case Intrinsic::loongarch_lasx_xvmadd_d: {
7991 EVT ResTy =
N->getValueType(0);
7996 case Intrinsic::loongarch_lsx_vmsub_b:
7997 case Intrinsic::loongarch_lsx_vmsub_h:
7998 case Intrinsic::loongarch_lsx_vmsub_w:
7999 case Intrinsic::loongarch_lsx_vmsub_d:
8000 case Intrinsic::loongarch_lasx_xvmsub_b:
8001 case Intrinsic::loongarch_lasx_xvmsub_h:
8002 case Intrinsic::loongarch_lasx_xvmsub_w:
8003 case Intrinsic::loongarch_lasx_xvmsub_d: {
8004 EVT ResTy =
N->getValueType(0);
8009 case Intrinsic::loongarch_lsx_vdiv_b:
8010 case Intrinsic::loongarch_lsx_vdiv_h:
8011 case Intrinsic::loongarch_lsx_vdiv_w:
8012 case Intrinsic::loongarch_lsx_vdiv_d:
8013 case Intrinsic::loongarch_lasx_xvdiv_b:
8014 case Intrinsic::loongarch_lasx_xvdiv_h:
8015 case Intrinsic::loongarch_lasx_xvdiv_w:
8016 case Intrinsic::loongarch_lasx_xvdiv_d:
8019 case Intrinsic::loongarch_lsx_vdiv_bu:
8020 case Intrinsic::loongarch_lsx_vdiv_hu:
8021 case Intrinsic::loongarch_lsx_vdiv_wu:
8022 case Intrinsic::loongarch_lsx_vdiv_du:
8023 case Intrinsic::loongarch_lasx_xvdiv_bu:
8024 case Intrinsic::loongarch_lasx_xvdiv_hu:
8025 case Intrinsic::loongarch_lasx_xvdiv_wu:
8026 case Intrinsic::loongarch_lasx_xvdiv_du:
8029 case Intrinsic::loongarch_lsx_vmod_b:
8030 case Intrinsic::loongarch_lsx_vmod_h:
8031 case Intrinsic::loongarch_lsx_vmod_w:
8032 case Intrinsic::loongarch_lsx_vmod_d:
8033 case Intrinsic::loongarch_lasx_xvmod_b:
8034 case Intrinsic::loongarch_lasx_xvmod_h:
8035 case Intrinsic::loongarch_lasx_xvmod_w:
8036 case Intrinsic::loongarch_lasx_xvmod_d:
8039 case Intrinsic::loongarch_lsx_vmod_bu:
8040 case Intrinsic::loongarch_lsx_vmod_hu:
8041 case Intrinsic::loongarch_lsx_vmod_wu:
8042 case Intrinsic::loongarch_lsx_vmod_du:
8043 case Intrinsic::loongarch_lasx_xvmod_bu:
8044 case Intrinsic::loongarch_lasx_xvmod_hu:
8045 case Intrinsic::loongarch_lasx_xvmod_wu:
8046 case Intrinsic::loongarch_lasx_xvmod_du:
8049 case Intrinsic::loongarch_lsx_vand_v:
8050 case Intrinsic::loongarch_lasx_xvand_v:
8053 case Intrinsic::loongarch_lsx_vor_v:
8054 case Intrinsic::loongarch_lasx_xvor_v:
8057 case Intrinsic::loongarch_lsx_vxor_v:
8058 case Intrinsic::loongarch_lasx_xvxor_v:
8061 case Intrinsic::loongarch_lsx_vnor_v:
8062 case Intrinsic::loongarch_lasx_xvnor_v: {
8067 case Intrinsic::loongarch_lsx_vandi_b:
8068 case Intrinsic::loongarch_lasx_xvandi_b:
8071 case Intrinsic::loongarch_lsx_vori_b:
8072 case Intrinsic::loongarch_lasx_xvori_b:
8075 case Intrinsic::loongarch_lsx_vxori_b:
8076 case Intrinsic::loongarch_lasx_xvxori_b:
8079 case Intrinsic::loongarch_lsx_vsll_b:
8080 case Intrinsic::loongarch_lsx_vsll_h:
8081 case Intrinsic::loongarch_lsx_vsll_w:
8082 case Intrinsic::loongarch_lsx_vsll_d:
8083 case Intrinsic::loongarch_lasx_xvsll_b:
8084 case Intrinsic::loongarch_lasx_xvsll_h:
8085 case Intrinsic::loongarch_lasx_xvsll_w:
8086 case Intrinsic::loongarch_lasx_xvsll_d:
8089 case Intrinsic::loongarch_lsx_vslli_b:
8090 case Intrinsic::loongarch_lasx_xvslli_b:
8093 case Intrinsic::loongarch_lsx_vslli_h:
8094 case Intrinsic::loongarch_lasx_xvslli_h:
8097 case Intrinsic::loongarch_lsx_vslli_w:
8098 case Intrinsic::loongarch_lasx_xvslli_w:
8101 case Intrinsic::loongarch_lsx_vslli_d:
8102 case Intrinsic::loongarch_lasx_xvslli_d:
8105 case Intrinsic::loongarch_lsx_vsrl_b:
8106 case Intrinsic::loongarch_lsx_vsrl_h:
8107 case Intrinsic::loongarch_lsx_vsrl_w:
8108 case Intrinsic::loongarch_lsx_vsrl_d:
8109 case Intrinsic::loongarch_lasx_xvsrl_b:
8110 case Intrinsic::loongarch_lasx_xvsrl_h:
8111 case Intrinsic::loongarch_lasx_xvsrl_w:
8112 case Intrinsic::loongarch_lasx_xvsrl_d:
8115 case Intrinsic::loongarch_lsx_vsrli_b:
8116 case Intrinsic::loongarch_lasx_xvsrli_b:
8119 case Intrinsic::loongarch_lsx_vsrli_h:
8120 case Intrinsic::loongarch_lasx_xvsrli_h:
8123 case Intrinsic::loongarch_lsx_vsrli_w:
8124 case Intrinsic::loongarch_lasx_xvsrli_w:
8127 case Intrinsic::loongarch_lsx_vsrli_d:
8128 case Intrinsic::loongarch_lasx_xvsrli_d:
8131 case Intrinsic::loongarch_lsx_vsra_b:
8132 case Intrinsic::loongarch_lsx_vsra_h:
8133 case Intrinsic::loongarch_lsx_vsra_w:
8134 case Intrinsic::loongarch_lsx_vsra_d:
8135 case Intrinsic::loongarch_lasx_xvsra_b:
8136 case Intrinsic::loongarch_lasx_xvsra_h:
8137 case Intrinsic::loongarch_lasx_xvsra_w:
8138 case Intrinsic::loongarch_lasx_xvsra_d:
8141 case Intrinsic::loongarch_lsx_vsrai_b:
8142 case Intrinsic::loongarch_lasx_xvsrai_b:
8145 case Intrinsic::loongarch_lsx_vsrai_h:
8146 case Intrinsic::loongarch_lasx_xvsrai_h:
8149 case Intrinsic::loongarch_lsx_vsrai_w:
8150 case Intrinsic::loongarch_lasx_xvsrai_w:
8153 case Intrinsic::loongarch_lsx_vsrai_d:
8154 case Intrinsic::loongarch_lasx_xvsrai_d:
8157 case Intrinsic::loongarch_lsx_vclz_b:
8158 case Intrinsic::loongarch_lsx_vclz_h:
8159 case Intrinsic::loongarch_lsx_vclz_w:
8160 case Intrinsic::loongarch_lsx_vclz_d:
8161 case Intrinsic::loongarch_lasx_xvclz_b:
8162 case Intrinsic::loongarch_lasx_xvclz_h:
8163 case Intrinsic::loongarch_lasx_xvclz_w:
8164 case Intrinsic::loongarch_lasx_xvclz_d:
8166 case Intrinsic::loongarch_lsx_vpcnt_b:
8167 case Intrinsic::loongarch_lsx_vpcnt_h:
8168 case Intrinsic::loongarch_lsx_vpcnt_w:
8169 case Intrinsic::loongarch_lsx_vpcnt_d:
8170 case Intrinsic::loongarch_lasx_xvpcnt_b:
8171 case Intrinsic::loongarch_lasx_xvpcnt_h:
8172 case Intrinsic::loongarch_lasx_xvpcnt_w:
8173 case Intrinsic::loongarch_lasx_xvpcnt_d:
8175 case Intrinsic::loongarch_lsx_vbitclr_b:
8176 case Intrinsic::loongarch_lsx_vbitclr_h:
8177 case Intrinsic::loongarch_lsx_vbitclr_w:
8178 case Intrinsic::loongarch_lsx_vbitclr_d:
8179 case Intrinsic::loongarch_lasx_xvbitclr_b:
8180 case Intrinsic::loongarch_lasx_xvbitclr_h:
8181 case Intrinsic::loongarch_lasx_xvbitclr_w:
8182 case Intrinsic::loongarch_lasx_xvbitclr_d:
8184 case Intrinsic::loongarch_lsx_vbitclri_b:
8185 case Intrinsic::loongarch_lasx_xvbitclri_b:
8187 case Intrinsic::loongarch_lsx_vbitclri_h:
8188 case Intrinsic::loongarch_lasx_xvbitclri_h:
8190 case Intrinsic::loongarch_lsx_vbitclri_w:
8191 case Intrinsic::loongarch_lasx_xvbitclri_w:
8193 case Intrinsic::loongarch_lsx_vbitclri_d:
8194 case Intrinsic::loongarch_lasx_xvbitclri_d:
8196 case Intrinsic::loongarch_lsx_vbitset_b:
8197 case Intrinsic::loongarch_lsx_vbitset_h:
8198 case Intrinsic::loongarch_lsx_vbitset_w:
8199 case Intrinsic::loongarch_lsx_vbitset_d:
8200 case Intrinsic::loongarch_lasx_xvbitset_b:
8201 case Intrinsic::loongarch_lasx_xvbitset_h:
8202 case Intrinsic::loongarch_lasx_xvbitset_w:
8203 case Intrinsic::loongarch_lasx_xvbitset_d: {
8204 EVT VecTy =
N->getValueType(0);
8210 case Intrinsic::loongarch_lsx_vbitseti_b:
8211 case Intrinsic::loongarch_lasx_xvbitseti_b:
8213 case Intrinsic::loongarch_lsx_vbitseti_h:
8214 case Intrinsic::loongarch_lasx_xvbitseti_h:
8216 case Intrinsic::loongarch_lsx_vbitseti_w:
8217 case Intrinsic::loongarch_lasx_xvbitseti_w:
8219 case Intrinsic::loongarch_lsx_vbitseti_d:
8220 case Intrinsic::loongarch_lasx_xvbitseti_d:
8222 case Intrinsic::loongarch_lsx_vbitrev_b:
8223 case Intrinsic::loongarch_lsx_vbitrev_h:
8224 case Intrinsic::loongarch_lsx_vbitrev_w:
8225 case Intrinsic::loongarch_lsx_vbitrev_d:
8226 case Intrinsic::loongarch_lasx_xvbitrev_b:
8227 case Intrinsic::loongarch_lasx_xvbitrev_h:
8228 case Intrinsic::loongarch_lasx_xvbitrev_w:
8229 case Intrinsic::loongarch_lasx_xvbitrev_d: {
8230 EVT VecTy =
N->getValueType(0);
8236 case Intrinsic::loongarch_lsx_vbitrevi_b:
8237 case Intrinsic::loongarch_lasx_xvbitrevi_b:
8239 case Intrinsic::loongarch_lsx_vbitrevi_h:
8240 case Intrinsic::loongarch_lasx_xvbitrevi_h:
8242 case Intrinsic::loongarch_lsx_vbitrevi_w:
8243 case Intrinsic::loongarch_lasx_xvbitrevi_w:
8245 case Intrinsic::loongarch_lsx_vbitrevi_d:
8246 case Intrinsic::loongarch_lasx_xvbitrevi_d:
8248 case Intrinsic::loongarch_lsx_vfadd_s:
8249 case Intrinsic::loongarch_lsx_vfadd_d:
8250 case Intrinsic::loongarch_lasx_xvfadd_s:
8251 case Intrinsic::loongarch_lasx_xvfadd_d:
8254 case Intrinsic::loongarch_lsx_vfsub_s:
8255 case Intrinsic::loongarch_lsx_vfsub_d:
8256 case Intrinsic::loongarch_lasx_xvfsub_s:
8257 case Intrinsic::loongarch_lasx_xvfsub_d:
8260 case Intrinsic::loongarch_lsx_vfmul_s:
8261 case Intrinsic::loongarch_lsx_vfmul_d:
8262 case Intrinsic::loongarch_lasx_xvfmul_s:
8263 case Intrinsic::loongarch_lasx_xvfmul_d:
8266 case Intrinsic::loongarch_lsx_vfdiv_s:
8267 case Intrinsic::loongarch_lsx_vfdiv_d:
8268 case Intrinsic::loongarch_lasx_xvfdiv_s:
8269 case Intrinsic::loongarch_lasx_xvfdiv_d:
8272 case Intrinsic::loongarch_lsx_vfmadd_s:
8273 case Intrinsic::loongarch_lsx_vfmadd_d:
8274 case Intrinsic::loongarch_lasx_xvfmadd_s:
8275 case Intrinsic::loongarch_lasx_xvfmadd_d:
8277 N->getOperand(2),
N->getOperand(3));
8278 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
8280 N->getOperand(1),
N->getOperand(2),
8282 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
8283 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
8285 N->getOperand(1),
N->getOperand(2),
8287 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
8288 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
8290 N->getOperand(1),
N->getOperand(2),
8292 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
8294 N->getOperand(1),
N->getOperand(2),
8296 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
8297 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
8298 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
8299 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
8300 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
8301 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
8302 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
8303 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
8304 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
8307 case Intrinsic::loongarch_lsx_vreplve_b:
8308 case Intrinsic::loongarch_lsx_vreplve_h:
8309 case Intrinsic::loongarch_lsx_vreplve_w:
8310 case Intrinsic::loongarch_lsx_vreplve_d:
8311 case Intrinsic::loongarch_lasx_xvreplve_b:
8312 case Intrinsic::loongarch_lasx_xvreplve_h:
8313 case Intrinsic::loongarch_lasx_xvreplve_w:
8314 case Intrinsic::loongarch_lasx_xvreplve_d:
8315 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
8319 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8323 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8324 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8328 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8332 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8336 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8337 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8341 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8345 case Intrinsic::loongarch_lsx_bz_b:
8346 case Intrinsic::loongarch_lsx_bz_h:
8347 case Intrinsic::loongarch_lsx_bz_w:
8348 case Intrinsic::loongarch_lsx_bz_d:
8349 case Intrinsic::loongarch_lasx_xbz_b:
8350 case Intrinsic::loongarch_lasx_xbz_h:
8351 case Intrinsic::loongarch_lasx_xbz_w:
8352 case Intrinsic::loongarch_lasx_xbz_d:
8354 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8357 case Intrinsic::loongarch_lsx_bz_v:
8358 case Intrinsic::loongarch_lasx_xbz_v:
8360 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8363 case Intrinsic::loongarch_lsx_bnz_b:
8364 case Intrinsic::loongarch_lsx_bnz_h:
8365 case Intrinsic::loongarch_lsx_bnz_w:
8366 case Intrinsic::loongarch_lsx_bnz_d:
8367 case Intrinsic::loongarch_lasx_xbnz_b:
8368 case Intrinsic::loongarch_lasx_xbnz_h:
8369 case Intrinsic::loongarch_lasx_xbnz_w:
8370 case Intrinsic::loongarch_lasx_xbnz_d:
8372 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8375 case Intrinsic::loongarch_lsx_bnz_v:
8376 case Intrinsic::loongarch_lasx_xbnz_v:
8378 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8381 case Intrinsic::loongarch_lasx_concat_128_s:
8382 case Intrinsic::loongarch_lasx_concat_128_d:
8383 case Intrinsic::loongarch_lasx_concat_128:
8385 N->getOperand(1),
N->getOperand(2));
8397 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8409 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8411 "Unexpected value type!");
8420 MVT VT =
N->getSimpleValueType(0);
8441 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8454 APInt V =
C->getValueAPF().bitcastToAPInt();
8469 MVT VT =
N->getSimpleValueType(0);
8528 EVT VT =
N->getValueType(0);
8530 EVT SrcVT = Src.getValueType();
8536 if (SrcEltBits >= DstEltBits)
8543 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8555 unsigned BlockBits) {
8557 MVT DstVT =
N->getSimpleValueType(0);
8559 MVT SrcVT = Src.getSimpleValueType();
8566 Src.getOperand(0).getValueType() == BlockVT) {
8567 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8569 }
else if (SrcBits > BlockBits) {
8571 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8576 BlockBits = SrcBits;
8583 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8588 if (BlockBits == 256) {
8598 if (Blocks.
size() == 1)
8608 EVT VT =
N->getValueType(0);
8610 EVT SrcVT = Src.getValueType();
8616 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8619 if (SrcEltBits <= DstEltBits)
8622 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8636 if (VT != MVT::f32 && VT != MVT::f64)
8638 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8640 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8672 EVT VT =
N->getValueType(0);
8689 if (!Subtarget.hasExtLSX())
8693 EVT DstVT =
N->getValueType(0);
8695 EVT SrcVT = Src.getValueType();
8705 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8710 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8713 if (DstEltBits < 32) {
8719 if (SrcEltBits != 64 || DstEltBits != 32)
8724 if (Subtarget.hasExtLASX())
8785 Subtarget.hasExtLASX() && N1.
hasOneUse())
8797 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8807 EVT VT =
N.getValueType();
8824 switch (
N.getOpcode()) {
8840 EVT VT =
N->getValueType(0);
8848 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
8853 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
8855 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
8867 EVT VT =
N->getValueType(0);
8869 if (VT.
isVector() &&
N->getNumOperands() == 2)
8882 EVT VT =
N->getValueType(0);
8894 SDValue TrueVal =
N->getOperand(1);
8895 SDValue FalseVal =
N->getOperand(2);
8929 if (FalseVal.getOpcode() !=
ISD::ADD)
8932 SDValue Add0 = FalseVal.getOperand(0);
8933 SDValue Add1 = FalseVal.getOperand(1);
9003 : LoongArchISD::VSRAR,
9010 switch (
N->getOpcode()) {
9042 case LoongArchISD::BITREV_W:
9044 case LoongArchISD::BR_CC:
9046 case LoongArchISD::SELECT_CC:
9050 case LoongArchISD::MOVGR2FR_W_LA64:
9052 case LoongArchISD::MOVFR2GR_S_LA64:
9054 case LoongArchISD::CRC_W_B_W:
9055 case LoongArchISD::CRC_W_H_W:
9056 case LoongArchISD::CRCC_W_B_W:
9057 case LoongArchISD::CRCC_W_H_W:
9058 case LoongArchISD::VMSKLTZ:
9059 case LoongArchISD::XVMSKLTZ:
9061 case LoongArchISD::SPLIT_PAIR_F64:
9063 case LoongArchISD::VANDN:
9069 case LoongArchISD::VPACKEV:
9070 case LoongArchISD::VPERMI:
9096 MF->
insert(It, BreakMBB);
9100 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
9101 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
9113 MBB->addSuccessor(BreakMBB);
9114 MBB->addSuccessor(SinkMBB);
9120 BreakMBB->addSuccessor(SinkMBB);
9132 switch (
MI.getOpcode()) {
9135 case LoongArch::PseudoVBZ:
9136 CondOpc = LoongArch::VSETEQZ_V;
9138 case LoongArch::PseudoVBZ_B:
9139 CondOpc = LoongArch::VSETANYEQZ_B;
9141 case LoongArch::PseudoVBZ_H:
9142 CondOpc = LoongArch::VSETANYEQZ_H;
9144 case LoongArch::PseudoVBZ_W:
9145 CondOpc = LoongArch::VSETANYEQZ_W;
9147 case LoongArch::PseudoVBZ_D:
9148 CondOpc = LoongArch::VSETANYEQZ_D;
9150 case LoongArch::PseudoVBNZ:
9151 CondOpc = LoongArch::VSETNEZ_V;
9153 case LoongArch::PseudoVBNZ_B:
9154 CondOpc = LoongArch::VSETALLNEZ_B;
9156 case LoongArch::PseudoVBNZ_H:
9157 CondOpc = LoongArch::VSETALLNEZ_H;
9159 case LoongArch::PseudoVBNZ_W:
9160 CondOpc = LoongArch::VSETALLNEZ_W;
9162 case LoongArch::PseudoVBNZ_D:
9163 CondOpc = LoongArch::VSETALLNEZ_D;
9165 case LoongArch::PseudoXVBZ:
9166 CondOpc = LoongArch::XVSETEQZ_V;
9168 case LoongArch::PseudoXVBZ_B:
9169 CondOpc = LoongArch::XVSETANYEQZ_B;
9171 case LoongArch::PseudoXVBZ_H:
9172 CondOpc = LoongArch::XVSETANYEQZ_H;
9174 case LoongArch::PseudoXVBZ_W:
9175 CondOpc = LoongArch::XVSETANYEQZ_W;
9177 case LoongArch::PseudoXVBZ_D:
9178 CondOpc = LoongArch::XVSETANYEQZ_D;
9180 case LoongArch::PseudoXVBNZ:
9181 CondOpc = LoongArch::XVSETNEZ_V;
9183 case LoongArch::PseudoXVBNZ_B:
9184 CondOpc = LoongArch::XVSETALLNEZ_B;
9186 case LoongArch::PseudoXVBNZ_H:
9187 CondOpc = LoongArch::XVSETALLNEZ_H;
9189 case LoongArch::PseudoXVBNZ_W:
9190 CondOpc = LoongArch::XVSETALLNEZ_W;
9192 case LoongArch::PseudoXVBNZ_D:
9193 CondOpc = LoongArch::XVSETALLNEZ_D;
9208 F->insert(It, FalseBB);
9209 F->insert(It, TrueBB);
9210 F->insert(It, SinkBB);
9213 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
9217 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
9226 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9234 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9242 MI.getOperand(0).getReg())
9249 MI.eraseFromParent();
9257 unsigned BroadcastOp;
9259 switch (
MI.getOpcode()) {
9262 case LoongArch::PseudoXVINSGR2VR_B:
9264 BroadcastOp = LoongArch::XVREPLGR2VR_B;
9265 InsOp = LoongArch::XVEXTRINS_B;
9267 case LoongArch::PseudoXVINSGR2VR_H:
9269 BroadcastOp = LoongArch::XVREPLGR2VR_H;
9270 InsOp = LoongArch::XVEXTRINS_H;
9282 unsigned Idx =
MI.getOperand(3).getImm();
9284 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
9286 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
9287 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
9290 .
addReg(XSrc, {}, LoongArch::sub_128);
9292 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
9293 : LoongArch::VINSGR2VR_B),
9301 .
addImm(LoongArch::sub_128);
9303 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9304 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9308 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
9311 .
addImm(Idx >= HalfSize ? 48 : 18);
9316 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
9319 MI.eraseFromParent();
9326 assert(Subtarget.hasExtLSX());
9334 unsigned BroadcastOp, CTOp, PickOp;
9335 switch (
MI.getOpcode()) {
9338 case LoongArch::PseudoCTPOP_B:
9339 BroadcastOp = LoongArch::VREPLGR2VR_B;
9340 CTOp = LoongArch::VPCNT_B;
9341 PickOp = LoongArch::VPICKVE2GR_B;
9343 case LoongArch::PseudoCTPOP_H:
9344 case LoongArch::PseudoCTPOP_H_LA32:
9345 BroadcastOp = LoongArch::VREPLGR2VR_H;
9346 CTOp = LoongArch::VPCNT_H;
9347 PickOp = LoongArch::VPICKVE2GR_H;
9349 case LoongArch::PseudoCTPOP_W:
9350 case LoongArch::PseudoCTPOP_W_LA32:
9351 BroadcastOp = LoongArch::VREPLGR2VR_W;
9352 CTOp = LoongArch::VPCNT_W;
9353 PickOp = LoongArch::VPICKVE2GR_W;
9355 case LoongArch::PseudoCTPOP_D:
9356 BroadcastOp = LoongArch::VREPLGR2VR_D;
9357 CTOp = LoongArch::VPCNT_D;
9358 PickOp = LoongArch::VPICKVE2GR_D;
9362 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
9363 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
9368 MI.eraseFromParent();
9382 unsigned EleBits = 8;
9383 unsigned NotOpc = 0;
9386 switch (
MI.getOpcode()) {
9389 case LoongArch::PseudoVMSKLTZ_B:
9390 MskOpc = LoongArch::VMSKLTZ_B;
9392 case LoongArch::PseudoVMSKLTZ_H:
9393 MskOpc = LoongArch::VMSKLTZ_H;
9396 case LoongArch::PseudoVMSKLTZ_W:
9397 MskOpc = LoongArch::VMSKLTZ_W;
9400 case LoongArch::PseudoVMSKLTZ_D:
9401 MskOpc = LoongArch::VMSKLTZ_D;
9404 case LoongArch::PseudoVMSKGEZ_B:
9405 MskOpc = LoongArch::VMSKGEZ_B;
9407 case LoongArch::PseudoVMSKEQZ_B:
9408 MskOpc = LoongArch::VMSKNZ_B;
9409 NotOpc = LoongArch::VNOR_V;
9411 case LoongArch::PseudoVMSKNEZ_B:
9412 MskOpc = LoongArch::VMSKNZ_B;
9414 case LoongArch::PseudoXVMSKLTZ_B:
9415 MskOpc = LoongArch::XVMSKLTZ_B;
9416 RC = &LoongArch::LASX256RegClass;
9418 case LoongArch::PseudoXVMSKLTZ_H:
9419 MskOpc = LoongArch::XVMSKLTZ_H;
9420 RC = &LoongArch::LASX256RegClass;
9423 case LoongArch::PseudoXVMSKLTZ_W:
9424 MskOpc = LoongArch::XVMSKLTZ_W;
9425 RC = &LoongArch::LASX256RegClass;
9428 case LoongArch::PseudoXVMSKLTZ_D:
9429 MskOpc = LoongArch::XVMSKLTZ_D;
9430 RC = &LoongArch::LASX256RegClass;
9433 case LoongArch::PseudoXVMSKGEZ_B:
9434 MskOpc = LoongArch::XVMSKGEZ_B;
9435 RC = &LoongArch::LASX256RegClass;
9437 case LoongArch::PseudoXVMSKEQZ_B:
9438 MskOpc = LoongArch::XVMSKNZ_B;
9439 NotOpc = LoongArch::XVNOR_V;
9440 RC = &LoongArch::LASX256RegClass;
9442 case LoongArch::PseudoXVMSKNEZ_B:
9443 MskOpc = LoongArch::XVMSKNZ_B;
9444 RC = &LoongArch::LASX256RegClass;
9459 if (
TRI->getRegSizeInBits(*RC) > 128) {
9460 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9461 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
9469 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
9470 : LoongArch::BSTRINS_W),
9474 .
addImm(256 / EleBits - 1)
9482 MI.eraseFromParent();
9489 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9490 "Unexpected instruction");
9502 MI.eraseFromParent();
9509 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9510 "Unexpected instruction");
9516 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
9526 MI.eraseFromParent();
9531 switch (
MI.getOpcode()) {
9534 case LoongArch::Select_GPR_Using_CC_GPR:
9570 if (
MI.getOperand(2).isReg())
9571 RHS =
MI.getOperand(2).getReg();
9572 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9576 SelectDests.
insert(
MI.getOperand(0).getReg());
9580 SequenceMBBI !=
E; ++SequenceMBBI) {
9581 if (SequenceMBBI->isDebugInstr())
9584 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9585 !SequenceMBBI->getOperand(2).isReg() ||
9586 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9587 SequenceMBBI->getOperand(3).getImm() !=
CC ||
9588 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9589 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9591 LastSelectPseudo = &*SequenceMBBI;
9593 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9596 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9597 SequenceMBBI->mayLoadOrStore() ||
9598 SequenceMBBI->usesCustomInsertionHook())
9601 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9616 F->insert(
I, IfFalseMBB);
9617 F->insert(
I, TailMBB);
9620 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9626 TailMBB->
push_back(DebugInstr->removeFromParent());
9630 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9640 if (
MI.getOperand(2).isImm())
9652 auto SelectMBBI =
MI.getIterator();
9653 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9655 while (SelectMBBI != SelectEnd) {
9656 auto Next = std::next(SelectMBBI);
9660 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9661 .
addReg(SelectMBBI->getOperand(4).getReg())
9663 .
addReg(SelectMBBI->getOperand(5).getReg())
9670 F->getProperties().resetNoPHIs();
9676 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9679 switch (
MI.getOpcode()) {
9682 case LoongArch::DIV_W:
9683 case LoongArch::DIV_WU:
9684 case LoongArch::MOD_W:
9685 case LoongArch::MOD_WU:
9686 case LoongArch::DIV_D:
9687 case LoongArch::DIV_DU:
9688 case LoongArch::MOD_D:
9689 case LoongArch::MOD_DU:
9692 case LoongArch::WRFCSR: {
9694 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9695 .
addReg(
MI.getOperand(1).getReg());
9696 MI.eraseFromParent();
9699 case LoongArch::RDFCSR: {
9700 MachineInstr *ReadFCSR =
9702 MI.getOperand(0).getReg())
9703 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9705 MI.eraseFromParent();
9708 case LoongArch::Select_GPR_Using_CC_GPR:
9710 case LoongArch::BuildPairF64Pseudo:
9712 case LoongArch::SplitPairF64Pseudo:
9714 case LoongArch::PseudoVBZ:
9715 case LoongArch::PseudoVBZ_B:
9716 case LoongArch::PseudoVBZ_H:
9717 case LoongArch::PseudoVBZ_W:
9718 case LoongArch::PseudoVBZ_D:
9719 case LoongArch::PseudoVBNZ:
9720 case LoongArch::PseudoVBNZ_B:
9721 case LoongArch::PseudoVBNZ_H:
9722 case LoongArch::PseudoVBNZ_W:
9723 case LoongArch::PseudoVBNZ_D:
9724 case LoongArch::PseudoXVBZ:
9725 case LoongArch::PseudoXVBZ_B:
9726 case LoongArch::PseudoXVBZ_H:
9727 case LoongArch::PseudoXVBZ_W:
9728 case LoongArch::PseudoXVBZ_D:
9729 case LoongArch::PseudoXVBNZ:
9730 case LoongArch::PseudoXVBNZ_B:
9731 case LoongArch::PseudoXVBNZ_H:
9732 case LoongArch::PseudoXVBNZ_W:
9733 case LoongArch::PseudoXVBNZ_D:
9735 case LoongArch::PseudoXVINSGR2VR_B:
9736 case LoongArch::PseudoXVINSGR2VR_H:
9738 case LoongArch::PseudoCTPOP_B:
9739 case LoongArch::PseudoCTPOP_H:
9740 case LoongArch::PseudoCTPOP_W:
9741 case LoongArch::PseudoCTPOP_D:
9742 case LoongArch::PseudoCTPOP_H_LA32:
9743 case LoongArch::PseudoCTPOP_W_LA32:
9745 case LoongArch::PseudoVMSKLTZ_B:
9746 case LoongArch::PseudoVMSKLTZ_H:
9747 case LoongArch::PseudoVMSKLTZ_W:
9748 case LoongArch::PseudoVMSKLTZ_D:
9749 case LoongArch::PseudoVMSKGEZ_B:
9750 case LoongArch::PseudoVMSKEQZ_B:
9751 case LoongArch::PseudoVMSKNEZ_B:
9752 case LoongArch::PseudoXVMSKLTZ_B:
9753 case LoongArch::PseudoXVMSKLTZ_H:
9754 case LoongArch::PseudoXVMSKLTZ_W:
9755 case LoongArch::PseudoXVMSKLTZ_D:
9756 case LoongArch::PseudoXVMSKGEZ_B:
9757 case LoongArch::PseudoXVMSKEQZ_B:
9758 case LoongArch::PseudoXVMSKNEZ_B:
9760 case TargetOpcode::STATEPOINT:
9766 MI.addOperand(*
MI.getMF(),
9768 LoongArch::R1,
true,
9771 if (!Subtarget.is64Bit())
9774 case LoongArch::PROBED_STACKALLOC_DYN:
9781 unsigned *
Fast)
const {
9782 if (!Subtarget.hasUAL())
9800 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9801 LoongArch::R10, LoongArch::R11};
9816 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9817 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9818 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9819 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9820 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9821 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9827 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9828 LoongArch::F6, LoongArch::F7};
9831 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9832 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9835 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9836 LoongArch::VR6, LoongArch::VR7};
9839 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9840 LoongArch::XR6, LoongArch::XR7};
9843 switch (State.getCallingConv()) {
9845 if (!State.isVarArg())
9849 return State.AllocateReg(
ArgGPRs);
9857 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9859 unsigned GRLenInBytes = GRLen / 8;
9870 State.AllocateStack(GRLenInBytes, StackAlign),
9873 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9884 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9892 unsigned ValNo,
MVT ValVT,
9895 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9896 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9897 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9902 if (IsRet && ValNo > 1)
9906 bool UseGPRForFloat =
true;
9916 UseGPRForFloat = ArgFlags.
isVarArg();
9929 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9932 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9933 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9935 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9941 State.getPendingArgFlags();
9944 "PendingLocs and PendingArgFlags out of sync");
9948 UseGPRForFloat =
true;
9950 if (UseGPRForFloat && ValVT == MVT::f32) {
9953 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9956 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9959 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
10001 PendingLocs.
size() <= 2) {
10002 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
10007 PendingLocs.
clear();
10008 PendingArgFlags.
clear();
10015 unsigned StoreSizeBytes = GRLen / 8;
10018 if (ValVT == MVT::f32 && !UseGPRForFloat) {
10020 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
10024 UseGPRForFloat =
false;
10025 StoreSizeBytes = 16;
10026 StackAlign =
Align(16);
10029 UseGPRForFloat =
false;
10030 StoreSizeBytes = 32;
10031 StackAlign =
Align(32);
10037 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
10041 if (!PendingLocs.
empty()) {
10043 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
10044 for (
auto &It : PendingLocs) {
10046 It.convertToReg(
Reg);
10051 PendingLocs.clear();
10052 PendingArgFlags.
clear();
10055 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
10056 "Expected an GRLenVT at this stage");
10073void LoongArchTargetLowering::analyzeInputArgs(
10076 LoongArchCCAssignFn Fn)
const {
10078 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
10079 MVT ArgVT = Ins[i].VT;
10080 Type *ArgTy =
nullptr;
10082 ArgTy = FType->getReturnType();
10083 else if (Ins[i].isOrigArg())
10084 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
10088 CCInfo, IsRet, ArgTy)) {
10089 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
10096void LoongArchTargetLowering::analyzeOutputArgs(
10099 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
10100 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10101 MVT ArgVT = Outs[i].VT;
10102 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
10106 CCInfo, IsRet, OrigTy)) {
10107 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
10126 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
10148 if (In.isOrigArg()) {
10153 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
10154 (
BitWidth < 32 && In.Flags.isZExt())) {
10204 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10217 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10221 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
10235 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
10247 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
10251 LoongArch::R23, LoongArch::R24, LoongArch::R25,
10252 LoongArch::R26, LoongArch::R27, LoongArch::R28,
10253 LoongArch::R29, LoongArch::R30, LoongArch::R31};
10260 if (LocVT == MVT::f32) {
10263 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
10264 LoongArch::F26, LoongArch::F27};
10271 if (LocVT == MVT::f64) {
10274 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
10275 LoongArch::F30_64, LoongArch::F31_64};
10294 switch (CallConv) {
10306 "GHC calling convention requires the F and D extensions");
10311 MVT GRLenVT = Subtarget.getGRLenVT();
10312 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
10321 return CI->isMustTailCall();
10326 std::vector<SDValue> OutChains;
10335 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
10337 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10354 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10363 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10364 assert(ArgPartOffset == 0);
10365 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10367 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10391 int VaArgOffset, VarArgsSaveSize;
10395 if (ArgRegs.
size() == Idx) {
10397 VarArgsSaveSize = 0;
10399 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10400 VaArgOffset = -VarArgsSaveSize;
10406 LoongArchFI->setVarArgsFrameIndex(FI);
10414 VarArgsSaveSize += GRLenInBytes;
10419 for (
unsigned I = Idx;
I < ArgRegs.
size();
10420 ++
I, VaArgOffset += GRLenInBytes) {
10421 const Register Reg = RegInfo.createVirtualRegister(RC);
10422 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10430 ->setValue((
Value *)
nullptr);
10431 OutChains.push_back(
Store);
10433 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10438 if (!OutChains.empty()) {
10439 OutChains.push_back(Chain);
10454 if (
N->getNumValues() != 1)
10456 if (!
N->hasNUsesOfValue(1, 0))
10459 SDNode *Copy = *
N->user_begin();
10465 if (Copy->getGluedNode())
10469 bool HasRet =
false;
10471 if (
Node->getOpcode() != LoongArchISD::RET)
10479 Chain = Copy->getOperand(0);
10484bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10488 auto CalleeCC = CLI.CallConv;
10489 auto &Outs = CLI.Outs;
10491 auto CallerCC = Caller.getCallingConv();
10493 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10502 for (
auto &Arg : Outs)
10503 if (Arg.Flags.isByVal())
10519 for (
auto &VA : ArgLocs)
10525 auto IsCallerStructRet = Caller.hasStructRetAttr();
10526 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10527 if (IsCallerStructRet || IsCalleeStructRet)
10532 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10533 if (CalleeCC != CallerCC) {
10534 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10535 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10561 MVT GRLenVT = Subtarget.getGRLenVT();
10573 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10577 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10583 "site marked musttail");
10590 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10592 if (!Flags.isByVal())
10596 unsigned Size = Flags.getByValSize();
10597 Align Alignment = Flags.getNonZeroByValAlign();
10604 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10606 false,
nullptr, std::nullopt,
10618 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10621 SDValue ArgValue = OutVals[OutIdx];
10629 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10630 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10642 if (!StackPtr.getNode())
10654 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10668 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10688 const Argument *FormalArg =
nullptr;
10689 unsigned FilteredIdx = 0;
10690 for (
const auto &CallArg : CLI.
CB->
args()) {
10691 if (CallArg->getType()->isEmptyTy())
10693 if (FilteredIdx == CallArgIdx) {
10702 unsigned FormalArgIdx = CallArgIdx;
10704 FormalArgIdx = FormalArg->
getArgNo();
10708 if (Arg.getType()->isEmptyTy())
10710 if (FilteredIdx == CallArgIdx) {
10711 FormalArgIdx = Arg.getArgNo();
10724 SDValue IncomingPtr = CopyOp;
10741 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10742 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10743 SDValue PartValue = OutVals[OutIdx + 1];
10744 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10755 ArgValue = IncomingPtr;
10759 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10771 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10772 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10773 assert(ArgPartOffset == 0);
10778 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10779 SDValue PartValue = OutVals[OutIdx + 1];
10780 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10792 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10794 for (
const auto &Part : Parts) {
10795 SDValue PartValue = Part.first;
10796 SDValue PartOffset = Part.second;
10803 ArgValue = SpillSlot;
10810 if (Flags.isByVal())
10811 ArgValue = ByValArgs[j++];
10819 "Tail call not allowed if stack is used for passing parameters");
10822 if (!StackPtr.getNode())
10835 if (!MemOpChains.
empty())
10841 for (
auto &Reg : RegsToPass) {
10842 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10864 Ops.push_back(Chain);
10865 Ops.push_back(Callee);
10869 for (
auto &Reg : RegsToPass)
10870 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10875 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10876 assert(Mask &&
"Missing call preserved mask for calling convention");
10882 Ops.push_back(Glue);
10891 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10894 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10897 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10898 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10920 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10923 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10924 auto &VA = RVLocs[i];
10932 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10933 assert(VA.needsCustom());
10938 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10939 RetValue, RetValue2);
10952 const Type *RetTy)
const {
10954 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10956 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10960 Outs[i].Flags, CCInfo,
true,
nullptr))
10986 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10987 SDValue Val = OutVals[OutIdx];
10996 DAG.
getVTList(MVT::i32, MVT::i32), Val);
11000 Register RegHi = RVLocs[++i].getLocReg();
11025 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
11033 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
11034 uint64_t RequiredImm = 0;
11036 if (SplatBitSize == 16 && !(V & 0x00FF)) {
11038 RequiredImm = (0b10101 << 8) | (V >> 8);
11039 return {
true, RequiredImm};
11040 }
else if (SplatBitSize == 32) {
11042 if (!(V & 0xFFFF00FF)) {
11043 RequiredImm = (0b10001 << 8) | (V >> 8);
11044 return {
true, RequiredImm};
11047 if (!(V & 0xFF00FFFF)) {
11048 RequiredImm = (0b10010 << 8) | (V >> 16);
11049 return {
true, RequiredImm};
11052 if (!(V & 0x00FFFFFF)) {
11053 RequiredImm = (0b10011 << 8) | (V >> 24);
11054 return {
true, RequiredImm};
11057 if ((V & 0xFFFF00FF) == 0xFF) {
11058 RequiredImm = (0b10110 << 8) | (V >> 8);
11059 return {
true, RequiredImm};
11062 if ((V & 0xFF00FFFF) == 0xFFFF) {
11063 RequiredImm = (0b10111 << 8) | (V >> 16);
11064 return {
true, RequiredImm};
11067 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
11069 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11070 return {
true, RequiredImm};
11072 }
else if (SplatBitSize == 64) {
11074 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
11075 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
11077 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11078 return {
true, RequiredImm};
11081 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
11082 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
11084 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
11085 return {
true, RequiredImm};
11088 auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {
11090 for (
int i = 0; i < 8; ++i) {
11092 if (
byte == 0 ||
byte == 0xFF)
11093 res |= ((
byte & 1) << i);
11098 return {
true, res};
11100 auto [IsSame, Suffix] = sameBitsPreByte(V);
11102 RequiredImm = (0b11001 << 8) | Suffix;
11103 return {
true, RequiredImm};
11106 return {
false, RequiredImm};
11111 if (!Subtarget.hasExtLSX())
11114 if (VT == MVT::f32) {
11115 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
11116 return (masked == 0x3e000000 || masked == 0x40000000);
11119 if (VT == MVT::f64) {
11120 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
11121 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
11130bool LoongArchTargetLowering::shouldConvertFpToSat(
unsigned Op,
EVT FPVT,
11136 if (FPVT == MVT::f32)
11138 return FPVT == MVT::f64 && Subtarget.hasBasicD();
11142LoongArchTargetLowering::getFPImmAction(
const APFloat &
Imm,
EVT VT,
11143 bool ForCodeSize)
const {
11145 if (VT == MVT::f32 && !Subtarget.hasBasicF())
11147 if (VT == MVT::f64 && !Subtarget.hasBasicD())
11165 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
11177bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
11187 Type *Ty =
I->getOperand(0)->getType();
11189 unsigned Size = Ty->getIntegerBitWidth();
11209 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
11214 if (Subtarget.hasExtLASX())
11216 else if (Subtarget.hasExtLSX())
11223 EVT VT =
Y.getValueType();
11226 return Subtarget.hasExtLSX() && VT.
isInteger();
11237 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
11238 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
11239 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
11240 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
11243 Info.memVT = MVT::i32;
11244 Info.ptrVal =
I.getArgOperand(0);
11246 Info.align =
Align(4);
11265 "Unable to expand");
11266 unsigned MinWordSize = 4;
11278 Value *AlignedAddr = Builder.CreateIntrinsic(
11279 Intrinsic::ptrmask, {PtrTy, IntTy},
11280 {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))},
nullptr,
11283 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
11284 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
11285 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
11286 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
11287 Value *Mask = Builder.CreateShl(
11288 ConstantInt::get(WordType,
11289 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
11291 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
11292 Value *ValOperand_Shifted =
11293 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
11294 ShiftAmt,
"ValOperand_Shifted");
11297 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
11299 NewOperand = ValOperand_Shifted;
11302 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
11305 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
11306 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
11307 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
11326 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
11334 if (Subtarget.hasLAMCAS()) {
11356 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
11358 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
11360 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
11362 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
11364 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
11366 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
11368 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
11370 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11380 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11382 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11384 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11386 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11388 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11390 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11392 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11394 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11406 if (Subtarget.hasLAMCAS())
11418 unsigned GRLen = Subtarget.getGRLen();
11420 Value *FailureOrdering =
11421 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t
>(FailOrd));
11422 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11424 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11425 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11426 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11427 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11430 Value *Result = Builder.CreateIntrinsic(
11431 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11433 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11449 Builder.CreateNot(Mask,
"Inv_Mask"),
11456 unsigned GRLen = Subtarget.getGRLen();
11458 Builder.getIntN(GRLen,
static_cast<uint64_t
>(AI->
getOrdering()));
11465 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11466 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11467 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11480 unsigned ValWidth =
11483 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11484 Result = Builder.CreateCall(LlwOpScwLoop,
11485 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11488 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11492 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11516 return LoongArch::R4;
11521 return LoongArch::R5;
11532 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11533 return RefinementSteps;
11538 assert(Subtarget.hasFrecipe() &&
11539 "Reciprocal estimate queried on unsupported target");
11550 return Subtarget.hasBasicD();
11554 return Subtarget.hasExtLSX();
11558 return Subtarget.hasExtLASX();
11567 int &RefinementSteps,
11568 bool &UseOneConstNR,
11569 bool Reciprocal)
const {
11571 "Enabled should never be Disabled here");
11573 if (!Subtarget.hasFrecipe())
11588 UseOneConstNR =
false;
11594 if (Reciprocal || RefinementSteps > 0)
11604 int &RefinementSteps)
const {
11606 "Enabled should never be Disabled here");
11608 if (!Subtarget.hasFrecipe())
11622 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11630LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11650 if (Constraint.
size() == 1) {
11651 switch (Constraint[0]) {
11667 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11676 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11683std::pair<unsigned, const TargetRegisterClass *>
11684LoongArchTargetLowering::getRegForInlineAsmConstraint(
11688 if (Constraint.
size() == 1) {
11689 switch (Constraint[0]) {
11694 return std::make_pair(0U, &LoongArch::GPRRegClass);
11696 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11698 if (Subtarget.hasBasicF() && VT == MVT::f32)
11699 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11700 if (Subtarget.hasBasicD() && VT == MVT::f64)
11701 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11702 if (Subtarget.hasExtLSX() &&
11703 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11704 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11705 if (Subtarget.hasExtLSX() && VT == MVT::i128)
11706 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11707 if (Subtarget.hasExtLASX() &&
11708 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11709 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11729 bool IsFP = Constraint[2] ==
'f';
11730 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11731 std::pair<unsigned, const TargetRegisterClass *>
R;
11736 unsigned RegNo =
R.first;
11737 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11738 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11739 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11740 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11750void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11754 if (Constraint.
size() == 1) {
11755 switch (Constraint[0]) {
11762 Subtarget.getGRLenVT()));
11771 Subtarget.getGRLenVT()));
11777 if (
C->getZExtValue() == 0)
11797#define GET_REGISTER_MATCHER
11798#include "LoongArchGenAsmMatcher.inc"
11804 std::string NewRegName = Name.second.str();
11810 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11811 if (!ReservedRegs.
test(Reg))
11828 const APInt &
Imm = ConstNode->getAPIntValue();
11830 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2() ||
11831 (1 -
Imm).isPowerOf2() || (-1 -
Imm).isPowerOf2())
11834 if (ConstNode->hasOneUse() &&
11835 ((
Imm - 2).isPowerOf2() || (
Imm - 4).isPowerOf2() ||
11836 (
Imm - 8).isPowerOf2() || (
Imm - 16).isPowerOf2()))
11842 if (ConstNode->hasOneUse() && !(
Imm.sge(-2048) &&
Imm.sle(4095))) {
11843 unsigned Shifts =
Imm.countr_zero();
11850 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11854 APInt ImmSmall =
APInt(
Imm.getBitWidth(), 1ULL << Shifts,
true);
11855 if ((
Imm - ImmSmall).isPowerOf2() || (
Imm + ImmSmall).isPowerOf2() ||
11856 (ImmSmall -
Imm).isPowerOf2())
11866 Type *Ty,
unsigned AS,
11885 switch (AM.
Scale) {
11921 EVT MemVT = LD->getMemoryVT();
11922 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11933 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11942 if (
Y.getValueType().isVector())
11954 Type *Ty,
bool IsSigned)
const {
11955 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11964 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11965 Type.getSizeInBits() < Subtarget.getGRLen()))
11975 Align &PrefAlign)
const {
11979 if (Subtarget.is64Bit()) {
11981 PrefAlign =
Align(8);
11984 PrefAlign =
Align(4);
11999bool LoongArchTargetLowering::splitValueIntoRegisterParts(
12001 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
12002 bool IsABIRegCopy =
CC.has_value();
12005 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
12006 PartVT == MVT::f32) {
12021SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
12023 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
12024 bool IsABIRegCopy =
CC.has_value();
12026 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
12027 PartVT == MVT::f32) {
12028 SDValue Val = Parts[0];
12044 if (VT == MVT::f16 && Subtarget.hasBasicF())
12050unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
12053 if (VT == MVT::f16 && Subtarget.hasBasicF())
12062 unsigned Opc =
Op.getOpcode();
12067 case LoongArchISD::VANYNONZERO:
12068 case LoongArchISD::VALLZERO: {
12070 Known.Zero.setBitsFrom(1);
12073 case LoongArchISD::VALL_ZERO:
12074 case LoongArchISD::VANY_ZERO:
12075 case LoongArchISD::VALL_NONZERO:
12076 case LoongArchISD::VANY_NONZERO: {
12079 Known.Zero.setBitsFrom(1);
12082 case LoongArchISD::VPICK_ZEXT_ELT: {
12086 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
12087 Known.Zero.setBitsFrom(VTBits);
12090 case LoongArchISD::BSTRINS: {
12092 unsigned Msb =
Op.getConstantOperandVal(2);
12093 unsigned Lsb =
Op.getConstantOperandVal(3);
12096 Known.insertBits(Known2.
trunc(Msb - Lsb + 1), Lsb);
12099 case LoongArchISD::BSTRPICK: {
12102 unsigned Msb =
Op.getConstantOperandVal(1);
12103 unsigned Lsb =
Op.getConstantOperandVal(2);
12113 unsigned Depth)
const {
12114 switch (
Op.getOpcode()) {
12117 case LoongArchISD::BSTRINS: {
12118 unsigned BitWidth =
Op.getScalarValueSizeInBits();
12119 unsigned Msb =
Op.getConstantOperandVal(2);
12120 unsigned Lsb =
Op.getConstantOperandVal(3);
12124 return std::min(Tmp,
BitWidth - 1 - Msb);
12128 return Tmp > Lsb ? Tmp - Lsb : 1;
12137 unsigned Depth)
const {
12138 EVT VT =
Op.getValueType();
12140 unsigned Opc =
Op.getOpcode();
12144 case LoongArchISD::CRC_W_B_W:
12145 case LoongArchISD::CRC_W_H_W:
12146 case LoongArchISD::CRCC_W_B_W:
12147 case LoongArchISD::CRCC_W_H_W: {
12149 APInt DemandedSrcBits =
12151 Opc == LoongArchISD::CRCC_W_B_W)
12155 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
12157 case LoongArchISD::VMSKLTZ:
12158 case LoongArchISD::XVMSKLTZ: {
12160 MVT SrcVT = Src.getSimpleValueType();
12165 if (OriginalDemandedBits.
countr_zero() >= NumElts)
12169 APInt KnownUndef, KnownZero;
12185 if (KnownSrc.
One[SrcBits - 1])
12186 Known.One.setLowBits(NumElts);
12187 else if (KnownSrc.
Zero[SrcBits - 1])
12188 Known.Zero.setLowBits(NumElts);
12192 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
12199 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
12223 unsigned Index)
const {
12234 unsigned Index)
const {
12238 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
12253 Align StackAlign)
const {
12257 unsigned StackProbeSize =
12261 return StackProbeSize ? StackProbeSize : StackAlign.
value();
12265LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
12279 const EVT VT =
Op.getValueType();
12290 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
12300 const Register TargetReg =
MI.getOperand(0).getReg();
12303 const bool IsLA64 = Subtarget.is64Bit();
12304 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
12311 MF.
insert(MBBInsertPoint, LoopTestMBB);
12314 MF.
insert(MBBInsertPoint, ExitMBB);
12325 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
12331 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
12337 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
12352 MBB->addSuccessor(LoopTestMBB);
12354 MI.eraseFromParent();
12356 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 std::pair< SDValue, EVT > stripSignExtendInReg(SDValue V)
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 std::tuple< unsigned, SDValue, EVT > matchBinOpWithSharedOperand(SDValue BinV, SDValue X)
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 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 performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
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 lowerVECTOR_SHUFFLE_XVPERMIQ(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI_Q (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 foldVMskZeroTest(SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
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)
static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow)
#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_XVREPLVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVE0 (if possible).
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 MergeBlocksConvert(SDNode *N, SelectionDAG &DAG, unsigned Opcode, unsigned BlockBits)
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.
static SDValue convertRMEncoding(SelectionDAG &DAG, const SDLoc &DL, MVT GRLenVT, SDValue RMValue)
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
MachineBasicBlock * Folded
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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,...
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.
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.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
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 LoongArchTargetLowering * getTargetLowering() 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...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
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.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
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.
bool isFPImmCheapInGPR(const APFloat &Imm, EVT VT) const
Returns true if building Imm in a GPR and moving it to a float register is cheaper than loading it fr...
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.
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
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 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...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
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
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.
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...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
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 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, in exactly one operand.
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...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl, SDNodeFlags Flags={})
Constant fold a setcc to true or false.
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)
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 getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 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 MMOMetadata &Metadata=MMOMetadata())
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 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 getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
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)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
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 isZeroEltSplatMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses all elements with the same value as the first element of exa...
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.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
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.
FPImmAction
How the legalizer should materialize a floating-point immediate.
@ ConstantPool
Load the immediate from the constant pool.
@ Legal
The target can instruction select the immediate natively.
@ Bitcast
Build the immediate as a bitcast of an integer constant with the same bits.
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.
@ POISON
POISON - A poison node.
@ 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.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ 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 - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ 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 - Same semantics as the llvm.minnum/maxnum intrinsics.
@ 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 ...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ 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.
@ Known
Known to have no common set bits.
@ 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.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
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...
@ Fast
Assign the register banks as fast as possible (default).
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
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
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).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
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
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
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)