30#include "llvm/IR/IntrinsicsLoongArch.h"
40#define DEBUG_TYPE "loongarch-isel-lowering"
45 cl::desc(
"Trap on integer division by zero."),
57 if (Subtarget.hasBasicF())
59 if (Subtarget.hasBasicD())
63 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
65 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
67 if (Subtarget.hasExtLSX())
71 if (Subtarget.hasExtLASX())
72 for (
MVT VT : LASXVTs)
174 if (Subtarget.hasBasicD())
186 if (Subtarget.hasBasicF()) {
220 if (!Subtarget.hasBasicD()) {
231 if (Subtarget.hasBasicD()) {
269 if (Subtarget.hasExtLSX()) {
284 for (
MVT VT : LSXVTs) {
298 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
315 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
317 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
319 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
323 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
341 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
342 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
357 if (Subtarget.hasExtLASX()) {
358 for (
MVT VT : LASXVTs) {
373 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
391 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
393 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
395 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
399 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
421 if (Subtarget.hasExtLSX()) {
446 if (Subtarget.hasLAMCAS())
449 if (Subtarget.hasSCQ()) {
466 switch (
Op.getOpcode()) {
468 return lowerATOMIC_FENCE(
Op, DAG);
470 return lowerEH_DWARF_CFA(
Op, DAG);
472 return lowerGlobalAddress(
Op, DAG);
474 return lowerGlobalTLSAddress(
Op, DAG);
476 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
478 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
480 return lowerINTRINSIC_VOID(
Op, DAG);
482 return lowerBlockAddress(
Op, DAG);
484 return lowerJumpTable(
Op, DAG);
486 return lowerShiftLeftParts(
Op, DAG);
488 return lowerShiftRightParts(
Op, DAG,
true);
490 return lowerShiftRightParts(
Op, DAG,
false);
492 return lowerConstantPool(
Op, DAG);
494 return lowerFP_TO_SINT(
Op, DAG);
496 return lowerBITCAST(
Op, DAG);
498 return lowerUINT_TO_FP(
Op, DAG);
500 return lowerSINT_TO_FP(
Op, DAG);
502 return lowerVASTART(
Op, DAG);
504 return lowerFRAMEADDR(
Op, DAG);
506 return lowerRETURNADDR(
Op, DAG);
508 return lowerWRITE_REGISTER(
Op, DAG);
510 return lowerINSERT_VECTOR_ELT(
Op, DAG);
512 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
514 return lowerBUILD_VECTOR(
Op, DAG);
516 return lowerCONCAT_VECTORS(
Op, DAG);
518 return lowerVECTOR_SHUFFLE(
Op, DAG);
520 return lowerBITREVERSE(
Op, DAG);
522 return lowerSCALAR_TO_VECTOR(
Op, DAG);
524 return lowerPREFETCH(
Op, DAG);
526 return lowerSELECT(
Op, DAG);
528 return lowerBRCOND(
Op, DAG);
530 return lowerFP_TO_FP16(
Op, DAG);
532 return lowerFP16_TO_FP(
Op, DAG);
534 return lowerFP_TO_BF16(
Op, DAG);
536 return lowerBF16_TO_FP(
Op, DAG);
538 return lowerVECREDUCE_ADD(
Op, DAG);
546 return lowerVECREDUCE(
Op, DAG);
563 MVT OpVT =
Op.getSimpleValueType();
569 unsigned LegalVecSize = 128;
570 bool isLASX256Vector =
580 if (isLASX256Vector) {
585 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
591 if (isLASX256Vector) {
616 MVT OpVT =
Op.getSimpleValueType();
630 for (
int i = NumEles; i > 1; i /= 2) {
633 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
642 unsigned IsData =
Op.getConstantOperandVal(4);
647 return Op.getOperand(0);
662 if (
LHS == LHS2 &&
RHS == RHS2) {
667 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
683 MVT VT =
N->getSimpleValueType(0);
711 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
714 if (~TrueVal == FalseVal) {
754 unsigned SelOpNo = 0;
764 unsigned ConstSelOpNo = 1;
765 unsigned OtherSelOpNo = 2;
766 if (!isa<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
771 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
772 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
776 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
777 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
783 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
785 std::swap(NewConstOps[0], NewConstOps[1]);
797 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
799 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
802 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
803 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
817 isa<ConstantSDNode>(
LHS.getOperand(1))) {
823 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
836 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
837 int64_t
C = RHSC->getSExtValue();
880 MVT VT =
Op.getSimpleValueType();
886 if (
Op.hasOneUse()) {
887 unsigned UseOpc =
Op->user_begin()->getOpcode();
896 return lowerSELECT(NewSel, DAG);
911 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
932 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
936 if (TrueVal - 1 == FalseVal)
938 if (TrueVal + 1 == FalseVal)
945 RHS == TrueV && LHS == FalseV) {
962 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
989 Op.getOperand(0), LHS, RHS, TargetCC,
993 Op.getOperand(0), CondV,
Op.getOperand(2));
1003LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1006 MVT OpVT =
Op.getSimpleValueType();
1017 EVT ResTy =
Op->getValueType(0);
1028 for (
unsigned int i = 0; i < NewEltNum; i++) {
1031 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1050 for (
unsigned int i = 0; i < NewEltNum; i++)
1051 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1052 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1070 if (EltBits > 32 || EltBits == 1)
1098 int MaskOffset,
const APInt &Zeroable) {
1099 int Size = Mask.size();
1100 unsigned SizeInBits =
Size * ScalarSizeInBits;
1102 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1103 for (
int i = 0; i <
Size; i += Scale)
1104 for (
int j = 0; j < Shift; ++j)
1105 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1113 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1114 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1119 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1120 for (
int i = 0; i !=
Size; i += Scale) {
1121 unsigned Pos =
Left ? i + Shift : i;
1122 unsigned Low =
Left ? i : i + Shift;
1123 unsigned Len = Scale - Shift;
1128 int ShiftEltBits = ScalarSizeInBits * Scale;
1129 bool ByteShift = ShiftEltBits > 64;
1132 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1136 Scale = ByteShift ? Scale / 2 : Scale;
1142 return (
int)ShiftAmt;
1145 unsigned MaxWidth = 128;
1146 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1147 for (
int Shift = 1; Shift != Scale; ++Shift)
1148 for (
bool Left : {
true,
false})
1149 if (CheckZeros(Shift, Scale,
Left)) {
1150 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1175 const APInt &Zeroable) {
1176 int Size = Mask.size();
1190 Mask,
Size, Zeroable);
1198 "Illegal integer vector type");
1207template <
typename ValType>
1210 unsigned CheckStride,
1212 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1216 if (*
I != -1 && *
I != ExpectedIndex)
1218 ExpectedIndex += ExpectedIndexStride;
1222 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1234 int Size = Mask.size();
1244 int ScalarSizeInBits = VectorSizeInBits /
Size;
1245 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1246 (void)ScalarSizeInBits;
1248 for (
int i = 0; i <
Size; ++i) {
1254 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1271 RepeatedMask.
assign(LaneSize, -1);
1272 int Size = Mask.size();
1273 for (
int i = 0; i <
Size; ++i) {
1274 assert(Mask[i] == -1 || Mask[i] >= 0);
1277 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1284 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1285 if (RepeatedMask[i % LaneSize] < 0)
1287 RepeatedMask[i % LaneSize] = LocalM;
1288 else if (RepeatedMask[i % LaneSize] != LocalM)
1305 int NumElts = RepeatedMask.
size();
1307 int Scale = 16 / NumElts;
1309 for (
int i = 0; i < NumElts; ++i) {
1310 int M = RepeatedMask[i];
1311 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1312 "Unexpected mask index.");
1317 int StartIdx = i - (M % NumElts);
1324 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1327 Rotation = CandidateRotation;
1328 else if (Rotation != CandidateRotation)
1332 SDValue MaskV = M < NumElts ? V1 : V2;
1343 else if (TargetV != MaskV)
1348 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1349 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1358 return Rotation * Scale;
1377 if (ByteRotation <= 0)
1384 int LoByteShift = 16 - ByteRotation;
1385 int HiByteShift = ByteRotation;
1408 const APInt &Zeroable) {
1422 for (
int i = 0; i < NumElements; i++) {
1426 if (i % Scale != 0) {
1437 SDValue V = M < NumElements ? V1 : V2;
1438 M = M % NumElements;
1441 Offset = M - (i / Scale);
1444 if (
Offset % (NumElements / Scale))
1446 }
else if (InputV != V)
1449 if (M != (
Offset + (i / Scale)))
1460 if (
Offset >= (NumElements / 2)) {
1462 Offset -= (NumElements / 2);
1469 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1473 }
while (Scale > 1);
1479 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1480 NumExtElements *= 2) {
1500 int SplatIndex = -1;
1501 for (
const auto &M : Mask) {
1508 if (SplatIndex == -1)
1511 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1512 if (fitsRegularPattern<int>(Mask.begin(), 1, Mask.end(), SplatIndex, 0)) {
1513 APInt Imm(64, SplatIndex);
1544 unsigned SubVecSize = 4;
1545 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1548 int SubMask[4] = {-1, -1, -1, -1};
1549 for (
unsigned i = 0; i < SubVecSize; ++i) {
1550 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1556 M -= 4 * (j / SubVecSize);
1557 if (M < 0 || M >= 4)
1563 if (SubMask[i] == -1)
1567 else if (M != -1 && M != SubMask[i])
1574 for (
int i = SubVecSize - 1; i >= 0; --i) {
1587 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1614 const auto &Begin = Mask.begin();
1615 const auto &
End = Mask.end();
1616 SDValue OriV1 = V1, OriV2 = V2;
1618 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 2))
1620 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 2))
1625 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 2))
1627 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 2))
1654 const auto &Begin = Mask.begin();
1655 const auto &
End = Mask.end();
1656 SDValue OriV1 = V1, OriV2 = V2;
1658 if (fitsRegularPattern<int>(Begin, 2,
End, 1, 2))
1660 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + 1, 2))
1665 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 1, 2))
1667 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + 1, 2))
1695 const auto &Begin = Mask.begin();
1696 const auto &
End = Mask.end();
1697 unsigned HalfSize = Mask.size() / 2;
1698 SDValue OriV1 = V1, OriV2 = V2;
1700 if (fitsRegularPattern<int>(Begin, 2,
End, HalfSize, 1))
1702 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + HalfSize, 1))
1707 if (fitsRegularPattern<int>(Begin + 1, 2,
End, HalfSize, 1))
1709 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + HalfSize,
1738 const auto &Begin = Mask.begin();
1739 const auto &
End = Mask.end();
1740 SDValue OriV1 = V1, OriV2 = V2;
1742 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 1))
1744 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 1))
1749 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 1))
1751 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 1))
1778 const auto &Begin = Mask.begin();
1779 const auto &Mid = Mask.begin() + Mask.size() / 2;
1780 const auto &
End = Mask.end();
1781 SDValue OriV1 = V1, OriV2 = V2;
1783 if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
1785 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size(), 2))
1790 if (fitsRegularPattern<int>(Mid, 1,
End, 0, 2))
1792 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size(), 2))
1820 const auto &Begin = Mask.begin();
1821 const auto &Mid = Mask.begin() + Mask.size() / 2;
1822 const auto &
End = Mask.end();
1823 SDValue OriV1 = V1, OriV2 = V2;
1825 if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
1827 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size() + 1, 2))
1832 if (fitsRegularPattern<int>(Mid, 1,
End, 1, 2))
1834 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size() + 1, 2))
1877 "Vector type is unsupported for lsx!");
1879 "Two operands have different types!");
1881 "Unexpected mask size for shuffle!");
1882 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
1884 APInt KnownUndef, KnownZero;
1886 APInt Zeroable = KnownUndef | KnownZero;
1949 int SplatIndex = -1;
1950 for (
const auto &M : Mask) {
1957 if (SplatIndex == -1)
1960 const auto &Begin = Mask.begin();
1961 const auto &
End = Mask.end();
1962 unsigned HalfSize = Mask.size() / 2;
1964 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1965 if (fitsRegularPattern<int>(Begin, 1,
End - HalfSize, SplatIndex, 0) &&
1966 fitsRegularPattern<int>(Begin + HalfSize, 1,
End, SplatIndex + HalfSize,
1968 APInt Imm(64, SplatIndex);
1983 if (Mask.size() <= 4)
2007 const auto &Begin = Mask.begin();
2008 const auto &
End = Mask.end();
2009 unsigned HalfSize = Mask.size() / 2;
2010 unsigned LeftSize = HalfSize / 2;
2011 SDValue OriV1 = V1, OriV2 = V2;
2013 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, HalfSize - LeftSize,
2015 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize + LeftSize, 1))
2017 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize,
2018 Mask.size() + HalfSize - LeftSize, 1) &&
2019 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
2020 Mask.size() + HalfSize + LeftSize, 1))
2025 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, HalfSize - LeftSize,
2027 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize + LeftSize,
2030 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize,
2031 Mask.size() + HalfSize - LeftSize, 1) &&
2032 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
2033 Mask.size() + HalfSize + LeftSize, 1))
2046 const auto &Begin = Mask.begin();
2047 const auto &
End = Mask.end();
2048 unsigned HalfSize = Mask.size() / 2;
2049 SDValue OriV1 = V1, OriV2 = V2;
2051 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, 0, 1) &&
2052 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize, 1))
2054 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, Mask.size(), 1) &&
2055 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
2056 Mask.size() + HalfSize, 1))
2061 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, 0, 1) &&
2062 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize, 1))
2064 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, Mask.size(),
2066 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
2067 Mask.size() + HalfSize, 1))
2080 const auto &Begin = Mask.begin();
2081 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2082 const auto &Mid = Mask.begin() + Mask.size() / 2;
2083 const auto &RightMid = Mask.end() - Mask.size() / 4;
2084 const auto &
End = Mask.end();
2085 unsigned HalfSize = Mask.size() / 2;
2086 SDValue OriV1 = V1, OriV2 = V2;
2088 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 0, 2) &&
2089 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize, 2))
2091 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size(), 2) &&
2092 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize, 2))
2097 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 0, 2) &&
2098 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize, 2))
2100 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size(), 2) &&
2101 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize, 2))
2115 const auto &Begin = Mask.begin();
2116 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2117 const auto &Mid = Mask.begin() + Mask.size() / 2;
2118 const auto &RightMid = Mask.end() - Mask.size() / 4;
2119 const auto &
End = Mask.end();
2120 unsigned HalfSize = Mask.size() / 2;
2121 SDValue OriV1 = V1, OriV2 = V2;
2123 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 1, 2) &&
2124 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize + 1, 2))
2126 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size() + 1, 2) &&
2127 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize + 1,
2133 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 1, 2) &&
2134 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize + 1, 2))
2136 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size() + 1, 2) &&
2137 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize + 1,
2151 int MaskSize = Mask.size();
2152 int HalfSize = Mask.size() / 2;
2153 const auto &Begin = Mask.begin();
2154 const auto &Mid = Mask.begin() + HalfSize;
2155 const auto &
End = Mask.end();
2167 for (
auto it = Begin; it < Mid; it++) {
2170 else if ((*it >= 0 && *it < HalfSize) ||
2171 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2172 int M = *it < HalfSize ? *it : *it - HalfSize;
2177 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2179 for (
auto it = Mid; it <
End; it++) {
2182 else if ((*it >= HalfSize && *it < MaskSize) ||
2183 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2184 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2189 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2219 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2221 int MaskSize = Mask.size();
2222 int HalfSize = Mask.size() / 2;
2225 HalfMaskType preMask =
None, postMask =
None;
2227 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2228 return M < 0 || (M >= 0 && M < HalfSize) ||
2229 (M >= MaskSize && M < MaskSize + HalfSize);
2231 preMask = HighLaneTy;
2232 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2233 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2234 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2236 preMask = LowLaneTy;
2238 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2239 return M < 0 || (M >= 0 && M < HalfSize) ||
2240 (M >= MaskSize && M < MaskSize + HalfSize);
2242 postMask = HighLaneTy;
2243 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2244 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2245 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2247 postMask = LowLaneTy;
2255 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2258 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2271 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2272 *it = *it < 0 ? *it : *it - HalfSize;
2274 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2275 *it = *it < 0 ? *it : *it + HalfSize;
2277 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2290 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2291 *it = *it < 0 ? *it : *it - HalfSize;
2293 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2306 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2307 *it = *it < 0 ? *it : *it + HalfSize;
2330 int Size = Mask.size();
2331 int LaneSize =
Size / 2;
2333 bool LaneCrossing[2] = {
false,
false};
2334 for (
int i = 0; i <
Size; ++i)
2335 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2336 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2339 if (!LaneCrossing[0] && !LaneCrossing[1])
2343 InLaneMask.
assign(Mask.begin(), Mask.end());
2344 for (
int i = 0; i <
Size; ++i) {
2345 int &M = InLaneMask[i];
2348 if (((M %
Size) / LaneSize) != (i / LaneSize))
2349 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2354 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2369 "Vector type is unsupported for lasx!");
2371 "Two operands have different types!");
2373 "Unexpected mask size for shuffle!");
2374 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2375 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2381 APInt KnownUndef, KnownZero;
2383 APInt Zeroable = KnownUndef | KnownZero;
2418 Subtarget, Zeroable)))
2437 MVT VT =
Op.getSimpleValueType();
2441 bool V1IsUndef = V1.
isUndef();
2442 bool V2IsUndef = V2.
isUndef();
2443 if (V1IsUndef && V2IsUndef)
2456 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2458 for (
int &M : NewMask)
2459 if (M >= NumElements)
2465 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2466 (void)MaskUpperLimit;
2468 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2469 "Out of bounds shuffle index");
2486 MakeLibCallOptions CallOptions;
2491 std::tie(Res, Chain) =
2492 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2503 MakeLibCallOptions CallOptions;
2510 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2511 CallOptions,
DL, Chain);
2517 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2519 MakeLibCallOptions CallOptions;
2523 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2531 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2532 MVT VT =
Op.getSimpleValueType();
2558 "Unsupported vector type for broadcast.");
2561 bool IsIdeneity =
true;
2563 for (
int i = 0; i != NumOps; i++) {
2565 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2576 auto *LN = cast<LoadSDNode>(IdentitySrc);
2577 auto ExtType = LN->getExtensionType();
2583 ? DAG.
getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other)
2585 SDValue Ops[] = {LN->getChain(), LN->getBasePtr(), LN->getOffset()};
2596 EVT ResTy =
Op->getValueType(0);
2599 APInt SplatValue, SplatUndef;
2600 unsigned SplatBitSize;
2603 bool UseSameConstant =
true;
2608 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
2609 (!Subtarget.hasExtLASX() || !Is256Vec))
2615 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
2617 SplatBitSize <= 64) {
2619 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2623 if (SplatBitSize == 64 && !Subtarget.
is64Bit()) {
2628 if ((Is128Vec && ResTy == MVT::v4i32) ||
2629 (Is256Vec && ResTy == MVT::v8i32))
2635 switch (SplatBitSize) {
2639 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
2642 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
2645 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
2648 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
2656 if (ViaVecTy != ResTy)
2665 for (
unsigned i = 0; i < NumElts; ++i) {
2670 ConstantValue = Opi;
2671 else if (ConstantValue != Opi)
2672 UseSameConstant =
false;
2677 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
2679 for (
unsigned i = 0; i < NumElts; ++i) {
2699 for (
unsigned i = 1; i < NumElts; ++i) {
2715 MVT ResVT =
Op.getSimpleValueType();
2719 unsigned NumFreezeUndef = 0;
2720 unsigned NumZero = 0;
2721 unsigned NumNonZero = 0;
2722 unsigned NonZeros = 0;
2724 for (
unsigned i = 0; i != NumOperands; ++i) {
2739 assert(i <
sizeof(NonZeros) * CHAR_BIT);
2746 if (NumNonZero > 2) {
2750 Ops.
slice(0, NumOperands / 2));
2752 Ops.
slice(NumOperands / 2));
2765 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
2767 for (
unsigned i = 0; i != NumOperands; ++i) {
2768 if ((NonZeros & (1 << i)) == 0)
2779LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
2781 EVT VecTy =
Op->getOperand(0)->getValueType(0);
2785 if (isa<ConstantSDNode>(
Idx) &&
Idx->getAsZExtVal() < NumElts)
2792LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
2794 MVT VT =
Op.getSimpleValueType();
2803 if (isa<ConstantSDNode>(Op2))
2816 for (
unsigned i = 0; i < NumElts; ++i)
2847 if (Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
2849 "On LA64, only 64-bit registers can be written.");
2850 return Op.getOperand(0);
2853 if (!Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
2855 "On LA32, only 32-bit registers can be written.");
2856 return Op.getOperand(0);
2864 if (!isa<ConstantSDNode>(
Op.getOperand(0))) {
2866 "be a constant integer");
2873 EVT VT =
Op.getValueType();
2876 unsigned Depth =
Op.getConstantOperandVal(0);
2877 int GRLenInBytes = Subtarget.
getGRLen() / 8;
2880 int Offset = -(GRLenInBytes * 2);
2892 if (
Op.getConstantOperandVal(0) != 0) {
2894 "return address can only be determined for the current frame");
2928 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
2936 !Subtarget.hasBasicD() &&
"unexpected target features");
2941 auto *
C = dyn_cast<ConstantSDNode>(Op0.
getOperand(1));
2942 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
2952 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLT(MVT::i32))
2956 EVT RetVT =
Op.getValueType();
2958 MakeLibCallOptions CallOptions;
2959 CallOptions.setTypeListBeforeSoften(OpVT, RetVT);
2962 std::tie(Result, Chain) =
2970 !Subtarget.hasBasicD() &&
"unexpected target features");
2977 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLE(MVT::i32))
2981 EVT RetVT =
Op.getValueType();
2983 MakeLibCallOptions CallOptions;
2984 CallOptions.setTypeListBeforeSoften(OpVT, RetVT);
2987 std::tie(Result, Chain) =
2996 EVT VT =
Op.getValueType();
3000 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3001 Subtarget.
is64Bit() && Subtarget.hasBasicF()) {
3005 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit()) {
3022 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3023 !Subtarget.hasBasicD()) {
3047 N->getOffset(), Flags);
3055template <
class NodeTy>
3058 bool IsLocal)
const {
3069 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
3121 return getAddr(cast<BlockAddressSDNode>(
Op), DAG,
3127 return getAddr(cast<JumpTableSDNode>(
Op), DAG,
3133 return getAddr(cast<ConstantPoolSDNode>(
Op), DAG,
3140 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3144 if (GV->
isDSOLocal() && isa<GlobalVariable>(GV)) {
3145 if (
auto GCM = dyn_cast<GlobalVariable>(GV)->
getCodeModel())
3154 unsigned Opc,
bool UseGOT,
3172 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3210 Args.emplace_back(Load, CallTy);
3242LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3249 assert((!Large || Subtarget.
is64Bit()) &&
"Large code model requires LA64");
3252 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3265 return getDynamicTLSAddr(
N, DAG,
3266 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3267 : LoongArch::PseudoLA_TLS_GD,
3274 return getDynamicTLSAddr(
N, DAG,
3275 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3276 : LoongArch::PseudoLA_TLS_LD,
3281 return getStaticTLSAddr(
N, DAG,
3282 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3283 : LoongArch::PseudoLA_TLS_IE,
3290 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3294 return getTLSDescAddr(
N, DAG,
3295 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3296 : LoongArch::PseudoLA_TLS_DESC,
3300template <
unsigned N>
3303 auto *CImm = cast<ConstantSDNode>(
Op->getOperand(ImmOp));
3305 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
3306 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
3308 ": argument out of range.");
3315LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3317 switch (
Op.getConstantOperandVal(0)) {
3320 case Intrinsic::thread_pointer: {
3324 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3325 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3326 case Intrinsic::loongarch_lsx_vreplvei_d:
3327 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3328 return checkIntrinsicImmArg<1>(
Op, 2, DAG);
3329 case Intrinsic::loongarch_lsx_vreplvei_w:
3330 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3331 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3332 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3333 case Intrinsic::loongarch_lasx_xvpickve_d:
3334 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3335 return checkIntrinsicImmArg<2>(
Op, 2, DAG);
3336 case Intrinsic::loongarch_lasx_xvinsve0_d:
3337 return checkIntrinsicImmArg<2>(
Op, 3, DAG);
3338 case Intrinsic::loongarch_lsx_vsat_b:
3339 case Intrinsic::loongarch_lsx_vsat_bu:
3340 case Intrinsic::loongarch_lsx_vrotri_b:
3341 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3342 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3343 case Intrinsic::loongarch_lsx_vsrlri_b:
3344 case Intrinsic::loongarch_lsx_vsrari_b:
3345 case Intrinsic::loongarch_lsx_vreplvei_h:
3346 case Intrinsic::loongarch_lasx_xvsat_b:
3347 case Intrinsic::loongarch_lasx_xvsat_bu:
3348 case Intrinsic::loongarch_lasx_xvrotri_b:
3349 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3350 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3351 case Intrinsic::loongarch_lasx_xvsrlri_b:
3352 case Intrinsic::loongarch_lasx_xvsrari_b:
3353 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3354 case Intrinsic::loongarch_lasx_xvpickve_w:
3355 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3356 return checkIntrinsicImmArg<3>(
Op, 2, DAG);
3357 case Intrinsic::loongarch_lasx_xvinsve0_w:
3358 return checkIntrinsicImmArg<3>(
Op, 3, DAG);
3359 case Intrinsic::loongarch_lsx_vsat_h:
3360 case Intrinsic::loongarch_lsx_vsat_hu:
3361 case Intrinsic::loongarch_lsx_vrotri_h:
3362 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3363 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3364 case Intrinsic::loongarch_lsx_vsrlri_h:
3365 case Intrinsic::loongarch_lsx_vsrari_h:
3366 case Intrinsic::loongarch_lsx_vreplvei_b:
3367 case Intrinsic::loongarch_lasx_xvsat_h:
3368 case Intrinsic::loongarch_lasx_xvsat_hu:
3369 case Intrinsic::loongarch_lasx_xvrotri_h:
3370 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3371 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3372 case Intrinsic::loongarch_lasx_xvsrlri_h:
3373 case Intrinsic::loongarch_lasx_xvsrari_h:
3374 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3375 return checkIntrinsicImmArg<4>(
Op, 2, DAG);
3376 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3377 case Intrinsic::loongarch_lsx_vsrani_b_h:
3378 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3379 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3380 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3381 case Intrinsic::loongarch_lsx_vssrani_b_h:
3382 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3383 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3384 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3385 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3386 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3387 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3388 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3389 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3390 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3391 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3392 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3393 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3394 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3395 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3396 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3397 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3398 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3399 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3400 return checkIntrinsicImmArg<4>(
Op, 3, DAG);
3401 case Intrinsic::loongarch_lsx_vsat_w:
3402 case Intrinsic::loongarch_lsx_vsat_wu:
3403 case Intrinsic::loongarch_lsx_vrotri_w:
3404 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3405 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3406 case Intrinsic::loongarch_lsx_vsrlri_w:
3407 case Intrinsic::loongarch_lsx_vsrari_w:
3408 case Intrinsic::loongarch_lsx_vslei_bu:
3409 case Intrinsic::loongarch_lsx_vslei_hu:
3410 case Intrinsic::loongarch_lsx_vslei_wu:
3411 case Intrinsic::loongarch_lsx_vslei_du:
3412 case Intrinsic::loongarch_lsx_vslti_bu:
3413 case Intrinsic::loongarch_lsx_vslti_hu:
3414 case Intrinsic::loongarch_lsx_vslti_wu:
3415 case Intrinsic::loongarch_lsx_vslti_du:
3416 case Intrinsic::loongarch_lsx_vbsll_v:
3417 case Intrinsic::loongarch_lsx_vbsrl_v:
3418 case Intrinsic::loongarch_lasx_xvsat_w:
3419 case Intrinsic::loongarch_lasx_xvsat_wu:
3420 case Intrinsic::loongarch_lasx_xvrotri_w:
3421 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
3422 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
3423 case Intrinsic::loongarch_lasx_xvsrlri_w:
3424 case Intrinsic::loongarch_lasx_xvsrari_w:
3425 case Intrinsic::loongarch_lasx_xvslei_bu:
3426 case Intrinsic::loongarch_lasx_xvslei_hu:
3427 case Intrinsic::loongarch_lasx_xvslei_wu:
3428 case Intrinsic::loongarch_lasx_xvslei_du:
3429 case Intrinsic::loongarch_lasx_xvslti_bu:
3430 case Intrinsic::loongarch_lasx_xvslti_hu:
3431 case Intrinsic::loongarch_lasx_xvslti_wu:
3432 case Intrinsic::loongarch_lasx_xvslti_du:
3433 case Intrinsic::loongarch_lasx_xvbsll_v:
3434 case Intrinsic::loongarch_lasx_xvbsrl_v:
3435 return checkIntrinsicImmArg<5>(
Op, 2, DAG);
3436 case Intrinsic::loongarch_lsx_vseqi_b:
3437 case Intrinsic::loongarch_lsx_vseqi_h:
3438 case Intrinsic::loongarch_lsx_vseqi_w:
3439 case Intrinsic::loongarch_lsx_vseqi_d:
3440 case Intrinsic::loongarch_lsx_vslei_b:
3441 case Intrinsic::loongarch_lsx_vslei_h:
3442 case Intrinsic::loongarch_lsx_vslei_w:
3443 case Intrinsic::loongarch_lsx_vslei_d:
3444 case Intrinsic::loongarch_lsx_vslti_b:
3445 case Intrinsic::loongarch_lsx_vslti_h:
3446 case Intrinsic::loongarch_lsx_vslti_w:
3447 case Intrinsic::loongarch_lsx_vslti_d:
3448 case Intrinsic::loongarch_lasx_xvseqi_b:
3449 case Intrinsic::loongarch_lasx_xvseqi_h:
3450 case Intrinsic::loongarch_lasx_xvseqi_w:
3451 case Intrinsic::loongarch_lasx_xvseqi_d:
3452 case Intrinsic::loongarch_lasx_xvslei_b:
3453 case Intrinsic::loongarch_lasx_xvslei_h:
3454 case Intrinsic::loongarch_lasx_xvslei_w:
3455 case Intrinsic::loongarch_lasx_xvslei_d:
3456 case Intrinsic::loongarch_lasx_xvslti_b:
3457 case Intrinsic::loongarch_lasx_xvslti_h:
3458 case Intrinsic::loongarch_lasx_xvslti_w:
3459 case Intrinsic::loongarch_lasx_xvslti_d:
3460 return checkIntrinsicImmArg<5>(
Op, 2, DAG,
true);
3461 case Intrinsic::loongarch_lsx_vsrlni_h_w:
3462 case Intrinsic::loongarch_lsx_vsrani_h_w:
3463 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
3464 case Intrinsic::loongarch_lsx_vsrarni_h_w:
3465 case Intrinsic::loongarch_lsx_vssrlni_h_w:
3466 case Intrinsic::loongarch_lsx_vssrani_h_w:
3467 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
3468 case Intrinsic::loongarch_lsx_vssrani_hu_w:
3469 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
3470 case Intrinsic::loongarch_lsx_vssrarni_h_w:
3471 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
3472 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
3473 case Intrinsic::loongarch_lsx_vfrstpi_b:
3474 case Intrinsic::loongarch_lsx_vfrstpi_h:
3475 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
3476 case Intrinsic::loongarch_lasx_xvsrani_h_w:
3477 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
3478 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
3479 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
3480 case Intrinsic::loongarch_lasx_xvssrani_h_w:
3481 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
3482 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
3483 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
3484 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
3485 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
3486 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
3487 case Intrinsic::loongarch_lasx_xvfrstpi_b:
3488 case Intrinsic::loongarch_lasx_xvfrstpi_h:
3489 return checkIntrinsicImmArg<5>(
Op, 3, DAG);
3490 case Intrinsic::loongarch_lsx_vsat_d:
3491 case Intrinsic::loongarch_lsx_vsat_du:
3492 case Intrinsic::loongarch_lsx_vrotri_d:
3493 case Intrinsic::loongarch_lsx_vsrlri_d:
3494 case Intrinsic::loongarch_lsx_vsrari_d:
3495 case Intrinsic::loongarch_lasx_xvsat_d:
3496 case Intrinsic::loongarch_lasx_xvsat_du:
3497 case Intrinsic::loongarch_lasx_xvrotri_d:
3498 case Intrinsic::loongarch_lasx_xvsrlri_d:
3499 case Intrinsic::loongarch_lasx_xvsrari_d:
3500 return checkIntrinsicImmArg<6>(
Op, 2, DAG);
3501 case Intrinsic::loongarch_lsx_vsrlni_w_d:
3502 case Intrinsic::loongarch_lsx_vsrani_w_d:
3503 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
3504 case Intrinsic::loongarch_lsx_vsrarni_w_d:
3505 case Intrinsic::loongarch_lsx_vssrlni_w_d:
3506 case Intrinsic::loongarch_lsx_vssrani_w_d:
3507 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
3508 case Intrinsic::loongarch_lsx_vssrani_wu_d:
3509 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
3510 case Intrinsic::loongarch_lsx_vssrarni_w_d:
3511 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
3512 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
3513 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
3514 case Intrinsic::loongarch_lasx_xvsrani_w_d:
3515 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
3516 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
3517 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
3518 case Intrinsic::loongarch_lasx_xvssrani_w_d:
3519 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
3520 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
3521 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
3522 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
3523 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
3524 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
3525 return checkIntrinsicImmArg<6>(
Op, 3, DAG);
3526 case Intrinsic::loongarch_lsx_vsrlni_d_q:
3527 case Intrinsic::loongarch_lsx_vsrani_d_q:
3528 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
3529 case Intrinsic::loongarch_lsx_vsrarni_d_q:
3530 case Intrinsic::loongarch_lsx_vssrlni_d_q:
3531 case Intrinsic::loongarch_lsx_vssrani_d_q:
3532 case Intrinsic::loongarch_lsx_vssrlni_du_q:
3533 case Intrinsic::loongarch_lsx_vssrani_du_q:
3534 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
3535 case Intrinsic::loongarch_lsx_vssrarni_d_q:
3536 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
3537 case Intrinsic::loongarch_lsx_vssrarni_du_q:
3538 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
3539 case Intrinsic::loongarch_lasx_xvsrani_d_q:
3540 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
3541 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
3542 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
3543 case Intrinsic::loongarch_lasx_xvssrani_d_q:
3544 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
3545 case Intrinsic::loongarch_lasx_xvssrani_du_q:
3546 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
3547 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
3548 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
3549 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
3550 return checkIntrinsicImmArg<7>(
Op, 3, DAG);
3551 case Intrinsic::loongarch_lsx_vnori_b:
3552 case Intrinsic::loongarch_lsx_vshuf4i_b:
3553 case Intrinsic::loongarch_lsx_vshuf4i_h:
3554 case Intrinsic::loongarch_lsx_vshuf4i_w:
3555 case Intrinsic::loongarch_lasx_xvnori_b:
3556 case Intrinsic::loongarch_lasx_xvshuf4i_b:
3557 case Intrinsic::loongarch_lasx_xvshuf4i_h:
3558 case Intrinsic::loongarch_lasx_xvshuf4i_w:
3559 case Intrinsic::loongarch_lasx_xvpermi_d:
3560 return checkIntrinsicImmArg<8>(
Op, 2, DAG);
3561 case Intrinsic::loongarch_lsx_vshuf4i_d:
3562 case Intrinsic::loongarch_lsx_vpermi_w:
3563 case Intrinsic::loongarch_lsx_vbitseli_b:
3564 case Intrinsic::loongarch_lsx_vextrins_b:
3565 case Intrinsic::loongarch_lsx_vextrins_h:
3566 case Intrinsic::loongarch_lsx_vextrins_w:
3567 case Intrinsic::loongarch_lsx_vextrins_d:
3568 case Intrinsic::loongarch_lasx_xvshuf4i_d:
3569 case Intrinsic::loongarch_lasx_xvpermi_w:
3570 case Intrinsic::loongarch_lasx_xvpermi_q:
3571 case Intrinsic::loongarch_lasx_xvbitseli_b:
3572 case Intrinsic::loongarch_lasx_xvextrins_b:
3573 case Intrinsic::loongarch_lasx_xvextrins_h:
3574 case Intrinsic::loongarch_lasx_xvextrins_w:
3575 case Intrinsic::loongarch_lasx_xvextrins_d:
3576 return checkIntrinsicImmArg<8>(
Op, 3, DAG);
3577 case Intrinsic::loongarch_lsx_vrepli_b:
3578 case Intrinsic::loongarch_lsx_vrepli_h:
3579 case Intrinsic::loongarch_lsx_vrepli_w:
3580 case Intrinsic::loongarch_lsx_vrepli_d:
3581 case Intrinsic::loongarch_lasx_xvrepli_b:
3582 case Intrinsic::loongarch_lasx_xvrepli_h:
3583 case Intrinsic::loongarch_lasx_xvrepli_w:
3584 case Intrinsic::loongarch_lasx_xvrepli_d:
3585 return checkIntrinsicImmArg<10>(
Op, 1, DAG,
true);
3586 case Intrinsic::loongarch_lsx_vldi:
3587 case Intrinsic::loongarch_lasx_xvldi:
3588 return checkIntrinsicImmArg<13>(
Op, 1, DAG,
true);
3603LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
3607 EVT VT =
Op.getValueType();
3609 const StringRef ErrorMsgOOR =
"argument out of range";
3610 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3611 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3613 switch (
Op.getConstantOperandVal(1)) {
3616 case Intrinsic::loongarch_crc_w_b_w:
3617 case Intrinsic::loongarch_crc_w_h_w:
3618 case Intrinsic::loongarch_crc_w_w_w:
3619 case Intrinsic::loongarch_crc_w_d_w:
3620 case Intrinsic::loongarch_crcc_w_b_w:
3621 case Intrinsic::loongarch_crcc_w_h_w:
3622 case Intrinsic::loongarch_crcc_w_w_w:
3623 case Intrinsic::loongarch_crcc_w_d_w:
3625 case Intrinsic::loongarch_csrrd_w:
3626 case Intrinsic::loongarch_csrrd_d: {
3627 unsigned Imm =
Op.getConstantOperandVal(2);
3628 return !isUInt<14>(Imm)
3633 case Intrinsic::loongarch_csrwr_w:
3634 case Intrinsic::loongarch_csrwr_d: {
3635 unsigned Imm =
Op.getConstantOperandVal(3);
3636 return !isUInt<14>(Imm)
3639 {Chain,
Op.getOperand(2),
3642 case Intrinsic::loongarch_csrxchg_w:
3643 case Intrinsic::loongarch_csrxchg_d: {
3644 unsigned Imm =
Op.getConstantOperandVal(4);
3645 return !isUInt<14>(Imm)
3648 {Chain,
Op.getOperand(2),
Op.getOperand(3),
3651 case Intrinsic::loongarch_iocsrrd_d: {
3656#define IOCSRRD_CASE(NAME, NODE) \
3657 case Intrinsic::loongarch_##NAME: { \
3658 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
3659 {Chain, Op.getOperand(2)}); \
3665 case Intrinsic::loongarch_cpucfg: {
3667 {Chain,
Op.getOperand(2)});
3669 case Intrinsic::loongarch_lddir_d: {
3670 unsigned Imm =
Op.getConstantOperandVal(3);
3671 return !isUInt<8>(Imm)
3675 case Intrinsic::loongarch_movfcsr2gr: {
3676 if (!Subtarget.hasBasicF())
3678 unsigned Imm =
Op.getConstantOperandVal(2);
3679 return !isUInt<2>(Imm)
3684 case Intrinsic::loongarch_lsx_vld:
3685 case Intrinsic::loongarch_lsx_vldrepl_b:
3686 case Intrinsic::loongarch_lasx_xvld:
3687 case Intrinsic::loongarch_lasx_xvldrepl_b:
3688 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3691 case Intrinsic::loongarch_lsx_vldrepl_h:
3692 case Intrinsic::loongarch_lasx_xvldrepl_h:
3693 return !isShiftedInt<11, 1>(
3694 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3696 Op,
"argument out of range or not a multiple of 2", DAG)
3698 case Intrinsic::loongarch_lsx_vldrepl_w:
3699 case Intrinsic::loongarch_lasx_xvldrepl_w:
3700 return !isShiftedInt<10, 2>(
3701 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3703 Op,
"argument out of range or not a multiple of 4", DAG)
3705 case Intrinsic::loongarch_lsx_vldrepl_d:
3706 case Intrinsic::loongarch_lasx_xvldrepl_d:
3707 return !isShiftedInt<9, 3>(
3708 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3710 Op,
"argument out of range or not a multiple of 8", DAG)
3721 return Op.getOperand(0);
3729 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
3731 const StringRef ErrorMsgOOR =
"argument out of range";
3732 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3733 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
3734 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3736 switch (IntrinsicEnum) {
3740 case Intrinsic::loongarch_cacop_d:
3741 case Intrinsic::loongarch_cacop_w: {
3742 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.
is64Bit())
3744 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.
is64Bit())
3748 int Imm2 = cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue();
3749 if (!isUInt<5>(Imm1) || !isInt<12>(Imm2))
3753 case Intrinsic::loongarch_dbar: {
3755 return !isUInt<15>(Imm)
3760 case Intrinsic::loongarch_ibar: {
3762 return !isUInt<15>(Imm)
3767 case Intrinsic::loongarch_break: {
3769 return !isUInt<15>(Imm)
3774 case Intrinsic::loongarch_movgr2fcsr: {
3775 if (!Subtarget.hasBasicF())
3778 return !isUInt<2>(Imm)
3785 case Intrinsic::loongarch_syscall: {
3787 return !isUInt<15>(Imm)
3792#define IOCSRWR_CASE(NAME, NODE) \
3793 case Intrinsic::loongarch_##NAME: { \
3794 SDValue Op3 = Op.getOperand(3); \
3795 return Subtarget.is64Bit() \
3796 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
3797 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
3798 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
3799 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
3806 case Intrinsic::loongarch_iocsrwr_d: {
3814#define ASRT_LE_GT_CASE(NAME) \
3815 case Intrinsic::loongarch_##NAME: { \
3816 return !Subtarget.is64Bit() \
3817 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
3822#undef ASRT_LE_GT_CASE
3823 case Intrinsic::loongarch_ldpte_d: {
3824 unsigned Imm =
Op.getConstantOperandVal(3);
3830 case Intrinsic::loongarch_lsx_vst:
3831 case Intrinsic::loongarch_lasx_xvst:
3832 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue())
3835 case Intrinsic::loongarch_lasx_xvstelm_b:
3836 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3837 !isUInt<5>(
Op.getConstantOperandVal(5)))
3840 case Intrinsic::loongarch_lsx_vstelm_b:
3841 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3842 !isUInt<4>(
Op.getConstantOperandVal(5)))
3845 case Intrinsic::loongarch_lasx_xvstelm_h:
3846 return (!isShiftedInt<8, 1>(
3847 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3848 !isUInt<4>(
Op.getConstantOperandVal(5)))
3850 Op,
"argument out of range or not a multiple of 2", DAG)
3852 case Intrinsic::loongarch_lsx_vstelm_h:
3853 return (!isShiftedInt<8, 1>(
3854 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3855 !isUInt<3>(
Op.getConstantOperandVal(5)))
3857 Op,
"argument out of range or not a multiple of 2", DAG)
3859 case Intrinsic::loongarch_lasx_xvstelm_w:
3860 return (!isShiftedInt<8, 2>(
3861 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3862 !isUInt<3>(
Op.getConstantOperandVal(5)))
3864 Op,
"argument out of range or not a multiple of 4", DAG)
3866 case Intrinsic::loongarch_lsx_vstelm_w:
3867 return (!isShiftedInt<8, 2>(
3868 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3869 !isUInt<2>(
Op.getConstantOperandVal(5)))
3871 Op,
"argument out of range or not a multiple of 4", DAG)
3873 case Intrinsic::loongarch_lasx_xvstelm_d:
3874 return (!isShiftedInt<8, 3>(
3875 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3876 !isUInt<2>(
Op.getConstantOperandVal(5)))
3878 Op,
"argument out of range or not a multiple of 8", DAG)
3880 case Intrinsic::loongarch_lsx_vstelm_d:
3881 return (!isShiftedInt<8, 3>(
3882 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3883 !isUInt<1>(
Op.getConstantOperandVal(5)))
3885 Op,
"argument out of range or not a multiple of 8", DAG)
3896 EVT VT =
Lo.getValueType();
3937 EVT VT =
Lo.getValueType();
4029 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4030 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4034 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4040 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4067 StringRef ErrorMsg,
bool WithChain =
true) {
4072 Results.push_back(
N->getOperand(0));
4075template <
unsigned N>
4080 const StringRef ErrorMsgOOR =
"argument out of range";
4081 unsigned Imm =
Node->getConstantOperandVal(2);
4082 if (!isUInt<N>(Imm)) {
4115 switch (
N->getConstantOperandVal(0)) {
4118 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4119 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
4122 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4123 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4124 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
4127 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4128 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
4131 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4132 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
4135 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4136 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4137 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
4140 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4141 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
4144 case Intrinsic::loongarch_lsx_bz_b:
4145 case Intrinsic::loongarch_lsx_bz_h:
4146 case Intrinsic::loongarch_lsx_bz_w:
4147 case Intrinsic::loongarch_lsx_bz_d:
4148 case Intrinsic::loongarch_lasx_xbz_b:
4149 case Intrinsic::loongarch_lasx_xbz_h:
4150 case Intrinsic::loongarch_lasx_xbz_w:
4151 case Intrinsic::loongarch_lasx_xbz_d:
4155 case Intrinsic::loongarch_lsx_bz_v:
4156 case Intrinsic::loongarch_lasx_xbz_v:
4160 case Intrinsic::loongarch_lsx_bnz_b:
4161 case Intrinsic::loongarch_lsx_bnz_h:
4162 case Intrinsic::loongarch_lsx_bnz_w:
4163 case Intrinsic::loongarch_lsx_bnz_d:
4164 case Intrinsic::loongarch_lasx_xbnz_b:
4165 case Intrinsic::loongarch_lasx_xbnz_h:
4166 case Intrinsic::loongarch_lasx_xbnz_w:
4167 case Intrinsic::loongarch_lasx_xbnz_d:
4171 case Intrinsic::loongarch_lsx_bnz_v:
4172 case Intrinsic::loongarch_lasx_xbnz_v:
4182 assert(
N->getValueType(0) == MVT::i128 &&
4183 "AtomicCmpSwap on types less than 128 should be legal");
4187 switch (
MemOp->getMergedOrdering()) {
4191 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4195 Opcode = LoongArch::PseudoCmpXchg128;
4202 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4203 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4204 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4205 NewVal.first, NewVal.second,
N->getOperand(0)};
4208 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4219 EVT VT =
N->getValueType(0);
4220 switch (
N->getOpcode()) {
4226 "Unexpected custom legalisation");
4234 "Unexpected custom legalisation");
4236 Subtarget.hasDiv32() && VT == MVT::i32
4244 "Unexpected custom legalisation");
4253 "Unexpected custom legalisation");
4258 "Unexpected custom legalisation");
4265 if (Src.getValueType() == MVT::f16)
4276 EVT OpVT = Src.getValueType();
4280 std::tie(Result, Chain) =
4287 EVT SrcVT = Src.getValueType();
4288 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.
is64Bit() &&
4289 Subtarget.hasBasicF()) {
4293 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.
is64Bit()) {
4295 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4304 "Unexpected custom legalisation");
4307 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4313 assert((VT == MVT::i16 || VT == MVT::i32) &&
4314 "Unexpected custom legalization");
4335 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
4336 "Unexpected custom legalization");
4356 "Unexpected custom legalisation");
4364 const StringRef ErrorMsgOOR =
"argument out of range";
4365 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4366 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4368 switch (
N->getConstantOperandVal(1)) {
4371 case Intrinsic::loongarch_movfcsr2gr: {
4372 if (!Subtarget.hasBasicF()) {
4377 if (!isUInt<2>(Imm)) {
4389#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4390 case Intrinsic::loongarch_##NAME: { \
4391 SDValue NODE = DAG.getNode( \
4392 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4393 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4394 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4395 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4396 Results.push_back(NODE.getValue(1)); \
4405#undef CRC_CASE_EXT_BINARYOP
4407#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4408 case Intrinsic::loongarch_##NAME: { \
4409 SDValue NODE = DAG.getNode( \
4410 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4412 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4413 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4414 Results.push_back(NODE.getValue(1)); \
4419#undef CRC_CASE_EXT_UNARYOP
4420#define CSR_CASE(ID) \
4421 case Intrinsic::loongarch_##ID: { \
4422 if (!Subtarget.is64Bit()) \
4423 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
4431 case Intrinsic::loongarch_csrrd_w: {
4433 if (!isUInt<14>(Imm)) {
4445 case Intrinsic::loongarch_csrwr_w: {
4446 unsigned Imm =
N->getConstantOperandVal(3);
4447 if (!isUInt<14>(Imm)) {
4460 case Intrinsic::loongarch_csrxchg_w: {
4461 unsigned Imm =
N->getConstantOperandVal(4);
4462 if (!isUInt<14>(Imm)) {
4476#define IOCSRRD_CASE(NAME, NODE) \
4477 case Intrinsic::loongarch_##NAME: { \
4478 SDValue IOCSRRDResults = \
4479 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4480 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
4481 Results.push_back( \
4482 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
4483 Results.push_back(IOCSRRDResults.getValue(1)); \
4490 case Intrinsic::loongarch_cpucfg: {
4499 case Intrinsic::loongarch_lddir_d: {
4512 "On LA64, only 64-bit registers can be read.");
4515 "On LA32, only 32-bit registers can be read.");
4517 Results.push_back(
N->getOperand(0));
4528 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
4541 MVT VT =
N->getSimpleValueType(0);
4547 EVT InVT = In.getValueType();
4558 for (
unsigned I = 0;
I < MinElts; ++
I)
4559 TruncMask[
I] = Scale *
I;
4561 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
4562 MVT SVT = In.getSimpleValueType().getScalarType();
4568 "Illegal vector type in truncation");
4587 SDValue FirstOperand =
N->getOperand(0);
4588 SDValue SecondOperand =
N->getOperand(1);
4589 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
4590 EVT ValTy =
N->getValueType(0);
4593 unsigned SMIdx, SMLen;
4599 if (!Subtarget.has32S())
4603 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||
4614 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))))
4655 NewOperand = FirstOperand;
4658 msb = lsb + SMLen - 1;
4662 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
4675 if (!Subtarget.has32S())
4687 SDValue FirstOperand =
N->getOperand(0);
4689 EVT ValTy =
N->getValueType(0);
4692 unsigned MaskIdx, MaskLen;
4698 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))) ||
4703 if (!(CN = dyn_cast<ConstantSDNode>(
N->getOperand(1))))
4707 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
4723 switch (Src.getOpcode()) {
4726 return Src.getOperand(0).getValueSizeInBits() ==
Size;
4736 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
4749 switch (Src.getOpcode()) {
4759 Src.getOpcode(),
DL, SExtVT,
4765 DL, SExtVT, Src.getOperand(0),
4777 EVT VT =
N->getValueType(0);
4779 EVT SrcVT = Src.getValueType();
4781 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
4786 EVT CmpVT = Src.getOperand(0).getValueType();
4791 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
4797 SDValue SrcN1 = Src.getOperand(1);
4798 switch (cast<CondCodeSDNode>(Src.getOperand(2))->get()) {
4819 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4826 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4850 EVT VT =
N->getValueType(0);
4852 EVT SrcVT = Src.getValueType();
4868 bool UseLASX =
false;
4869 bool PropagateSExt =
false;
4871 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
4872 EVT CmpVT = Src.getOperand(0).getValueType();
4881 SExtVT = MVT::v2i64;
4884 SExtVT = MVT::v4i32;
4886 SExtVT = MVT::v4i64;
4888 PropagateSExt =
true;
4892 SExtVT = MVT::v8i16;
4894 SExtVT = MVT::v8i32;
4896 PropagateSExt =
true;
4900 SExtVT = MVT::v16i8;
4902 SExtVT = MVT::v16i16;
4904 PropagateSExt =
true;
4908 SExtVT = MVT::v32i8;
4916 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
4917 if (Src.getSimpleValueType() == MVT::v32i8) {
4925 }
else if (UseLASX) {
4944 EVT ValTy =
N->getValueType(0);
4945 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
4949 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
4951 bool SwapAndRetried =
false;
4954 if (!Subtarget.has32S())
4960 if (ValBits != 32 && ValBits != 64)
4970 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4973 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
4975 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
4976 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
4978 (MaskIdx0 + MaskLen0 <= ValBits)) {
4992 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4995 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
4997 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
4999 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5000 (MaskIdx0 + MaskLen0 <= ValBits)) {
5015 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
5017 (MaskIdx0 + MaskLen0 <= 64) &&
5018 (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) &&
5025 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5026 : (MaskIdx0 + MaskLen0 - 1),
5038 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
5040 MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5042 (MaskIdx0 + MaskLen0 <= ValBits)) {
5057 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
5059 (CN1 = dyn_cast<ConstantSDNode>(N1)) &&
5065 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5066 : (MaskIdx0 + MaskLen0 - 1),
5081 unsigned MaskIdx, MaskLen;
5082 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5083 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
5085 MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5107 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5109 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5110 (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
5123 if (!SwapAndRetried) {
5125 SwapAndRetried =
true;
5129 SwapAndRetried =
false;
5141 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5155 if (!SwapAndRetried) {
5157 SwapAndRetried =
true;
5167 switch (V.getNode()->getOpcode()) {
5169 LoadSDNode *LoadNode = cast<LoadSDNode>(V.getNode());
5178 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
5179 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5186 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
5187 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5262 ISD::CondCode CC = cast<CondCodeSDNode>(
N->getOperand(2))->get();
5264 SDNode *AndNode =
N->getOperand(0).getNode();
5272 SDValue CmpInputValue =
N->getOperand(1);
5280 CN = dyn_cast<ConstantSDNode>(CmpInputValue);
5283 AndInputValue1 = AndInputValue1.
getOperand(0);
5287 if (AndInputValue2 != CmpInputValue)
5320 TruncInputValue1, TruncInputValue2);
5322 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5363 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
5367 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
5391 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
5425 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
5441 EVT VT =
N->getValueType(0);
5444 if (TrueV == FalseV)
5449 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
5455 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
5456 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
5459 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
5460 isInt<12>(TrueSImm - FalseSImm)) {
5476 {LHS, RHS, CC, TrueV, FalseV});
5481template <
unsigned N>
5485 bool IsSigned =
false) {
5487 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
5489 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
5490 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
5492 ": argument out of range.");
5498template <
unsigned N>
5502 EVT ResTy =
Node->getValueType(0);
5503 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
5506 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
5507 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
5509 ": argument out of range.");
5514 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
5520 EVT ResTy =
Node->getValueType(0);
5528 EVT ResTy =
Node->getValueType(0);
5537template <
unsigned N>
5540 EVT ResTy =
Node->getValueType(0);
5541 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5543 if (!isUInt<N>(CImm->getZExtValue())) {
5545 ": argument out of range.");
5555template <
unsigned N>
5558 EVT ResTy =
Node->getValueType(0);
5559 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5561 if (!isUInt<N>(CImm->getZExtValue())) {
5563 ": argument out of range.");
5572template <
unsigned N>
5575 EVT ResTy =
Node->getValueType(0);
5576 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5578 if (!isUInt<N>(CImm->getZExtValue())) {
5580 ": argument out of range.");
5594 switch (
N->getConstantOperandVal(0)) {
5597 case Intrinsic::loongarch_lsx_vadd_b:
5598 case Intrinsic::loongarch_lsx_vadd_h:
5599 case Intrinsic::loongarch_lsx_vadd_w:
5600 case Intrinsic::loongarch_lsx_vadd_d:
5601 case Intrinsic::loongarch_lasx_xvadd_b:
5602 case Intrinsic::loongarch_lasx_xvadd_h:
5603 case Intrinsic::loongarch_lasx_xvadd_w:
5604 case Intrinsic::loongarch_lasx_xvadd_d:
5607 case Intrinsic::loongarch_lsx_vaddi_bu:
5608 case Intrinsic::loongarch_lsx_vaddi_hu:
5609 case Intrinsic::loongarch_lsx_vaddi_wu:
5610 case Intrinsic::loongarch_lsx_vaddi_du:
5611 case Intrinsic::loongarch_lasx_xvaddi_bu:
5612 case Intrinsic::loongarch_lasx_xvaddi_hu:
5613 case Intrinsic::loongarch_lasx_xvaddi_wu:
5614 case Intrinsic::loongarch_lasx_xvaddi_du:
5616 lowerVectorSplatImm<5>(
N, 2, DAG));
5617 case Intrinsic::loongarch_lsx_vsub_b:
5618 case Intrinsic::loongarch_lsx_vsub_h:
5619 case Intrinsic::loongarch_lsx_vsub_w:
5620 case Intrinsic::loongarch_lsx_vsub_d:
5621 case Intrinsic::loongarch_lasx_xvsub_b:
5622 case Intrinsic::loongarch_lasx_xvsub_h:
5623 case Intrinsic::loongarch_lasx_xvsub_w:
5624 case Intrinsic::loongarch_lasx_xvsub_d:
5627 case Intrinsic::loongarch_lsx_vsubi_bu:
5628 case Intrinsic::loongarch_lsx_vsubi_hu:
5629 case Intrinsic::loongarch_lsx_vsubi_wu:
5630 case Intrinsic::loongarch_lsx_vsubi_du:
5631 case Intrinsic::loongarch_lasx_xvsubi_bu:
5632 case Intrinsic::loongarch_lasx_xvsubi_hu:
5633 case Intrinsic::loongarch_lasx_xvsubi_wu:
5634 case Intrinsic::loongarch_lasx_xvsubi_du:
5636 lowerVectorSplatImm<5>(
N, 2, DAG));
5637 case Intrinsic::loongarch_lsx_vneg_b:
5638 case Intrinsic::loongarch_lsx_vneg_h:
5639 case Intrinsic::loongarch_lsx_vneg_w:
5640 case Intrinsic::loongarch_lsx_vneg_d:
5641 case Intrinsic::loongarch_lasx_xvneg_b:
5642 case Intrinsic::loongarch_lasx_xvneg_h:
5643 case Intrinsic::loongarch_lasx_xvneg_w:
5644 case Intrinsic::loongarch_lasx_xvneg_d:
5648 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
5650 SDLoc(
N),
N->getValueType(0)),
5652 case Intrinsic::loongarch_lsx_vmax_b:
5653 case Intrinsic::loongarch_lsx_vmax_h:
5654 case Intrinsic::loongarch_lsx_vmax_w:
5655 case Intrinsic::loongarch_lsx_vmax_d:
5656 case Intrinsic::loongarch_lasx_xvmax_b:
5657 case Intrinsic::loongarch_lasx_xvmax_h:
5658 case Intrinsic::loongarch_lasx_xvmax_w:
5659 case Intrinsic::loongarch_lasx_xvmax_d:
5662 case Intrinsic::loongarch_lsx_vmax_bu:
5663 case Intrinsic::loongarch_lsx_vmax_hu:
5664 case Intrinsic::loongarch_lsx_vmax_wu:
5665 case Intrinsic::loongarch_lsx_vmax_du:
5666 case Intrinsic::loongarch_lasx_xvmax_bu:
5667 case Intrinsic::loongarch_lasx_xvmax_hu:
5668 case Intrinsic::loongarch_lasx_xvmax_wu:
5669 case Intrinsic::loongarch_lasx_xvmax_du:
5672 case Intrinsic::loongarch_lsx_vmaxi_b:
5673 case Intrinsic::loongarch_lsx_vmaxi_h:
5674 case Intrinsic::loongarch_lsx_vmaxi_w:
5675 case Intrinsic::loongarch_lsx_vmaxi_d:
5676 case Intrinsic::loongarch_lasx_xvmaxi_b:
5677 case Intrinsic::loongarch_lasx_xvmaxi_h:
5678 case Intrinsic::loongarch_lasx_xvmaxi_w:
5679 case Intrinsic::loongarch_lasx_xvmaxi_d:
5681 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
5682 case Intrinsic::loongarch_lsx_vmaxi_bu:
5683 case Intrinsic::loongarch_lsx_vmaxi_hu:
5684 case Intrinsic::loongarch_lsx_vmaxi_wu:
5685 case Intrinsic::loongarch_lsx_vmaxi_du:
5686 case Intrinsic::loongarch_lasx_xvmaxi_bu:
5687 case Intrinsic::loongarch_lasx_xvmaxi_hu:
5688 case Intrinsic::loongarch_lasx_xvmaxi_wu:
5689 case Intrinsic::loongarch_lasx_xvmaxi_du:
5691 lowerVectorSplatImm<5>(
N, 2, DAG));
5692 case Intrinsic::loongarch_lsx_vmin_b:
5693 case Intrinsic::loongarch_lsx_vmin_h:
5694 case Intrinsic::loongarch_lsx_vmin_w:
5695 case Intrinsic::loongarch_lsx_vmin_d:
5696 case Intrinsic::loongarch_lasx_xvmin_b:
5697 case Intrinsic::loongarch_lasx_xvmin_h:
5698 case Intrinsic::loongarch_lasx_xvmin_w:
5699 case Intrinsic::loongarch_lasx_xvmin_d:
5702 case Intrinsic::loongarch_lsx_vmin_bu:
5703 case Intrinsic::loongarch_lsx_vmin_hu:
5704 case Intrinsic::loongarch_lsx_vmin_wu:
5705 case Intrinsic::loongarch_lsx_vmin_du:
5706 case Intrinsic::loongarch_lasx_xvmin_bu:
5707 case Intrinsic::loongarch_lasx_xvmin_hu:
5708 case Intrinsic::loongarch_lasx_xvmin_wu:
5709 case Intrinsic::loongarch_lasx_xvmin_du:
5712 case Intrinsic::loongarch_lsx_vmini_b:
5713 case Intrinsic::loongarch_lsx_vmini_h:
5714 case Intrinsic::loongarch_lsx_vmini_w:
5715 case Intrinsic::loongarch_lsx_vmini_d:
5716 case Intrinsic::loongarch_lasx_xvmini_b:
5717 case Intrinsic::loongarch_lasx_xvmini_h:
5718 case Intrinsic::loongarch_lasx_xvmini_w:
5719 case Intrinsic::loongarch_lasx_xvmini_d:
5721 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
5722 case Intrinsic::loongarch_lsx_vmini_bu:
5723 case Intrinsic::loongarch_lsx_vmini_hu:
5724 case Intrinsic::loongarch_lsx_vmini_wu:
5725 case Intrinsic::loongarch_lsx_vmini_du:
5726 case Intrinsic::loongarch_lasx_xvmini_bu:
5727 case Intrinsic::loongarch_lasx_xvmini_hu:
5728 case Intrinsic::loongarch_lasx_xvmini_wu:
5729 case Intrinsic::loongarch_lasx_xvmini_du:
5731 lowerVectorSplatImm<5>(
N, 2, DAG));
5732 case Intrinsic::loongarch_lsx_vmul_b:
5733 case Intrinsic::loongarch_lsx_vmul_h:
5734 case Intrinsic::loongarch_lsx_vmul_w:
5735 case Intrinsic::loongarch_lsx_vmul_d:
5736 case Intrinsic::loongarch_lasx_xvmul_b:
5737 case Intrinsic::loongarch_lasx_xvmul_h:
5738 case Intrinsic::loongarch_lasx_xvmul_w:
5739 case Intrinsic::loongarch_lasx_xvmul_d:
5742 case Intrinsic::loongarch_lsx_vmadd_b:
5743 case Intrinsic::loongarch_lsx_vmadd_h:
5744 case Intrinsic::loongarch_lsx_vmadd_w:
5745 case Intrinsic::loongarch_lsx_vmadd_d:
5746 case Intrinsic::loongarch_lasx_xvmadd_b:
5747 case Intrinsic::loongarch_lasx_xvmadd_h:
5748 case Intrinsic::loongarch_lasx_xvmadd_w:
5749 case Intrinsic::loongarch_lasx_xvmadd_d: {
5750 EVT ResTy =
N->getValueType(0);
5755 case Intrinsic::loongarch_lsx_vmsub_b:
5756 case Intrinsic::loongarch_lsx_vmsub_h:
5757 case Intrinsic::loongarch_lsx_vmsub_w:
5758 case Intrinsic::loongarch_lsx_vmsub_d:
5759 case Intrinsic::loongarch_lasx_xvmsub_b:
5760 case Intrinsic::loongarch_lasx_xvmsub_h:
5761 case Intrinsic::loongarch_lasx_xvmsub_w:
5762 case Intrinsic::loongarch_lasx_xvmsub_d: {
5763 EVT ResTy =
N->getValueType(0);
5768 case Intrinsic::loongarch_lsx_vdiv_b:
5769 case Intrinsic::loongarch_lsx_vdiv_h:
5770 case Intrinsic::loongarch_lsx_vdiv_w:
5771 case Intrinsic::loongarch_lsx_vdiv_d:
5772 case Intrinsic::loongarch_lasx_xvdiv_b:
5773 case Intrinsic::loongarch_lasx_xvdiv_h:
5774 case Intrinsic::loongarch_lasx_xvdiv_w:
5775 case Intrinsic::loongarch_lasx_xvdiv_d:
5778 case Intrinsic::loongarch_lsx_vdiv_bu:
5779 case Intrinsic::loongarch_lsx_vdiv_hu:
5780 case Intrinsic::loongarch_lsx_vdiv_wu:
5781 case Intrinsic::loongarch_lsx_vdiv_du:
5782 case Intrinsic::loongarch_lasx_xvdiv_bu:
5783 case Intrinsic::loongarch_lasx_xvdiv_hu:
5784 case Intrinsic::loongarch_lasx_xvdiv_wu:
5785 case Intrinsic::loongarch_lasx_xvdiv_du:
5788 case Intrinsic::loongarch_lsx_vmod_b:
5789 case Intrinsic::loongarch_lsx_vmod_h:
5790 case Intrinsic::loongarch_lsx_vmod_w:
5791 case Intrinsic::loongarch_lsx_vmod_d:
5792 case Intrinsic::loongarch_lasx_xvmod_b:
5793 case Intrinsic::loongarch_lasx_xvmod_h:
5794 case Intrinsic::loongarch_lasx_xvmod_w:
5795 case Intrinsic::loongarch_lasx_xvmod_d:
5798 case Intrinsic::loongarch_lsx_vmod_bu:
5799 case Intrinsic::loongarch_lsx_vmod_hu:
5800 case Intrinsic::loongarch_lsx_vmod_wu:
5801 case Intrinsic::loongarch_lsx_vmod_du:
5802 case Intrinsic::loongarch_lasx_xvmod_bu:
5803 case Intrinsic::loongarch_lasx_xvmod_hu:
5804 case Intrinsic::loongarch_lasx_xvmod_wu:
5805 case Intrinsic::loongarch_lasx_xvmod_du:
5808 case Intrinsic::loongarch_lsx_vand_v:
5809 case Intrinsic::loongarch_lasx_xvand_v:
5812 case Intrinsic::loongarch_lsx_vor_v:
5813 case Intrinsic::loongarch_lasx_xvor_v:
5816 case Intrinsic::loongarch_lsx_vxor_v:
5817 case Intrinsic::loongarch_lasx_xvxor_v:
5820 case Intrinsic::loongarch_lsx_vnor_v:
5821 case Intrinsic::loongarch_lasx_xvnor_v: {
5826 case Intrinsic::loongarch_lsx_vandi_b:
5827 case Intrinsic::loongarch_lasx_xvandi_b:
5829 lowerVectorSplatImm<8>(
N, 2, DAG));
5830 case Intrinsic::loongarch_lsx_vori_b:
5831 case Intrinsic::loongarch_lasx_xvori_b:
5833 lowerVectorSplatImm<8>(
N, 2, DAG));
5834 case Intrinsic::loongarch_lsx_vxori_b:
5835 case Intrinsic::loongarch_lasx_xvxori_b:
5837 lowerVectorSplatImm<8>(
N, 2, DAG));
5838 case Intrinsic::loongarch_lsx_vsll_b:
5839 case Intrinsic::loongarch_lsx_vsll_h:
5840 case Intrinsic::loongarch_lsx_vsll_w:
5841 case Intrinsic::loongarch_lsx_vsll_d:
5842 case Intrinsic::loongarch_lasx_xvsll_b:
5843 case Intrinsic::loongarch_lasx_xvsll_h:
5844 case Intrinsic::loongarch_lasx_xvsll_w:
5845 case Intrinsic::loongarch_lasx_xvsll_d:
5848 case Intrinsic::loongarch_lsx_vslli_b:
5849 case Intrinsic::loongarch_lasx_xvslli_b:
5851 lowerVectorSplatImm<3>(
N, 2, DAG));
5852 case Intrinsic::loongarch_lsx_vslli_h:
5853 case Intrinsic::loongarch_lasx_xvslli_h:
5855 lowerVectorSplatImm<4>(
N, 2, DAG));
5856 case Intrinsic::loongarch_lsx_vslli_w:
5857 case Intrinsic::loongarch_lasx_xvslli_w:
5859 lowerVectorSplatImm<5>(
N, 2, DAG));
5860 case Intrinsic::loongarch_lsx_vslli_d:
5861 case Intrinsic::loongarch_lasx_xvslli_d:
5863 lowerVectorSplatImm<6>(
N, 2, DAG));
5864 case Intrinsic::loongarch_lsx_vsrl_b:
5865 case Intrinsic::loongarch_lsx_vsrl_h:
5866 case Intrinsic::loongarch_lsx_vsrl_w:
5867 case Intrinsic::loongarch_lsx_vsrl_d:
5868 case Intrinsic::loongarch_lasx_xvsrl_b:
5869 case Intrinsic::loongarch_lasx_xvsrl_h:
5870 case Intrinsic::loongarch_lasx_xvsrl_w:
5871 case Intrinsic::loongarch_lasx_xvsrl_d:
5874 case Intrinsic::loongarch_lsx_vsrli_b:
5875 case Intrinsic::loongarch_lasx_xvsrli_b:
5877 lowerVectorSplatImm<3>(
N, 2, DAG));
5878 case Intrinsic::loongarch_lsx_vsrli_h:
5879 case Intrinsic::loongarch_lasx_xvsrli_h:
5881 lowerVectorSplatImm<4>(
N, 2, DAG));
5882 case Intrinsic::loongarch_lsx_vsrli_w:
5883 case Intrinsic::loongarch_lasx_xvsrli_w:
5885 lowerVectorSplatImm<5>(
N, 2, DAG));
5886 case Intrinsic::loongarch_lsx_vsrli_d:
5887 case Intrinsic::loongarch_lasx_xvsrli_d:
5889 lowerVectorSplatImm<6>(
N, 2, DAG));
5890 case Intrinsic::loongarch_lsx_vsra_b:
5891 case Intrinsic::loongarch_lsx_vsra_h:
5892 case Intrinsic::loongarch_lsx_vsra_w:
5893 case Intrinsic::loongarch_lsx_vsra_d:
5894 case Intrinsic::loongarch_lasx_xvsra_b:
5895 case Intrinsic::loongarch_lasx_xvsra_h:
5896 case Intrinsic::loongarch_lasx_xvsra_w:
5897 case Intrinsic::loongarch_lasx_xvsra_d:
5900 case Intrinsic::loongarch_lsx_vsrai_b:
5901 case Intrinsic::loongarch_lasx_xvsrai_b:
5903 lowerVectorSplatImm<3>(
N, 2, DAG));
5904 case Intrinsic::loongarch_lsx_vsrai_h:
5905 case Intrinsic::loongarch_lasx_xvsrai_h:
5907 lowerVectorSplatImm<4>(
N, 2, DAG));
5908 case Intrinsic::loongarch_lsx_vsrai_w:
5909 case Intrinsic::loongarch_lasx_xvsrai_w:
5911 lowerVectorSplatImm<5>(
N, 2, DAG));
5912 case Intrinsic::loongarch_lsx_vsrai_d:
5913 case Intrinsic::loongarch_lasx_xvsrai_d:
5915 lowerVectorSplatImm<6>(
N, 2, DAG));
5916 case Intrinsic::loongarch_lsx_vclz_b:
5917 case Intrinsic::loongarch_lsx_vclz_h:
5918 case Intrinsic::loongarch_lsx_vclz_w:
5919 case Intrinsic::loongarch_lsx_vclz_d:
5920 case Intrinsic::loongarch_lasx_xvclz_b:
5921 case Intrinsic::loongarch_lasx_xvclz_h:
5922 case Intrinsic::loongarch_lasx_xvclz_w:
5923 case Intrinsic::loongarch_lasx_xvclz_d:
5925 case Intrinsic::loongarch_lsx_vpcnt_b:
5926 case Intrinsic::loongarch_lsx_vpcnt_h:
5927 case Intrinsic::loongarch_lsx_vpcnt_w:
5928 case Intrinsic::loongarch_lsx_vpcnt_d:
5929 case Intrinsic::loongarch_lasx_xvpcnt_b:
5930 case Intrinsic::loongarch_lasx_xvpcnt_h:
5931 case Intrinsic::loongarch_lasx_xvpcnt_w:
5932 case Intrinsic::loongarch_lasx_xvpcnt_d:
5934 case Intrinsic::loongarch_lsx_vbitclr_b:
5935 case Intrinsic::loongarch_lsx_vbitclr_h:
5936 case Intrinsic::loongarch_lsx_vbitclr_w:
5937 case Intrinsic::loongarch_lsx_vbitclr_d:
5938 case Intrinsic::loongarch_lasx_xvbitclr_b:
5939 case Intrinsic::loongarch_lasx_xvbitclr_h:
5940 case Intrinsic::loongarch_lasx_xvbitclr_w:
5941 case Intrinsic::loongarch_lasx_xvbitclr_d:
5943 case Intrinsic::loongarch_lsx_vbitclri_b:
5944 case Intrinsic::loongarch_lasx_xvbitclri_b:
5945 return lowerVectorBitClearImm<3>(
N, DAG);
5946 case Intrinsic::loongarch_lsx_vbitclri_h:
5947 case Intrinsic::loongarch_lasx_xvbitclri_h:
5948 return lowerVectorBitClearImm<4>(
N, DAG);
5949 case Intrinsic::loongarch_lsx_vbitclri_w:
5950 case Intrinsic::loongarch_lasx_xvbitclri_w:
5951 return lowerVectorBitClearImm<5>(
N, DAG);
5952 case Intrinsic::loongarch_lsx_vbitclri_d:
5953 case Intrinsic::loongarch_lasx_xvbitclri_d:
5954 return lowerVectorBitClearImm<6>(
N, DAG);
5955 case Intrinsic::loongarch_lsx_vbitset_b:
5956 case Intrinsic::loongarch_lsx_vbitset_h:
5957 case Intrinsic::loongarch_lsx_vbitset_w:
5958 case Intrinsic::loongarch_lsx_vbitset_d:
5959 case Intrinsic::loongarch_lasx_xvbitset_b:
5960 case Intrinsic::loongarch_lasx_xvbitset_h:
5961 case Intrinsic::loongarch_lasx_xvbitset_w:
5962 case Intrinsic::loongarch_lasx_xvbitset_d: {
5963 EVT VecTy =
N->getValueType(0);
5969 case Intrinsic::loongarch_lsx_vbitseti_b:
5970 case Intrinsic::loongarch_lasx_xvbitseti_b:
5971 return lowerVectorBitSetImm<3>(
N, DAG);
5972 case Intrinsic::loongarch_lsx_vbitseti_h:
5973 case Intrinsic::loongarch_lasx_xvbitseti_h:
5974 return lowerVectorBitSetImm<4>(
N, DAG);
5975 case Intrinsic::loongarch_lsx_vbitseti_w:
5976 case Intrinsic::loongarch_lasx_xvbitseti_w:
5977 return lowerVectorBitSetImm<5>(
N, DAG);
5978 case Intrinsic::loongarch_lsx_vbitseti_d:
5979 case Intrinsic::loongarch_lasx_xvbitseti_d:
5980 return lowerVectorBitSetImm<6>(
N, DAG);
5981 case Intrinsic::loongarch_lsx_vbitrev_b:
5982 case Intrinsic::loongarch_lsx_vbitrev_h:
5983 case Intrinsic::loongarch_lsx_vbitrev_w:
5984 case Intrinsic::loongarch_lsx_vbitrev_d:
5985 case Intrinsic::loongarch_lasx_xvbitrev_b:
5986 case Intrinsic::loongarch_lasx_xvbitrev_h:
5987 case Intrinsic::loongarch_lasx_xvbitrev_w:
5988 case Intrinsic::loongarch_lasx_xvbitrev_d: {
5989 EVT VecTy =
N->getValueType(0);
5995 case Intrinsic::loongarch_lsx_vbitrevi_b:
5996 case Intrinsic::loongarch_lasx_xvbitrevi_b:
5997 return lowerVectorBitRevImm<3>(
N, DAG);
5998 case Intrinsic::loongarch_lsx_vbitrevi_h:
5999 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6000 return lowerVectorBitRevImm<4>(
N, DAG);
6001 case Intrinsic::loongarch_lsx_vbitrevi_w:
6002 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6003 return lowerVectorBitRevImm<5>(
N, DAG);
6004 case Intrinsic::loongarch_lsx_vbitrevi_d:
6005 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6006 return lowerVectorBitRevImm<6>(
N, DAG);
6007 case Intrinsic::loongarch_lsx_vfadd_s:
6008 case Intrinsic::loongarch_lsx_vfadd_d:
6009 case Intrinsic::loongarch_lasx_xvfadd_s:
6010 case Intrinsic::loongarch_lasx_xvfadd_d:
6013 case Intrinsic::loongarch_lsx_vfsub_s:
6014 case Intrinsic::loongarch_lsx_vfsub_d:
6015 case Intrinsic::loongarch_lasx_xvfsub_s:
6016 case Intrinsic::loongarch_lasx_xvfsub_d:
6019 case Intrinsic::loongarch_lsx_vfmul_s:
6020 case Intrinsic::loongarch_lsx_vfmul_d:
6021 case Intrinsic::loongarch_lasx_xvfmul_s:
6022 case Intrinsic::loongarch_lasx_xvfmul_d:
6025 case Intrinsic::loongarch_lsx_vfdiv_s:
6026 case Intrinsic::loongarch_lsx_vfdiv_d:
6027 case Intrinsic::loongarch_lasx_xvfdiv_s:
6028 case Intrinsic::loongarch_lasx_xvfdiv_d:
6031 case Intrinsic::loongarch_lsx_vfmadd_s:
6032 case Intrinsic::loongarch_lsx_vfmadd_d:
6033 case Intrinsic::loongarch_lasx_xvfmadd_s:
6034 case Intrinsic::loongarch_lasx_xvfmadd_d:
6036 N->getOperand(2),
N->getOperand(3));
6037 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6039 N->getOperand(1),
N->getOperand(2),
6040 legalizeIntrinsicImmArg<4>(
N, 3, DAG, Subtarget));
6041 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6042 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6044 N->getOperand(1),
N->getOperand(2),
6045 legalizeIntrinsicImmArg<3>(
N, 3, DAG, Subtarget));
6046 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6047 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6049 N->getOperand(1),
N->getOperand(2),
6050 legalizeIntrinsicImmArg<2>(
N, 3, DAG, Subtarget));
6051 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6053 N->getOperand(1),
N->getOperand(2),
6054 legalizeIntrinsicImmArg<1>(
N, 3, DAG, Subtarget));
6055 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6056 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6057 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6058 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6059 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6060 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6061 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6062 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6066 case Intrinsic::loongarch_lsx_vreplve_b:
6067 case Intrinsic::loongarch_lsx_vreplve_h:
6068 case Intrinsic::loongarch_lsx_vreplve_w:
6069 case Intrinsic::loongarch_lsx_vreplve_d:
6070 case Intrinsic::loongarch_lasx_xvreplve_b:
6071 case Intrinsic::loongarch_lasx_xvreplve_h:
6072 case Intrinsic::loongarch_lasx_xvreplve_w:
6073 case Intrinsic::loongarch_lasx_xvreplve_d:
6103 "Unexpected value type!");
6112 MVT VT =
N->getSimpleValueType(0);
6146 APInt V =
C->getValueAPF().bitcastToAPInt();
6158 switch (
N->getOpcode()) {
6210 MF->
insert(It, BreakMBB);
6214 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->
end());
6215 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
6234 BreakMBB->addSuccessor(SinkMBB);
6246 switch (
MI.getOpcode()) {
6249 case LoongArch::PseudoVBZ:
6250 CondOpc = LoongArch::VSETEQZ_V;
6252 case LoongArch::PseudoVBZ_B:
6253 CondOpc = LoongArch::VSETANYEQZ_B;
6255 case LoongArch::PseudoVBZ_H:
6256 CondOpc = LoongArch::VSETANYEQZ_H;
6258 case LoongArch::PseudoVBZ_W:
6259 CondOpc = LoongArch::VSETANYEQZ_W;
6261 case LoongArch::PseudoVBZ_D:
6262 CondOpc = LoongArch::VSETANYEQZ_D;
6264 case LoongArch::PseudoVBNZ:
6265 CondOpc = LoongArch::VSETNEZ_V;
6267 case LoongArch::PseudoVBNZ_B:
6268 CondOpc = LoongArch::VSETALLNEZ_B;
6270 case LoongArch::PseudoVBNZ_H:
6271 CondOpc = LoongArch::VSETALLNEZ_H;
6273 case LoongArch::PseudoVBNZ_W:
6274 CondOpc = LoongArch::VSETALLNEZ_W;
6276 case LoongArch::PseudoVBNZ_D:
6277 CondOpc = LoongArch::VSETALLNEZ_D;
6279 case LoongArch::PseudoXVBZ:
6280 CondOpc = LoongArch::XVSETEQZ_V;
6282 case LoongArch::PseudoXVBZ_B:
6283 CondOpc = LoongArch::XVSETANYEQZ_B;
6285 case LoongArch::PseudoXVBZ_H:
6286 CondOpc = LoongArch::XVSETANYEQZ_H;
6288 case LoongArch::PseudoXVBZ_W:
6289 CondOpc = LoongArch::XVSETANYEQZ_W;
6291 case LoongArch::PseudoXVBZ_D:
6292 CondOpc = LoongArch::XVSETANYEQZ_D;
6294 case LoongArch::PseudoXVBNZ:
6295 CondOpc = LoongArch::XVSETNEZ_V;
6297 case LoongArch::PseudoXVBNZ_B:
6298 CondOpc = LoongArch::XVSETALLNEZ_B;
6300 case LoongArch::PseudoXVBNZ_H:
6301 CondOpc = LoongArch::XVSETALLNEZ_H;
6303 case LoongArch::PseudoXVBNZ_W:
6304 CondOpc = LoongArch::XVSETALLNEZ_W;
6306 case LoongArch::PseudoXVBNZ_D:
6307 CondOpc = LoongArch::XVSETALLNEZ_D;
6322 F->insert(It, FalseBB);
6323 F->insert(It, TrueBB);
6324 F->insert(It, SinkBB);
6327 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
6331 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
6340 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6348 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6356 MI.getOperand(0).getReg())
6363 MI.eraseFromParent();
6371 unsigned BroadcastOp;
6373 switch (
MI.getOpcode()) {
6376 case LoongArch::PseudoXVINSGR2VR_B:
6378 BroadcastOp = LoongArch::XVREPLGR2VR_B;
6379 InsOp = LoongArch::XVEXTRINS_B;
6381 case LoongArch::PseudoXVINSGR2VR_H:
6383 BroadcastOp = LoongArch::XVREPLGR2VR_H;
6384 InsOp = LoongArch::XVEXTRINS_H;
6396 unsigned Idx =
MI.getOperand(3).getImm();
6398 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
6400 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
6401 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
6404 .
addReg(XSrc, 0, LoongArch::sub_128);
6406 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
6407 : LoongArch::VINSGR2VR_B),
6416 .
addImm(LoongArch::sub_128);
6418 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6419 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6423 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
6434 MI.eraseFromParent();
6441 assert(Subtarget.hasExtLSX());
6448 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6449 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6450 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
6454 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
6455 : LoongArch::VINSGR2VR_W),
6462 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
6466 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
6467 : LoongArch::VPICKVE2GR_W),
6472 MI.eraseFromParent();
6486 unsigned EleBits = 8;
6487 unsigned NotOpc = 0;
6490 switch (
MI.getOpcode()) {
6493 case LoongArch::PseudoVMSKLTZ_B:
6494 MskOpc = LoongArch::VMSKLTZ_B;
6496 case LoongArch::PseudoVMSKLTZ_H:
6497 MskOpc = LoongArch::VMSKLTZ_H;
6500 case LoongArch::PseudoVMSKLTZ_W:
6501 MskOpc = LoongArch::VMSKLTZ_W;
6504 case LoongArch::PseudoVMSKLTZ_D:
6505 MskOpc = LoongArch::VMSKLTZ_D;
6508 case LoongArch::PseudoVMSKGEZ_B:
6509 MskOpc = LoongArch::VMSKGEZ_B;
6511 case LoongArch::PseudoVMSKEQZ_B:
6512 MskOpc = LoongArch::VMSKNZ_B;
6513 NotOpc = LoongArch::VNOR_V;
6515 case LoongArch::PseudoVMSKNEZ_B:
6516 MskOpc = LoongArch::VMSKNZ_B;
6518 case LoongArch::PseudoXVMSKLTZ_B:
6519 MskOpc = LoongArch::XVMSKLTZ_B;
6520 RC = &LoongArch::LASX256RegClass;
6522 case LoongArch::PseudoXVMSKLTZ_H:
6523 MskOpc = LoongArch::XVMSKLTZ_H;
6524 RC = &LoongArch::LASX256RegClass;
6527 case LoongArch::PseudoXVMSKLTZ_W:
6528 MskOpc = LoongArch::XVMSKLTZ_W;
6529 RC = &LoongArch::LASX256RegClass;
6532 case LoongArch::PseudoXVMSKLTZ_D:
6533 MskOpc = LoongArch::XVMSKLTZ_D;
6534 RC = &LoongArch::LASX256RegClass;
6537 case LoongArch::PseudoXVMSKGEZ_B:
6538 MskOpc = LoongArch::XVMSKGEZ_B;
6539 RC = &LoongArch::LASX256RegClass;
6541 case LoongArch::PseudoXVMSKEQZ_B:
6542 MskOpc = LoongArch::XVMSKNZ_B;
6543 NotOpc = LoongArch::XVNOR_V;
6544 RC = &LoongArch::LASX256RegClass;
6546 case LoongArch::PseudoXVMSKNEZ_B:
6547 MskOpc = LoongArch::XVMSKNZ_B;
6548 RC = &LoongArch::LASX256RegClass;
6563 if (
TRI->getRegSizeInBits(*RC) > 128) {
6564 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6565 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6573 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
6574 : LoongArch::BSTRINS_W),
6578 .
addImm(256 / EleBits - 1)
6586 MI.eraseFromParent();
6593 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
6594 "Unexpected instruction");
6606 MI.eraseFromParent();
6613 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
6614 "Unexpected instruction");
6620 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
6630 MI.eraseFromParent();
6635 switch (
MI.getOpcode()) {
6638 case LoongArch::Select_GPR_Using_CC_GPR:
6674 if (
MI.getOperand(2).isReg())
6675 RHS =
MI.getOperand(2).getReg();
6676 auto CC =
static_cast<unsigned>(
MI.getOperand(3).getImm());
6680 SelectDests.
insert(
MI.getOperand(0).getReg());
6684 SequenceMBBI != E; ++SequenceMBBI) {
6685 if (SequenceMBBI->isDebugInstr())
6688 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
6689 !SequenceMBBI->getOperand(2).isReg() ||
6690 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
6691 SequenceMBBI->getOperand(3).getImm() != CC ||
6692 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
6693 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
6695 LastSelectPseudo = &*SequenceMBBI;
6697 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
6700 if (SequenceMBBI->hasUnmodeledSideEffects() ||
6701 SequenceMBBI->mayLoadOrStore() ||
6702 SequenceMBBI->usesCustomInsertionHook())
6705 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
6720 F->insert(
I, IfFalseMBB);
6721 F->insert(
I, TailMBB);
6724 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
6730 TailMBB->
push_back(DebugInstr->removeFromParent());
6734 TailMBB->
splice(TailMBB->
end(), HeadMBB,
6744 if (
MI.getOperand(2).isImm())
6756 auto SelectMBBI =
MI.getIterator();
6757 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
6759 while (SelectMBBI != SelectEnd) {
6760 auto Next = std::next(SelectMBBI);
6764 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
6765 .
addReg(SelectMBBI->getOperand(4).getReg())
6767 .
addReg(SelectMBBI->getOperand(5).getReg())
6774 F->getProperties().resetNoPHIs();
6783 switch (
MI.getOpcode()) {
6786 case LoongArch::DIV_W:
6787 case LoongArch::DIV_WU:
6788 case LoongArch::MOD_W:
6789 case LoongArch::MOD_WU:
6790 case LoongArch::DIV_D:
6791 case LoongArch::DIV_DU:
6792 case LoongArch::MOD_D:
6793 case LoongArch::MOD_DU:
6796 case LoongArch::WRFCSR: {
6798 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
6799 .
addReg(
MI.getOperand(1).getReg());
6800 MI.eraseFromParent();
6803 case LoongArch::RDFCSR: {
6806 MI.getOperand(0).getReg())
6807 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
6809 MI.eraseFromParent();
6812 case LoongArch::Select_GPR_Using_CC_GPR:
6814 case LoongArch::BuildPairF64Pseudo:
6816 case LoongArch::SplitPairF64Pseudo:
6818 case LoongArch::PseudoVBZ:
6819 case LoongArch::PseudoVBZ_B:
6820 case LoongArch::PseudoVBZ_H:
6821 case LoongArch::PseudoVBZ_W:
6822 case LoongArch::PseudoVBZ_D:
6823 case LoongArch::PseudoVBNZ:
6824 case LoongArch::PseudoVBNZ_B:
6825 case LoongArch::PseudoVBNZ_H:
6826 case LoongArch::PseudoVBNZ_W:
6827 case LoongArch::PseudoVBNZ_D:
6828 case LoongArch::PseudoXVBZ:
6829 case LoongArch::PseudoXVBZ_B:
6830 case LoongArch::PseudoXVBZ_H:
6831 case LoongArch::PseudoXVBZ_W:
6832 case LoongArch::PseudoXVBZ_D:
6833 case LoongArch::PseudoXVBNZ:
6834 case LoongArch::PseudoXVBNZ_B:
6835 case LoongArch::PseudoXVBNZ_H:
6836 case LoongArch::PseudoXVBNZ_W:
6837 case LoongArch::PseudoXVBNZ_D:
6839 case LoongArch::PseudoXVINSGR2VR_B:
6840 case LoongArch::PseudoXVINSGR2VR_H:
6842 case LoongArch::PseudoCTPOP:
6844 case LoongArch::PseudoVMSKLTZ_B:
6845 case LoongArch::PseudoVMSKLTZ_H:
6846 case LoongArch::PseudoVMSKLTZ_W:
6847 case LoongArch::PseudoVMSKLTZ_D:
6848 case LoongArch::PseudoVMSKGEZ_B:
6849 case LoongArch::PseudoVMSKEQZ_B:
6850 case LoongArch::PseudoVMSKNEZ_B:
6851 case LoongArch::PseudoXVMSKLTZ_B:
6852 case LoongArch::PseudoXVMSKLTZ_H:
6853 case LoongArch::PseudoXVMSKLTZ_W:
6854 case LoongArch::PseudoXVMSKLTZ_D:
6855 case LoongArch::PseudoXVMSKGEZ_B:
6856 case LoongArch::PseudoXVMSKEQZ_B:
6857 case LoongArch::PseudoXVMSKNEZ_B:
6859 case TargetOpcode::STATEPOINT:
6865 MI.addOperand(*
MI.getMF(),
6867 LoongArch::R1,
true,
6878 unsigned *
Fast)
const {
6879 if (!Subtarget.hasUAL())
6893#define NODE_NAME_CASE(node) \
6894 case LoongArchISD::node: \
6895 return "LoongArchISD::" #node;
6994#undef NODE_NAME_CASE
7007 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7008 LoongArch::R10, LoongArch::R11};
7012 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7013 LoongArch::F6, LoongArch::F7};
7016 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7017 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7020 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7021 LoongArch::VR6, LoongArch::VR7};
7024 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7025 LoongArch::XR6, LoongArch::XR7};
7031 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7033 unsigned GRLenInBytes = GRLen / 8;
7066 unsigned ValNo,
MVT ValVT,
7069 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7070 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7071 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7076 if (IsRet && ValNo > 1)
7080 bool UseGPRForFloat =
true;
7090 UseGPRForFloat = ArgFlags.
isVarArg();
7103 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7106 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7109 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7118 "PendingLocs and PendingArgFlags out of sync");
7122 UseGPRForFloat =
true;
7124 if (UseGPRForFloat && ValVT == MVT::f32) {
7127 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7130 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7133 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7175 PendingLocs.
size() <= 2) {
7176 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7181 PendingLocs.
clear();
7182 PendingArgFlags.
clear();
7189 unsigned StoreSizeBytes = GRLen / 8;
7192 if (ValVT == MVT::f32 && !UseGPRForFloat)
7194 else if (ValVT == MVT::f64 && !UseGPRForFloat)
7208 if (!PendingLocs.
empty()) {
7210 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7211 for (
auto &It : PendingLocs) {
7213 It.convertToReg(Reg);
7218 PendingLocs.clear();
7219 PendingArgFlags.
clear();
7222 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7223 "Expected an GRLenVT at this stage");
7240void LoongArchTargetLowering::analyzeInputArgs(
7243 LoongArchCCAssignFn Fn)
const {
7245 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7247 Type *ArgTy =
nullptr;
7249 ArgTy = FType->getReturnType();
7250 else if (Ins[i].isOrigArg())
7251 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7255 CCInfo, IsRet, ArgTy)) {
7256 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7263void LoongArchTargetLowering::analyzeOutputArgs(
7266 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7267 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7268 MVT ArgVT = Outs[i].VT;
7269 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7273 CCInfo, IsRet, OrigTy)) {
7274 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7315 if (In.isOrigArg()) {
7320 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
7321 (
BitWidth < 32 && In.Flags.isZExt())) {
7371 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7384 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7414 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
7418 LoongArch::R23, LoongArch::R24, LoongArch::R25,
7419 LoongArch::R26, LoongArch::R27, LoongArch::R28,
7420 LoongArch::R29, LoongArch::R30, LoongArch::R31};
7427 if (LocVT == MVT::f32) {
7430 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
7431 LoongArch::F26, LoongArch::F27};
7438 if (LocVT == MVT::f64) {
7441 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
7442 LoongArch::F30_64, LoongArch::F31_64};
7472 "GHC calling convention requires the F and D extensions");
7477 unsigned GRLenInBytes = Subtarget.
getGRLen() / 8;
7479 std::vector<SDValue> OutChains;
7488 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
7490 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
7507 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
7508 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
7509 assert(ArgPartOffset == 0);
7510 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
7512 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
7536 int VaArgOffset, VarArgsSaveSize;
7542 VarArgsSaveSize = 0;
7544 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() -
Idx);
7545 VaArgOffset = -VarArgsSaveSize;
7551 LoongArchFI->setVarArgsFrameIndex(FI);
7559 VarArgsSaveSize += GRLenInBytes;
7564 for (
unsigned I =
Idx;
I < ArgRegs.
size();
7565 ++
I, VaArgOffset += GRLenInBytes) {
7573 cast<StoreSDNode>(Store.getNode())
7575 ->setValue((
Value *)
nullptr);
7576 OutChains.push_back(Store);
7578 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
7583 if (!OutChains.empty()) {
7584 OutChains.push_back(Chain);
7599 if (
N->getNumValues() != 1)
7601 if (!
N->hasNUsesOfValue(1, 0))
7604 SDNode *Copy = *
N->user_begin();
7610 if (Copy->getGluedNode())
7614 bool HasRet =
false;
7615 for (
SDNode *Node : Copy->users()) {
7624 Chain = Copy->getOperand(0);
7629bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
7633 auto CalleeCC = CLI.CallConv;
7634 auto &Outs = CLI.Outs;
7636 auto CallerCC = Caller.getCallingConv();
7643 for (
auto &VA : ArgLocs)
7649 auto IsCallerStructRet = Caller.hasStructRetAttr();
7650 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
7651 if (IsCallerStructRet || IsCalleeStructRet)
7655 for (
auto &Arg : Outs)
7656 if (Arg.Flags.isByVal())
7661 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
7662 if (CalleeCC != CallerCC) {
7663 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
7664 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
7702 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
7706 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
7712 "site marked musttail");
7719 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7721 if (!Flags.isByVal())
7725 unsigned Size = Flags.getByValSize();
7726 Align Alignment = Flags.getNonZeroByValAlign();
7733 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
7735 false,
nullptr, std::nullopt,
7747 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
7750 SDValue ArgValue = OutVals[OutIdx];
7759 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
7771 if (!StackPtr.getNode())
7783 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
7798 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
7799 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
7800 assert(ArgPartOffset == 0);
7805 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
7806 SDValue PartValue = OutVals[OutIdx + 1];
7807 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
7818 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
7822 for (
const auto &Part : Parts) {
7823 SDValue PartValue = Part.first;
7824 SDValue PartOffset = Part.second;
7831 ArgValue = SpillSlot;
7837 if (Flags.isByVal())
7838 ArgValue = ByValArgs[j++];
7845 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
7846 "for passing parameters");
7849 if (!StackPtr.getNode())
7862 if (!MemOpChains.
empty())
7868 for (
auto &Reg : RegsToPass) {
7869 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
7896 for (
auto &Reg : RegsToPass)
7902 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
7903 assert(Mask &&
"Missing call preserved mask for calling convention");
7921 assert(Subtarget.
is64Bit() &&
"Medium code model requires LA64");
7925 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
7948 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
7951 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
7952 auto &VA = RVLocs[i];
7960 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
7961 assert(VA.needsCustom());
7967 RetValue, RetValue2);
7984 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7988 Outs[i].Flags, CCInfo,
true,
nullptr))
8014 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8015 SDValue Val = OutVals[OutIdx];
8024 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8028 Register RegHi = RVLocs[++i].getLocReg();
8058 if (!Subtarget.hasExtLSX())
8061 if (VT == MVT::f32) {
8062 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8063 return (masked == 0x3e000000 || masked == 0x40000000);
8066 if (VT == MVT::f64) {
8067 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8068 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8074bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8075 bool ForCodeSize)
const {
8077 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8079 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8081 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8092bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8095 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
8097 if (isa<LoadInst>(
I))
8102 Type *Ty =
I->getOperand(0)->getType();
8121 return Y.getValueType().isScalarInteger() && !isa<ConstantSDNode>(
Y);
8127 unsigned Intrinsic)
const {
8128 switch (Intrinsic) {
8131 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8132 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8133 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8134 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8136 Info.memVT = MVT::i32;
8137 Info.ptrVal =
I.getArgOperand(0);
8156 "Unable to expand");
8157 unsigned MinWordSize = 4;
8170 Intrinsic::ptrmask, {PtrTy, IntTy},
8171 {
Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8175 Value *PtrLSB = Builder.
CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8177 ShiftAmt = Builder.
CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8179 ConstantInt::get(WordType,
8183 Value *ValOperand_Shifted =
8185 ShiftAmt,
"ValOperand_Shifted");
8188 NewOperand = Builder.
CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8190 NewOperand = ValOperand_Shifted;
8216 if (Subtarget.hasLAM_BH() && Subtarget.
is64Bit() &&
8224 if (Subtarget.hasLAMCAS()) {
8246 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
8248 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
8250 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
8252 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
8254 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
8256 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
8258 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
8260 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
8270 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
8272 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
8274 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
8276 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
8278 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
8280 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
8282 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
8284 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
8296 if (Subtarget.hasLAMCAS())
8308 unsigned GRLen = Subtarget.
getGRLen();
8310 Value *FailureOrdering =
8312 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
8314 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
8321 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
8346 unsigned GRLen = Subtarget.
getGRLen();
8375 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
8378 Builder.
CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
8405 const Constant *PersonalityFn)
const {
8406 return LoongArch::R4;
8410 const Constant *PersonalityFn)
const {
8411 return LoongArch::R5;
8422 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
8423 return RefinementSteps;
8428 int &RefinementSteps,
8429 bool &UseOneConstNR,
8430 bool Reciprocal)
const {
8431 if (Subtarget.hasFrecipe()) {
8435 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8436 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8437 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8438 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8439 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8458 int &RefinementSteps)
const {
8459 if (Subtarget.hasFrecipe()) {
8463 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8464 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8465 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8466 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8467 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8484LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
8504 if (Constraint.
size() == 1) {
8505 switch (Constraint[0]) {
8521 if (Constraint ==
"ZC" || Constraint ==
"ZB")
8537std::pair<unsigned, const TargetRegisterClass *>
8538LoongArchTargetLowering::getRegForInlineAsmConstraint(
8542 if (Constraint.
size() == 1) {
8543 switch (Constraint[0]) {
8548 return std::make_pair(0U, &LoongArch::GPRRegClass);
8550 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
8552 if (Subtarget.hasBasicF() && VT == MVT::f32)
8553 return std::make_pair(0U, &LoongArch::FPR32RegClass);
8554 if (Subtarget.hasBasicD() && VT == MVT::f64)
8555 return std::make_pair(0U, &LoongArch::FPR64RegClass);
8556 if (Subtarget.hasExtLSX() &&
8557 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
8558 return std::make_pair(0U, &LoongArch::LSX128RegClass);
8559 if (Subtarget.hasExtLASX() &&
8560 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
8561 return std::make_pair(0U, &LoongArch::LASX256RegClass);
8581 bool IsFP = Constraint[2] ==
'f';
8582 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
8583 std::pair<unsigned, const TargetRegisterClass *>
R;
8585 TRI, join_items(
"", Temp.first, Temp.second), VT);
8588 unsigned RegNo =
R.first;
8589 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
8590 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
8591 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
8592 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
8602void LoongArchTargetLowering::LowerAsmOperandForConstraint(
8606 if (Constraint.
size() == 1) {
8607 switch (Constraint[0]) {
8610 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8612 if (isInt<16>(CVal))
8619 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8621 if (isInt<12>(CVal))
8628 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op))
8629 if (
C->getZExtValue() == 0)
8635 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8637 if (isUInt<12>(CVal))
8649#define GET_REGISTER_MATCHER
8650#include "LoongArchGenAsmMatcher.inc"
8656 std::string NewRegName =
Name.second.str();
8663 if (!ReservedRegs.
test(Reg))
8679 if (
auto *ConstNode = dyn_cast<ConstantSDNode>(
C.getNode())) {
8680 const APInt &Imm = ConstNode->getAPIntValue();
8682 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
8683 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
8686 if (ConstNode->hasOneUse() &&
8687 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
8688 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
8694 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
8695 unsigned Shifts = Imm.countr_zero();
8701 APInt ImmPop = Imm.ashr(Shifts);
8702 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
8706 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
8707 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
8708 (ImmSmall - Imm).isPowerOf2())
8718 Type *Ty,
unsigned AS,
8734 !(isShiftedInt<14, 2>(AM.
BaseOffs) && Subtarget.hasUAL()))
8761 return isInt<12>(Imm);
8765 return isInt<12>(Imm);
8772 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
8773 EVT MemVT = LD->getMemoryVT();
8774 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
8785 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
8794 if (
Y.getValueType().isVector())
8797 return !isa<ConstantSDNode>(
Y);
8806 Type *Ty,
bool IsSigned)
const {
8827 Align &PrefAlign)
const {
8828 if (!isa<MemIntrinsic>(CI))
8833 PrefAlign =
Align(8);
8836 PrefAlign =
Align(4);
8851bool LoongArchTargetLowering::splitValueIntoRegisterParts(
8853 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
8854 bool IsABIRegCopy = CC.has_value();
8857 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
8858 PartVT == MVT::f32) {
8873SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
8875 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
8876 bool IsABIRegCopy = CC.has_value();
8878 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
8879 PartVT == MVT::f32) {
8892MVT LoongArchTargetLowering::getRegisterTypeForCallingConv(
LLVMContext &Context,
8896 if (VT == MVT::f16 && Subtarget.hasBasicF())
8902unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
8905 if (VT == MVT::f16 && Subtarget.hasBasicF())
8914 unsigned Depth)
const {
8915 EVT VT =
Op.getValueType();
8917 unsigned Opc =
Op.getOpcode();
8924 MVT SrcVT = Src.getSimpleValueType();
8929 if (OriginalDemandedBits.
countr_zero() >= NumElts)
8933 APInt KnownUndef, KnownZero;
8949 if (KnownSrc.
One[SrcBits - 1])
8951 else if (KnownSrc.
Zero[SrcBits - 1])
8956 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
8963 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
#define NODE_NAME_CASE(node)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
Analysis containing CSE Info
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)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
const HexagonInstrInfo * TII
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static 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)
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 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 MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static 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 SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void 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.
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VSHUF.
static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode)
Register const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool 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,...
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.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to 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.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
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,...
SmallVectorImpl< ISD::ArgFlagsTy > & getPendingArgFlags()
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
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.
SmallVectorImpl< CCValAssign > & getPendingLocs()
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
void addLoc(const CCValAssign &V)
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
This class represents a function call, abstracting a target machine's calling convention.
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.
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Argument * getArg(unsigned i) const
Common base class shared among various IRBuilders.
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
This class is used to represent ISD::LOAD nodes.
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void addSExt32Register(Register Reg)
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getMaxBytesForAlignment() const
Align getPrefFunctionAlignment() const
unsigned getGRLen() const
Align getPrefLoopAlignment() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y —> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
EVT getMemoryVT() const
Return the type of the in-memory value.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
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.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
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
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "look through" ops that don't contri...
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.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI unsigned getIntegerBitWidth() const
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.
bool hasOneUse() const
Return true if there is exactly one use 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 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.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
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.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
AtomicOrdering
Atomic ordering for LLVM's memory model.
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Align getNonZeroOrigAlign() const
Register getFrameRegister(const MachineFunction &MF) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)