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}) {
350 if (Subtarget.hasExtLASX()) {
351 for (
MVT VT : LASXVTs) {
366 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
384 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
386 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
388 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
392 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
414 if (Subtarget.hasExtLSX()) {
439 if (Subtarget.hasLAMCAS())
442 if (Subtarget.hasSCQ()) {
459 switch (
Op.getOpcode()) {
461 return lowerATOMIC_FENCE(
Op, DAG);
463 return lowerEH_DWARF_CFA(
Op, DAG);
465 return lowerGlobalAddress(
Op, DAG);
467 return lowerGlobalTLSAddress(
Op, DAG);
469 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
471 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
473 return lowerINTRINSIC_VOID(
Op, DAG);
475 return lowerBlockAddress(
Op, DAG);
477 return lowerJumpTable(
Op, DAG);
479 return lowerShiftLeftParts(
Op, DAG);
481 return lowerShiftRightParts(
Op, DAG,
true);
483 return lowerShiftRightParts(
Op, DAG,
false);
485 return lowerConstantPool(
Op, DAG);
487 return lowerFP_TO_SINT(
Op, DAG);
489 return lowerBITCAST(
Op, DAG);
491 return lowerUINT_TO_FP(
Op, DAG);
493 return lowerSINT_TO_FP(
Op, DAG);
495 return lowerVASTART(
Op, DAG);
497 return lowerFRAMEADDR(
Op, DAG);
499 return lowerRETURNADDR(
Op, DAG);
501 return lowerWRITE_REGISTER(
Op, DAG);
503 return lowerINSERT_VECTOR_ELT(
Op, DAG);
505 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
507 return lowerBUILD_VECTOR(
Op, DAG);
509 return lowerCONCAT_VECTORS(
Op, DAG);
511 return lowerVECTOR_SHUFFLE(
Op, DAG);
513 return lowerBITREVERSE(
Op, DAG);
515 return lowerSCALAR_TO_VECTOR(
Op, DAG);
517 return lowerPREFETCH(
Op, DAG);
519 return lowerSELECT(
Op, DAG);
521 return lowerBRCOND(
Op, DAG);
523 return lowerFP_TO_FP16(
Op, DAG);
525 return lowerFP16_TO_FP(
Op, DAG);
527 return lowerFP_TO_BF16(
Op, DAG);
529 return lowerBF16_TO_FP(
Op, DAG);
531 return lowerVECREDUCE_ADD(
Op, DAG);
548 MVT OpVT =
Op.getSimpleValueType();
554 unsigned LegalVecSize = 128;
555 bool isLASX256Vector =
565 if (isLASX256Vector) {
570 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
576 if (isLASX256Vector) {
588 unsigned IsData =
Op.getConstantOperandVal(4);
593 return Op.getOperand(0);
608 if (
LHS == LHS2 &&
RHS == RHS2) {
613 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
629 MVT VT =
N->getSimpleValueType(0);
657 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
660 if (~TrueVal == FalseVal) {
700 unsigned SelOpNo = 0;
710 unsigned ConstSelOpNo = 1;
711 unsigned OtherSelOpNo = 2;
712 if (!isa<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
717 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
718 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
722 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
723 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
729 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
731 std::swap(NewConstOps[0], NewConstOps[1]);
743 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
745 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
748 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
749 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
763 isa<ConstantSDNode>(
LHS.getOperand(1))) {
769 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
782 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
783 int64_t
C = RHSC->getSExtValue();
826 MVT VT =
Op.getSimpleValueType();
832 if (
Op.hasOneUse()) {
833 unsigned UseOpc =
Op->user_begin()->getOpcode();
842 return lowerSELECT(NewSel, DAG);
857 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
878 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
882 if (TrueVal - 1 == FalseVal)
884 if (TrueVal + 1 == FalseVal)
891 RHS == TrueV && LHS == FalseV) {
908 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
935 Op.getOperand(0), LHS, RHS, TargetCC,
939 Op.getOperand(0), CondV,
Op.getOperand(2));
949LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
952 MVT OpVT =
Op.getSimpleValueType();
963 EVT ResTy =
Op->getValueType(0);
974 for (
unsigned int i = 0; i < NewEltNum; i++) {
977 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
996 for (
unsigned int i = 0; i < NewEltNum; i++)
997 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
998 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1016 if (EltBits > 32 || EltBits == 1)
1044 int MaskOffset,
const APInt &Zeroable) {
1045 int Size = Mask.size();
1046 unsigned SizeInBits =
Size * ScalarSizeInBits;
1048 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1049 for (
int i = 0; i <
Size; i += Scale)
1050 for (
int j = 0; j < Shift; ++j)
1051 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1059 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1060 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1065 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1066 for (
int i = 0; i !=
Size; i += Scale) {
1067 unsigned Pos =
Left ? i + Shift : i;
1068 unsigned Low =
Left ? i : i + Shift;
1069 unsigned Len = Scale - Shift;
1074 int ShiftEltBits = ScalarSizeInBits * Scale;
1075 bool ByteShift = ShiftEltBits > 64;
1078 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1082 Scale = ByteShift ? Scale / 2 : Scale;
1088 return (
int)ShiftAmt;
1091 unsigned MaxWidth = 128;
1092 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1093 for (
int Shift = 1; Shift != Scale; ++Shift)
1094 for (
bool Left : {
true,
false})
1095 if (CheckZeros(Shift, Scale,
Left)) {
1096 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1120 const APInt &Zeroable) {
1121 int Size = Mask.size();
1135 Mask,
Size, Zeroable);
1143 "Illegal integer vector type");
1152template <
typename ValType>
1155 unsigned CheckStride,
1157 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1161 if (*
I != -1 && *
I != ExpectedIndex)
1163 ExpectedIndex += ExpectedIndexStride;
1167 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1179 int Size = Mask.size();
1189 int ScalarSizeInBits = VectorSizeInBits /
Size;
1190 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1191 (void)ScalarSizeInBits;
1193 for (
int i = 0; i <
Size; ++i) {
1199 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1216 RepeatedMask.
assign(LaneSize, -1);
1217 int Size = Mask.size();
1218 for (
int i = 0; i <
Size; ++i) {
1219 assert(Mask[i] == -1 || Mask[i] >= 0);
1222 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1229 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1230 if (RepeatedMask[i % LaneSize] < 0)
1232 RepeatedMask[i % LaneSize] = LocalM;
1233 else if (RepeatedMask[i % LaneSize] != LocalM)
1250 int NumElts = RepeatedMask.
size();
1252 int Scale = 16 / NumElts;
1254 for (
int i = 0; i < NumElts; ++i) {
1255 int M = RepeatedMask[i];
1256 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1257 "Unexpected mask index.");
1262 int StartIdx = i - (M % NumElts);
1269 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1272 Rotation = CandidateRotation;
1273 else if (Rotation != CandidateRotation)
1277 SDValue MaskV = M < NumElts ? V1 : V2;
1288 else if (TargetV != MaskV)
1293 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1294 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1303 return Rotation * Scale;
1322 if (ByteRotation <= 0)
1329 int LoByteShift = 16 - ByteRotation;
1330 int HiByteShift = ByteRotation;
1352 const APInt &Zeroable) {
1366 for (
int i = 0; i < NumElements; i++) {
1370 if (i % Scale != 0) {
1381 SDValue V = M < NumElements ? V1 : V2;
1382 M = M % NumElements;
1385 Offset = M - (i / Scale);
1388 if (
Offset % (NumElements / Scale))
1390 }
else if (InputV != V)
1393 if (M != (
Offset + (i / Scale)))
1404 if (
Offset >= (NumElements / 2)) {
1406 Offset -= (NumElements / 2);
1413 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1417 }
while (Scale > 1);
1423 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1424 NumExtElements *= 2) {
1443 int SplatIndex = -1;
1444 for (
const auto &M : Mask) {
1451 if (SplatIndex == -1)
1454 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1455 if (fitsRegularPattern<int>(Mask.begin(), 1, Mask.end(), SplatIndex, 0)) {
1456 APInt Imm(64, SplatIndex);
1486 unsigned SubVecSize = 4;
1487 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1490 int SubMask[4] = {-1, -1, -1, -1};
1491 for (
unsigned i = 0; i < SubVecSize; ++i) {
1492 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1498 M -= 4 * (j / SubVecSize);
1499 if (M < 0 || M >= 4)
1505 if (SubMask[i] == -1)
1509 else if (M != -1 && M != SubMask[i])
1516 for (
int i = SubVecSize - 1; i >= 0; --i) {
1527 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1554 const auto &Begin = Mask.begin();
1555 const auto &
End = Mask.end();
1556 SDValue OriV1 = V1, OriV2 = V2;
1558 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 2))
1560 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 2))
1565 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 2))
1567 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 2))
1594 const auto &Begin = Mask.begin();
1595 const auto &
End = Mask.end();
1596 SDValue OriV1 = V1, OriV2 = V2;
1598 if (fitsRegularPattern<int>(Begin, 2,
End, 1, 2))
1600 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + 1, 2))
1605 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 1, 2))
1607 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + 1, 2))
1635 const auto &Begin = Mask.begin();
1636 const auto &
End = Mask.end();
1637 unsigned HalfSize = Mask.size() / 2;
1638 SDValue OriV1 = V1, OriV2 = V2;
1640 if (fitsRegularPattern<int>(Begin, 2,
End, HalfSize, 1))
1642 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + HalfSize, 1))
1647 if (fitsRegularPattern<int>(Begin + 1, 2,
End, HalfSize, 1))
1649 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + HalfSize,
1678 const auto &Begin = Mask.begin();
1679 const auto &
End = Mask.end();
1680 SDValue OriV1 = V1, OriV2 = V2;
1682 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 1))
1684 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 1))
1689 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 1))
1691 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 1))
1718 const auto &Begin = Mask.begin();
1719 const auto &Mid = Mask.begin() + Mask.size() / 2;
1720 const auto &
End = Mask.end();
1721 SDValue OriV1 = V1, OriV2 = V2;
1723 if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
1725 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size(), 2))
1730 if (fitsRegularPattern<int>(Mid, 1,
End, 0, 2))
1732 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size(), 2))
1760 const auto &Begin = Mask.begin();
1761 const auto &Mid = Mask.begin() + Mask.size() / 2;
1762 const auto &
End = Mask.end();
1763 SDValue OriV1 = V1, OriV2 = V2;
1765 if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
1767 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size() + 1, 2))
1772 if (fitsRegularPattern<int>(Mid, 1,
End, 1, 2))
1774 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size() + 1, 2))
1816 "Vector type is unsupported for lsx!");
1818 "Two operands have different types!");
1820 "Unexpected mask size for shuffle!");
1821 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
1823 APInt KnownUndef, KnownZero;
1825 APInt Zeroable = KnownUndef | KnownZero;
1884 int SplatIndex = -1;
1885 for (
const auto &M : Mask) {
1892 if (SplatIndex == -1)
1895 const auto &Begin = Mask.begin();
1896 const auto &
End = Mask.end();
1897 unsigned HalfSize = Mask.size() / 2;
1899 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1900 if (fitsRegularPattern<int>(Begin, 1,
End - HalfSize, SplatIndex, 0) &&
1901 fitsRegularPattern<int>(Begin + HalfSize, 1,
End, SplatIndex + HalfSize,
1903 APInt Imm(64, SplatIndex);
1917 if (Mask.size() <= 4)
1941 const auto &Begin = Mask.begin();
1942 const auto &
End = Mask.end();
1943 unsigned HalfSize = Mask.size() / 2;
1944 unsigned LeftSize = HalfSize / 2;
1945 SDValue OriV1 = V1, OriV2 = V2;
1947 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, HalfSize - LeftSize,
1949 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize + LeftSize, 1))
1951 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize,
1952 Mask.size() + HalfSize - LeftSize, 1) &&
1953 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
1954 Mask.size() + HalfSize + LeftSize, 1))
1959 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, HalfSize - LeftSize,
1961 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize + LeftSize,
1964 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize,
1965 Mask.size() + HalfSize - LeftSize, 1) &&
1966 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
1967 Mask.size() + HalfSize + LeftSize, 1))
1980 const auto &Begin = Mask.begin();
1981 const auto &
End = Mask.end();
1982 unsigned HalfSize = Mask.size() / 2;
1983 SDValue OriV1 = V1, OriV2 = V2;
1985 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, 0, 1) &&
1986 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize, 1))
1988 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, Mask.size(), 1) &&
1989 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
1990 Mask.size() + HalfSize, 1))
1995 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, 0, 1) &&
1996 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize, 1))
1998 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, Mask.size(),
2000 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
2001 Mask.size() + HalfSize, 1))
2014 const auto &Begin = Mask.begin();
2015 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2016 const auto &Mid = Mask.begin() + Mask.size() / 2;
2017 const auto &RightMid = Mask.end() - Mask.size() / 4;
2018 const auto &
End = Mask.end();
2019 unsigned HalfSize = Mask.size() / 2;
2020 SDValue OriV1 = V1, OriV2 = V2;
2022 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 0, 2) &&
2023 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize, 2))
2025 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size(), 2) &&
2026 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize, 2))
2031 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 0, 2) &&
2032 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize, 2))
2034 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size(), 2) &&
2035 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize, 2))
2049 const auto &Begin = Mask.begin();
2050 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2051 const auto &Mid = Mask.begin() + Mask.size() / 2;
2052 const auto &RightMid = Mask.end() - Mask.size() / 4;
2053 const auto &
End = Mask.end();
2054 unsigned HalfSize = Mask.size() / 2;
2055 SDValue OriV1 = V1, OriV2 = V2;
2057 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 1, 2) &&
2058 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize + 1, 2))
2060 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size() + 1, 2) &&
2061 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize + 1,
2067 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 1, 2) &&
2068 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize + 1, 2))
2070 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size() + 1, 2) &&
2071 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize + 1,
2085 int MaskSize = Mask.size();
2086 int HalfSize = Mask.size() / 2;
2087 const auto &Begin = Mask.begin();
2088 const auto &Mid = Mask.begin() + HalfSize;
2089 const auto &
End = Mask.end();
2101 for (
auto it = Begin; it < Mid; it++) {
2104 else if ((*it >= 0 && *it < HalfSize) ||
2105 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2106 int M = *it < HalfSize ? *it : *it - HalfSize;
2111 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2113 for (
auto it = Mid; it <
End; it++) {
2116 else if ((*it >= HalfSize && *it < MaskSize) ||
2117 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2118 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2123 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2154 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2156 int MaskSize = Mask.size();
2157 int HalfSize = Mask.size() / 2;
2159 HalfMaskType preMask =
None, postMask =
None;
2161 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2162 return M < 0 || (M >= 0 && M < HalfSize) ||
2163 (M >= MaskSize && M < MaskSize + HalfSize);
2165 preMask = HighLaneTy;
2166 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2167 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2168 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2170 preMask = LowLaneTy;
2172 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2173 return M < 0 || (M >= 0 && M < HalfSize) ||
2174 (M >= MaskSize && M < MaskSize + HalfSize);
2176 postMask = HighLaneTy;
2177 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2178 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2179 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2181 postMask = LowLaneTy;
2189 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2192 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2205 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2206 *it = *it < 0 ? *it : *it - HalfSize;
2208 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2209 *it = *it < 0 ? *it : *it + HalfSize;
2211 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2224 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2225 *it = *it < 0 ? *it : *it - HalfSize;
2227 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2240 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2241 *it = *it < 0 ? *it : *it + HalfSize;
2264 int Size = Mask.size();
2265 int LaneSize =
Size / 2;
2267 bool LaneCrossing[2] = {
false,
false};
2268 for (
int i = 0; i <
Size; ++i)
2269 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2270 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2273 if (!LaneCrossing[0] && !LaneCrossing[1])
2277 InLaneMask.
assign(Mask.begin(), Mask.end());
2278 for (
int i = 0; i <
Size; ++i) {
2279 int &M = InLaneMask[i];
2282 if (((M %
Size) / LaneSize) != (i / LaneSize))
2283 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2288 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2302 "Vector type is unsupported for lasx!");
2304 "Two operands have different types!");
2306 "Unexpected mask size for shuffle!");
2307 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2308 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2314 APInt KnownUndef, KnownZero;
2316 APInt Zeroable = KnownUndef | KnownZero;
2367 MVT VT =
Op.getSimpleValueType();
2371 bool V1IsUndef = V1.
isUndef();
2372 bool V2IsUndef = V2.
isUndef();
2373 if (V1IsUndef && V2IsUndef)
2386 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2388 for (
int &M : NewMask)
2389 if (M >= NumElements)
2395 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2396 (void)MaskUpperLimit;
2398 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2399 "Out of bounds shuffle index");
2416 MakeLibCallOptions CallOptions;
2421 std::tie(Res, Chain) =
2422 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2433 MakeLibCallOptions CallOptions;
2440 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2441 CallOptions,
DL, Chain);
2447 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2449 MakeLibCallOptions CallOptions;
2453 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2461 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2462 MVT VT =
Op.getSimpleValueType();
2488 "Unsupported vector type for broadcast.");
2491 bool IsIdeneity =
true;
2493 for (
int i = 0; i != NumOps; i++) {
2495 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2507 auto *LN = cast<LoadSDNode>(IdentitySrc);
2510 ? DAG.
getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other)
2512 SDValue Ops[] = {LN->getChain(), LN->getBasePtr(), LN->getOffset()};
2523 EVT ResTy =
Op->getValueType(0);
2526 APInt SplatValue, SplatUndef;
2527 unsigned SplatBitSize;
2530 bool UseSameConstant =
true;
2535 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
2536 (!Subtarget.hasExtLASX() || !Is256Vec))
2542 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
2544 SplatBitSize <= 64) {
2546 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2552 switch (SplatBitSize) {
2556 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
2559 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
2562 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
2565 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
2573 if (ViaVecTy != ResTy)
2582 for (
unsigned i = 0; i < NumElts; ++i) {
2587 ConstantValue = Opi;
2588 else if (ConstantValue != Opi)
2589 UseSameConstant =
false;
2594 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
2596 for (
unsigned i = 0; i < NumElts; ++i) {
2616 for (
unsigned i = 1; i < NumElts; ++i) {
2632 MVT ResVT =
Op.getSimpleValueType();
2636 unsigned NumFreezeUndef = 0;
2637 unsigned NumZero = 0;
2638 unsigned NumNonZero = 0;
2639 unsigned NonZeros = 0;
2641 for (
unsigned i = 0; i != NumOperands; ++i) {
2656 assert(i <
sizeof(NonZeros) * CHAR_BIT);
2663 if (NumNonZero > 2) {
2667 Ops.
slice(0, NumOperands / 2));
2669 Ops.
slice(NumOperands / 2));
2682 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
2684 for (
unsigned i = 0; i != NumOperands; ++i) {
2685 if ((NonZeros & (1 << i)) == 0)
2696LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
2698 EVT VecTy =
Op->getOperand(0)->getValueType(0);
2702 if (isa<ConstantSDNode>(
Idx) &&
Idx->getAsZExtVal() < NumElts)
2709LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
2711 MVT VT =
Op.getSimpleValueType();
2720 if (isa<ConstantSDNode>(Op2))
2733 for (
unsigned i = 0; i < NumElts; ++i)
2764 if (Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
2766 "On LA64, only 64-bit registers can be written.");
2767 return Op.getOperand(0);
2770 if (!Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
2772 "On LA32, only 32-bit registers can be written.");
2773 return Op.getOperand(0);
2781 if (!isa<ConstantSDNode>(
Op.getOperand(0))) {
2783 "be a constant integer");
2790 EVT VT =
Op.getValueType();
2793 unsigned Depth =
Op.getConstantOperandVal(0);
2794 int GRLenInBytes = Subtarget.
getGRLen() / 8;
2797 int Offset = -(GRLenInBytes * 2);
2809 if (
Op.getConstantOperandVal(0) != 0) {
2811 "return address can only be determined for the current frame");
2845 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
2853 !Subtarget.hasBasicD() &&
"unexpected target features");
2858 auto *
C = dyn_cast<ConstantSDNode>(Op0.
getOperand(1));
2859 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
2869 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLT(MVT::i32))
2873 EVT RetVT =
Op.getValueType();
2875 MakeLibCallOptions CallOptions;
2876 CallOptions.setTypeListBeforeSoften(OpVT, RetVT);
2879 std::tie(Result, Chain) =
2887 !Subtarget.hasBasicD() &&
"unexpected target features");
2894 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLE(MVT::i32))
2898 EVT RetVT =
Op.getValueType();
2900 MakeLibCallOptions CallOptions;
2901 CallOptions.setTypeListBeforeSoften(OpVT, RetVT);
2904 std::tie(Result, Chain) =
2913 EVT VT =
Op.getValueType();
2917 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
2918 Subtarget.
is64Bit() && Subtarget.hasBasicF()) {
2922 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit()) {
2939 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
2940 !Subtarget.hasBasicD()) {
2964 N->getOffset(), Flags);
2972template <
class NodeTy>
2975 bool IsLocal)
const {
2986 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
3038 return getAddr(cast<BlockAddressSDNode>(
Op), DAG,
3044 return getAddr(cast<JumpTableSDNode>(
Op), DAG,
3050 return getAddr(cast<ConstantPoolSDNode>(
Op), DAG,
3057 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3061 if (GV->
isDSOLocal() && isa<GlobalVariable>(GV)) {
3062 if (
auto GCM = dyn_cast<GlobalVariable>(GV)->
getCodeModel())
3071 unsigned Opc,
bool UseGOT,
3089 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3127 Args.emplace_back(Load, CallTy);
3159LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3166 assert((!Large || Subtarget.
is64Bit()) &&
"Large code model requires LA64");
3169 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3182 return getDynamicTLSAddr(
N, DAG,
3183 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3184 : LoongArch::PseudoLA_TLS_GD,
3191 return getDynamicTLSAddr(
N, DAG,
3192 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3193 : LoongArch::PseudoLA_TLS_LD,
3198 return getStaticTLSAddr(
N, DAG,
3199 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3200 : LoongArch::PseudoLA_TLS_IE,
3207 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3211 return getTLSDescAddr(
N, DAG,
3212 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3213 : LoongArch::PseudoLA_TLS_DESC,
3217template <
unsigned N>
3220 auto *CImm = cast<ConstantSDNode>(
Op->getOperand(ImmOp));
3222 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
3223 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
3225 ": argument out of range.");
3232LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3234 switch (
Op.getConstantOperandVal(0)) {
3237 case Intrinsic::thread_pointer: {
3241 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3242 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3243 case Intrinsic::loongarch_lsx_vreplvei_d:
3244 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3245 return checkIntrinsicImmArg<1>(
Op, 2, DAG);
3246 case Intrinsic::loongarch_lsx_vreplvei_w:
3247 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3248 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3249 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3250 case Intrinsic::loongarch_lasx_xvpickve_d:
3251 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3252 return checkIntrinsicImmArg<2>(
Op, 2, DAG);
3253 case Intrinsic::loongarch_lasx_xvinsve0_d:
3254 return checkIntrinsicImmArg<2>(
Op, 3, DAG);
3255 case Intrinsic::loongarch_lsx_vsat_b:
3256 case Intrinsic::loongarch_lsx_vsat_bu:
3257 case Intrinsic::loongarch_lsx_vrotri_b:
3258 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3259 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3260 case Intrinsic::loongarch_lsx_vsrlri_b:
3261 case Intrinsic::loongarch_lsx_vsrari_b:
3262 case Intrinsic::loongarch_lsx_vreplvei_h:
3263 case Intrinsic::loongarch_lasx_xvsat_b:
3264 case Intrinsic::loongarch_lasx_xvsat_bu:
3265 case Intrinsic::loongarch_lasx_xvrotri_b:
3266 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3267 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3268 case Intrinsic::loongarch_lasx_xvsrlri_b:
3269 case Intrinsic::loongarch_lasx_xvsrari_b:
3270 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3271 case Intrinsic::loongarch_lasx_xvpickve_w:
3272 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3273 return checkIntrinsicImmArg<3>(
Op, 2, DAG);
3274 case Intrinsic::loongarch_lasx_xvinsve0_w:
3275 return checkIntrinsicImmArg<3>(
Op, 3, DAG);
3276 case Intrinsic::loongarch_lsx_vsat_h:
3277 case Intrinsic::loongarch_lsx_vsat_hu:
3278 case Intrinsic::loongarch_lsx_vrotri_h:
3279 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3280 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3281 case Intrinsic::loongarch_lsx_vsrlri_h:
3282 case Intrinsic::loongarch_lsx_vsrari_h:
3283 case Intrinsic::loongarch_lsx_vreplvei_b:
3284 case Intrinsic::loongarch_lasx_xvsat_h:
3285 case Intrinsic::loongarch_lasx_xvsat_hu:
3286 case Intrinsic::loongarch_lasx_xvrotri_h:
3287 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3288 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3289 case Intrinsic::loongarch_lasx_xvsrlri_h:
3290 case Intrinsic::loongarch_lasx_xvsrari_h:
3291 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3292 return checkIntrinsicImmArg<4>(
Op, 2, DAG);
3293 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3294 case Intrinsic::loongarch_lsx_vsrani_b_h:
3295 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3296 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3297 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3298 case Intrinsic::loongarch_lsx_vssrani_b_h:
3299 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3300 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3301 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3302 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3303 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3304 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3305 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3306 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3307 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3308 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3309 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3310 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3311 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3312 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3313 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3314 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3315 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3316 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3317 return checkIntrinsicImmArg<4>(
Op, 3, DAG);
3318 case Intrinsic::loongarch_lsx_vsat_w:
3319 case Intrinsic::loongarch_lsx_vsat_wu:
3320 case Intrinsic::loongarch_lsx_vrotri_w:
3321 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3322 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3323 case Intrinsic::loongarch_lsx_vsrlri_w:
3324 case Intrinsic::loongarch_lsx_vsrari_w:
3325 case Intrinsic::loongarch_lsx_vslei_bu:
3326 case Intrinsic::loongarch_lsx_vslei_hu:
3327 case Intrinsic::loongarch_lsx_vslei_wu:
3328 case Intrinsic::loongarch_lsx_vslei_du:
3329 case Intrinsic::loongarch_lsx_vslti_bu:
3330 case Intrinsic::loongarch_lsx_vslti_hu:
3331 case Intrinsic::loongarch_lsx_vslti_wu:
3332 case Intrinsic::loongarch_lsx_vslti_du:
3333 case Intrinsic::loongarch_lsx_vbsll_v:
3334 case Intrinsic::loongarch_lsx_vbsrl_v:
3335 case Intrinsic::loongarch_lasx_xvsat_w:
3336 case Intrinsic::loongarch_lasx_xvsat_wu:
3337 case Intrinsic::loongarch_lasx_xvrotri_w:
3338 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
3339 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
3340 case Intrinsic::loongarch_lasx_xvsrlri_w:
3341 case Intrinsic::loongarch_lasx_xvsrari_w:
3342 case Intrinsic::loongarch_lasx_xvslei_bu:
3343 case Intrinsic::loongarch_lasx_xvslei_hu:
3344 case Intrinsic::loongarch_lasx_xvslei_wu:
3345 case Intrinsic::loongarch_lasx_xvslei_du:
3346 case Intrinsic::loongarch_lasx_xvslti_bu:
3347 case Intrinsic::loongarch_lasx_xvslti_hu:
3348 case Intrinsic::loongarch_lasx_xvslti_wu:
3349 case Intrinsic::loongarch_lasx_xvslti_du:
3350 case Intrinsic::loongarch_lasx_xvbsll_v:
3351 case Intrinsic::loongarch_lasx_xvbsrl_v:
3352 return checkIntrinsicImmArg<5>(
Op, 2, DAG);
3353 case Intrinsic::loongarch_lsx_vseqi_b:
3354 case Intrinsic::loongarch_lsx_vseqi_h:
3355 case Intrinsic::loongarch_lsx_vseqi_w:
3356 case Intrinsic::loongarch_lsx_vseqi_d:
3357 case Intrinsic::loongarch_lsx_vslei_b:
3358 case Intrinsic::loongarch_lsx_vslei_h:
3359 case Intrinsic::loongarch_lsx_vslei_w:
3360 case Intrinsic::loongarch_lsx_vslei_d:
3361 case Intrinsic::loongarch_lsx_vslti_b:
3362 case Intrinsic::loongarch_lsx_vslti_h:
3363 case Intrinsic::loongarch_lsx_vslti_w:
3364 case Intrinsic::loongarch_lsx_vslti_d:
3365 case Intrinsic::loongarch_lasx_xvseqi_b:
3366 case Intrinsic::loongarch_lasx_xvseqi_h:
3367 case Intrinsic::loongarch_lasx_xvseqi_w:
3368 case Intrinsic::loongarch_lasx_xvseqi_d:
3369 case Intrinsic::loongarch_lasx_xvslei_b:
3370 case Intrinsic::loongarch_lasx_xvslei_h:
3371 case Intrinsic::loongarch_lasx_xvslei_w:
3372 case Intrinsic::loongarch_lasx_xvslei_d:
3373 case Intrinsic::loongarch_lasx_xvslti_b:
3374 case Intrinsic::loongarch_lasx_xvslti_h:
3375 case Intrinsic::loongarch_lasx_xvslti_w:
3376 case Intrinsic::loongarch_lasx_xvslti_d:
3377 return checkIntrinsicImmArg<5>(
Op, 2, DAG,
true);
3378 case Intrinsic::loongarch_lsx_vsrlni_h_w:
3379 case Intrinsic::loongarch_lsx_vsrani_h_w:
3380 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
3381 case Intrinsic::loongarch_lsx_vsrarni_h_w:
3382 case Intrinsic::loongarch_lsx_vssrlni_h_w:
3383 case Intrinsic::loongarch_lsx_vssrani_h_w:
3384 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
3385 case Intrinsic::loongarch_lsx_vssrani_hu_w:
3386 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
3387 case Intrinsic::loongarch_lsx_vssrarni_h_w:
3388 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
3389 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
3390 case Intrinsic::loongarch_lsx_vfrstpi_b:
3391 case Intrinsic::loongarch_lsx_vfrstpi_h:
3392 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
3393 case Intrinsic::loongarch_lasx_xvsrani_h_w:
3394 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
3395 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
3396 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
3397 case Intrinsic::loongarch_lasx_xvssrani_h_w:
3398 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
3399 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
3400 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
3401 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
3402 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
3403 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
3404 case Intrinsic::loongarch_lasx_xvfrstpi_b:
3405 case Intrinsic::loongarch_lasx_xvfrstpi_h:
3406 return checkIntrinsicImmArg<5>(
Op, 3, DAG);
3407 case Intrinsic::loongarch_lsx_vsat_d:
3408 case Intrinsic::loongarch_lsx_vsat_du:
3409 case Intrinsic::loongarch_lsx_vrotri_d:
3410 case Intrinsic::loongarch_lsx_vsrlri_d:
3411 case Intrinsic::loongarch_lsx_vsrari_d:
3412 case Intrinsic::loongarch_lasx_xvsat_d:
3413 case Intrinsic::loongarch_lasx_xvsat_du:
3414 case Intrinsic::loongarch_lasx_xvrotri_d:
3415 case Intrinsic::loongarch_lasx_xvsrlri_d:
3416 case Intrinsic::loongarch_lasx_xvsrari_d:
3417 return checkIntrinsicImmArg<6>(
Op, 2, DAG);
3418 case Intrinsic::loongarch_lsx_vsrlni_w_d:
3419 case Intrinsic::loongarch_lsx_vsrani_w_d:
3420 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
3421 case Intrinsic::loongarch_lsx_vsrarni_w_d:
3422 case Intrinsic::loongarch_lsx_vssrlni_w_d:
3423 case Intrinsic::loongarch_lsx_vssrani_w_d:
3424 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
3425 case Intrinsic::loongarch_lsx_vssrani_wu_d:
3426 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
3427 case Intrinsic::loongarch_lsx_vssrarni_w_d:
3428 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
3429 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
3430 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
3431 case Intrinsic::loongarch_lasx_xvsrani_w_d:
3432 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
3433 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
3434 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
3435 case Intrinsic::loongarch_lasx_xvssrani_w_d:
3436 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
3437 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
3438 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
3439 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
3440 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
3441 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
3442 return checkIntrinsicImmArg<6>(
Op, 3, DAG);
3443 case Intrinsic::loongarch_lsx_vsrlni_d_q:
3444 case Intrinsic::loongarch_lsx_vsrani_d_q:
3445 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
3446 case Intrinsic::loongarch_lsx_vsrarni_d_q:
3447 case Intrinsic::loongarch_lsx_vssrlni_d_q:
3448 case Intrinsic::loongarch_lsx_vssrani_d_q:
3449 case Intrinsic::loongarch_lsx_vssrlni_du_q:
3450 case Intrinsic::loongarch_lsx_vssrani_du_q:
3451 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
3452 case Intrinsic::loongarch_lsx_vssrarni_d_q:
3453 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
3454 case Intrinsic::loongarch_lsx_vssrarni_du_q:
3455 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
3456 case Intrinsic::loongarch_lasx_xvsrani_d_q:
3457 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
3458 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
3459 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
3460 case Intrinsic::loongarch_lasx_xvssrani_d_q:
3461 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
3462 case Intrinsic::loongarch_lasx_xvssrani_du_q:
3463 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
3464 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
3465 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
3466 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
3467 return checkIntrinsicImmArg<7>(
Op, 3, DAG);
3468 case Intrinsic::loongarch_lsx_vnori_b:
3469 case Intrinsic::loongarch_lsx_vshuf4i_b:
3470 case Intrinsic::loongarch_lsx_vshuf4i_h:
3471 case Intrinsic::loongarch_lsx_vshuf4i_w:
3472 case Intrinsic::loongarch_lasx_xvnori_b:
3473 case Intrinsic::loongarch_lasx_xvshuf4i_b:
3474 case Intrinsic::loongarch_lasx_xvshuf4i_h:
3475 case Intrinsic::loongarch_lasx_xvshuf4i_w:
3476 case Intrinsic::loongarch_lasx_xvpermi_d:
3477 return checkIntrinsicImmArg<8>(
Op, 2, DAG);
3478 case Intrinsic::loongarch_lsx_vshuf4i_d:
3479 case Intrinsic::loongarch_lsx_vpermi_w:
3480 case Intrinsic::loongarch_lsx_vbitseli_b:
3481 case Intrinsic::loongarch_lsx_vextrins_b:
3482 case Intrinsic::loongarch_lsx_vextrins_h:
3483 case Intrinsic::loongarch_lsx_vextrins_w:
3484 case Intrinsic::loongarch_lsx_vextrins_d:
3485 case Intrinsic::loongarch_lasx_xvshuf4i_d:
3486 case Intrinsic::loongarch_lasx_xvpermi_w:
3487 case Intrinsic::loongarch_lasx_xvpermi_q:
3488 case Intrinsic::loongarch_lasx_xvbitseli_b:
3489 case Intrinsic::loongarch_lasx_xvextrins_b:
3490 case Intrinsic::loongarch_lasx_xvextrins_h:
3491 case Intrinsic::loongarch_lasx_xvextrins_w:
3492 case Intrinsic::loongarch_lasx_xvextrins_d:
3493 return checkIntrinsicImmArg<8>(
Op, 3, DAG);
3494 case Intrinsic::loongarch_lsx_vrepli_b:
3495 case Intrinsic::loongarch_lsx_vrepli_h:
3496 case Intrinsic::loongarch_lsx_vrepli_w:
3497 case Intrinsic::loongarch_lsx_vrepli_d:
3498 case Intrinsic::loongarch_lasx_xvrepli_b:
3499 case Intrinsic::loongarch_lasx_xvrepli_h:
3500 case Intrinsic::loongarch_lasx_xvrepli_w:
3501 case Intrinsic::loongarch_lasx_xvrepli_d:
3502 return checkIntrinsicImmArg<10>(
Op, 1, DAG,
true);
3503 case Intrinsic::loongarch_lsx_vldi:
3504 case Intrinsic::loongarch_lasx_xvldi:
3505 return checkIntrinsicImmArg<13>(
Op, 1, DAG,
true);
3520LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
3524 EVT VT =
Op.getValueType();
3526 const StringRef ErrorMsgOOR =
"argument out of range";
3527 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3528 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3530 switch (
Op.getConstantOperandVal(1)) {
3533 case Intrinsic::loongarch_crc_w_b_w:
3534 case Intrinsic::loongarch_crc_w_h_w:
3535 case Intrinsic::loongarch_crc_w_w_w:
3536 case Intrinsic::loongarch_crc_w_d_w:
3537 case Intrinsic::loongarch_crcc_w_b_w:
3538 case Intrinsic::loongarch_crcc_w_h_w:
3539 case Intrinsic::loongarch_crcc_w_w_w:
3540 case Intrinsic::loongarch_crcc_w_d_w:
3542 case Intrinsic::loongarch_csrrd_w:
3543 case Intrinsic::loongarch_csrrd_d: {
3544 unsigned Imm =
Op.getConstantOperandVal(2);
3545 return !isUInt<14>(Imm)
3550 case Intrinsic::loongarch_csrwr_w:
3551 case Intrinsic::loongarch_csrwr_d: {
3552 unsigned Imm =
Op.getConstantOperandVal(3);
3553 return !isUInt<14>(Imm)
3556 {Chain,
Op.getOperand(2),
3559 case Intrinsic::loongarch_csrxchg_w:
3560 case Intrinsic::loongarch_csrxchg_d: {
3561 unsigned Imm =
Op.getConstantOperandVal(4);
3562 return !isUInt<14>(Imm)
3565 {Chain,
Op.getOperand(2),
Op.getOperand(3),
3568 case Intrinsic::loongarch_iocsrrd_d: {
3573#define IOCSRRD_CASE(NAME, NODE) \
3574 case Intrinsic::loongarch_##NAME: { \
3575 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
3576 {Chain, Op.getOperand(2)}); \
3582 case Intrinsic::loongarch_cpucfg: {
3584 {Chain,
Op.getOperand(2)});
3586 case Intrinsic::loongarch_lddir_d: {
3587 unsigned Imm =
Op.getConstantOperandVal(3);
3588 return !isUInt<8>(Imm)
3592 case Intrinsic::loongarch_movfcsr2gr: {
3593 if (!Subtarget.hasBasicF())
3595 unsigned Imm =
Op.getConstantOperandVal(2);
3596 return !isUInt<2>(Imm)
3601 case Intrinsic::loongarch_lsx_vld:
3602 case Intrinsic::loongarch_lsx_vldrepl_b:
3603 case Intrinsic::loongarch_lasx_xvld:
3604 case Intrinsic::loongarch_lasx_xvldrepl_b:
3605 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3608 case Intrinsic::loongarch_lsx_vldrepl_h:
3609 case Intrinsic::loongarch_lasx_xvldrepl_h:
3610 return !isShiftedInt<11, 1>(
3611 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3613 Op,
"argument out of range or not a multiple of 2", DAG)
3615 case Intrinsic::loongarch_lsx_vldrepl_w:
3616 case Intrinsic::loongarch_lasx_xvldrepl_w:
3617 return !isShiftedInt<10, 2>(
3618 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3620 Op,
"argument out of range or not a multiple of 4", DAG)
3622 case Intrinsic::loongarch_lsx_vldrepl_d:
3623 case Intrinsic::loongarch_lasx_xvldrepl_d:
3624 return !isShiftedInt<9, 3>(
3625 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
3627 Op,
"argument out of range or not a multiple of 8", DAG)
3638 return Op.getOperand(0);
3646 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
3648 const StringRef ErrorMsgOOR =
"argument out of range";
3649 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3650 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
3651 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3653 switch (IntrinsicEnum) {
3657 case Intrinsic::loongarch_cacop_d:
3658 case Intrinsic::loongarch_cacop_w: {
3659 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.
is64Bit())
3661 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.
is64Bit())
3665 int Imm2 = cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue();
3666 if (!isUInt<5>(Imm1) || !isInt<12>(Imm2))
3670 case Intrinsic::loongarch_dbar: {
3672 return !isUInt<15>(Imm)
3677 case Intrinsic::loongarch_ibar: {
3679 return !isUInt<15>(Imm)
3684 case Intrinsic::loongarch_break: {
3686 return !isUInt<15>(Imm)
3691 case Intrinsic::loongarch_movgr2fcsr: {
3692 if (!Subtarget.hasBasicF())
3695 return !isUInt<2>(Imm)
3702 case Intrinsic::loongarch_syscall: {
3704 return !isUInt<15>(Imm)
3709#define IOCSRWR_CASE(NAME, NODE) \
3710 case Intrinsic::loongarch_##NAME: { \
3711 SDValue Op3 = Op.getOperand(3); \
3712 return Subtarget.is64Bit() \
3713 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
3714 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
3715 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
3716 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
3723 case Intrinsic::loongarch_iocsrwr_d: {
3731#define ASRT_LE_GT_CASE(NAME) \
3732 case Intrinsic::loongarch_##NAME: { \
3733 return !Subtarget.is64Bit() \
3734 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
3739#undef ASRT_LE_GT_CASE
3740 case Intrinsic::loongarch_ldpte_d: {
3741 unsigned Imm =
Op.getConstantOperandVal(3);
3747 case Intrinsic::loongarch_lsx_vst:
3748 case Intrinsic::loongarch_lasx_xvst:
3749 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue())
3752 case Intrinsic::loongarch_lasx_xvstelm_b:
3753 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3754 !isUInt<5>(
Op.getConstantOperandVal(5)))
3757 case Intrinsic::loongarch_lsx_vstelm_b:
3758 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3759 !isUInt<4>(
Op.getConstantOperandVal(5)))
3762 case Intrinsic::loongarch_lasx_xvstelm_h:
3763 return (!isShiftedInt<8, 1>(
3764 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3765 !isUInt<4>(
Op.getConstantOperandVal(5)))
3767 Op,
"argument out of range or not a multiple of 2", DAG)
3769 case Intrinsic::loongarch_lsx_vstelm_h:
3770 return (!isShiftedInt<8, 1>(
3771 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3772 !isUInt<3>(
Op.getConstantOperandVal(5)))
3774 Op,
"argument out of range or not a multiple of 2", DAG)
3776 case Intrinsic::loongarch_lasx_xvstelm_w:
3777 return (!isShiftedInt<8, 2>(
3778 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3779 !isUInt<3>(
Op.getConstantOperandVal(5)))
3781 Op,
"argument out of range or not a multiple of 4", DAG)
3783 case Intrinsic::loongarch_lsx_vstelm_w:
3784 return (!isShiftedInt<8, 2>(
3785 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3786 !isUInt<2>(
Op.getConstantOperandVal(5)))
3788 Op,
"argument out of range or not a multiple of 4", DAG)
3790 case Intrinsic::loongarch_lasx_xvstelm_d:
3791 return (!isShiftedInt<8, 3>(
3792 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3793 !isUInt<2>(
Op.getConstantOperandVal(5)))
3795 Op,
"argument out of range or not a multiple of 8", DAG)
3797 case Intrinsic::loongarch_lsx_vstelm_d:
3798 return (!isShiftedInt<8, 3>(
3799 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
3800 !isUInt<1>(
Op.getConstantOperandVal(5)))
3802 Op,
"argument out of range or not a multiple of 8", DAG)
3813 EVT VT =
Lo.getValueType();
3854 EVT VT =
Lo.getValueType();
3946 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
3947 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
3951 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
3957 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
3984 StringRef ErrorMsg,
bool WithChain =
true) {
3989 Results.push_back(
N->getOperand(0));
3992template <
unsigned N>
3997 const StringRef ErrorMsgOOR =
"argument out of range";
3998 unsigned Imm =
Node->getConstantOperandVal(2);
3999 if (!isUInt<N>(Imm)) {
4032 switch (
N->getConstantOperandVal(0)) {
4035 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4036 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
4039 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4040 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4041 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
4044 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4045 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
4048 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4049 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
4052 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4053 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4054 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
4057 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4058 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
4061 case Intrinsic::loongarch_lsx_bz_b:
4062 case Intrinsic::loongarch_lsx_bz_h:
4063 case Intrinsic::loongarch_lsx_bz_w:
4064 case Intrinsic::loongarch_lsx_bz_d:
4065 case Intrinsic::loongarch_lasx_xbz_b:
4066 case Intrinsic::loongarch_lasx_xbz_h:
4067 case Intrinsic::loongarch_lasx_xbz_w:
4068 case Intrinsic::loongarch_lasx_xbz_d:
4072 case Intrinsic::loongarch_lsx_bz_v:
4073 case Intrinsic::loongarch_lasx_xbz_v:
4077 case Intrinsic::loongarch_lsx_bnz_b:
4078 case Intrinsic::loongarch_lsx_bnz_h:
4079 case Intrinsic::loongarch_lsx_bnz_w:
4080 case Intrinsic::loongarch_lsx_bnz_d:
4081 case Intrinsic::loongarch_lasx_xbnz_b:
4082 case Intrinsic::loongarch_lasx_xbnz_h:
4083 case Intrinsic::loongarch_lasx_xbnz_w:
4084 case Intrinsic::loongarch_lasx_xbnz_d:
4088 case Intrinsic::loongarch_lsx_bnz_v:
4089 case Intrinsic::loongarch_lasx_xbnz_v:
4099 assert(
N->getValueType(0) == MVT::i128 &&
4100 "AtomicCmpSwap on types less than 128 should be legal");
4104 switch (
MemOp->getMergedOrdering()) {
4108 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4112 Opcode = LoongArch::PseudoCmpXchg128;
4119 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4120 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4121 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4122 NewVal.first, NewVal.second,
N->getOperand(0)};
4125 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4136 EVT VT =
N->getValueType(0);
4137 switch (
N->getOpcode()) {
4143 "Unexpected custom legalisation");
4151 "Unexpected custom legalisation");
4153 Subtarget.hasDiv32() && VT == MVT::i32
4161 "Unexpected custom legalisation");
4170 "Unexpected custom legalisation");
4175 "Unexpected custom legalisation");
4182 if (Src.getValueType() == MVT::f16)
4193 EVT OpVT = Src.getValueType();
4197 std::tie(Result, Chain) =
4204 EVT SrcVT = Src.getValueType();
4205 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.
is64Bit() &&
4206 Subtarget.hasBasicF()) {
4210 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.
is64Bit()) {
4212 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4221 "Unexpected custom legalisation");
4224 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4230 assert((VT == MVT::i16 || VT == MVT::i32) &&
4231 "Unexpected custom legalization");
4252 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
4253 "Unexpected custom legalization");
4273 "Unexpected custom legalisation");
4281 const StringRef ErrorMsgOOR =
"argument out of range";
4282 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4283 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4285 switch (
N->getConstantOperandVal(1)) {
4288 case Intrinsic::loongarch_movfcsr2gr: {
4289 if (!Subtarget.hasBasicF()) {
4294 if (!isUInt<2>(Imm)) {
4306#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4307 case Intrinsic::loongarch_##NAME: { \
4308 SDValue NODE = DAG.getNode( \
4309 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4310 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4311 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4312 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4313 Results.push_back(NODE.getValue(1)); \
4322#undef CRC_CASE_EXT_BINARYOP
4324#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4325 case Intrinsic::loongarch_##NAME: { \
4326 SDValue NODE = DAG.getNode( \
4327 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4329 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4330 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4331 Results.push_back(NODE.getValue(1)); \
4336#undef CRC_CASE_EXT_UNARYOP
4337#define CSR_CASE(ID) \
4338 case Intrinsic::loongarch_##ID: { \
4339 if (!Subtarget.is64Bit()) \
4340 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
4348 case Intrinsic::loongarch_csrrd_w: {
4350 if (!isUInt<14>(Imm)) {
4362 case Intrinsic::loongarch_csrwr_w: {
4363 unsigned Imm =
N->getConstantOperandVal(3);
4364 if (!isUInt<14>(Imm)) {
4377 case Intrinsic::loongarch_csrxchg_w: {
4378 unsigned Imm =
N->getConstantOperandVal(4);
4379 if (!isUInt<14>(Imm)) {
4393#define IOCSRRD_CASE(NAME, NODE) \
4394 case Intrinsic::loongarch_##NAME: { \
4395 SDValue IOCSRRDResults = \
4396 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4397 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
4398 Results.push_back( \
4399 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
4400 Results.push_back(IOCSRRDResults.getValue(1)); \
4407 case Intrinsic::loongarch_cpucfg: {
4416 case Intrinsic::loongarch_lddir_d: {
4429 "On LA64, only 64-bit registers can be read.");
4432 "On LA32, only 32-bit registers can be read.");
4434 Results.push_back(
N->getOperand(0));
4445 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
4458 MVT VT =
N->getSimpleValueType(0);
4464 EVT InVT = In.getValueType();
4475 for (
unsigned I = 0;
I < MinElts; ++
I)
4476 TruncMask[
I] = Scale *
I;
4478 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
4479 MVT SVT = In.getSimpleValueType().getScalarType();
4485 "Illegal vector type in truncation");
4504 SDValue FirstOperand =
N->getOperand(0);
4505 SDValue SecondOperand =
N->getOperand(1);
4506 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
4507 EVT ValTy =
N->getValueType(0);
4510 unsigned SMIdx, SMLen;
4516 if (!Subtarget.has32S())
4520 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||
4531 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))))
4572 NewOperand = FirstOperand;
4575 msb = lsb + SMLen - 1;
4579 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
4592 if (!Subtarget.has32S())
4604 SDValue FirstOperand =
N->getOperand(0);
4606 EVT ValTy =
N->getValueType(0);
4609 unsigned MaskIdx, MaskLen;
4615 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))) ||
4620 if (!(CN = dyn_cast<ConstantSDNode>(
N->getOperand(1))))
4624 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
4640 switch (Src.getOpcode()) {
4643 return Src.getOperand(0).getValueSizeInBits() ==
Size;
4653 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
4666 switch (Src.getOpcode()) {
4676 Src.getOpcode(),
DL, SExtVT,
4682 DL, SExtVT, Src.getOperand(0),
4694 EVT VT =
N->getValueType(0);
4696 EVT SrcVT = Src.getValueType();
4698 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
4703 EVT CmpVT = Src.getOperand(0).getValueType();
4708 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
4714 SDValue SrcN1 = Src.getOperand(1);
4715 switch (cast<CondCodeSDNode>(Src.getOperand(2))->get()) {
4736 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4743 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4767 EVT VT =
N->getValueType(0);
4769 EVT SrcVT = Src.getValueType();
4785 bool UseLASX =
false;
4786 bool PropagateSExt =
false;
4788 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
4789 EVT CmpVT = Src.getOperand(0).getValueType();
4798 SExtVT = MVT::v2i64;
4801 SExtVT = MVT::v4i32;
4803 SExtVT = MVT::v4i64;
4805 PropagateSExt =
true;
4809 SExtVT = MVT::v8i16;
4811 SExtVT = MVT::v8i32;
4813 PropagateSExt =
true;
4817 SExtVT = MVT::v16i8;
4819 SExtVT = MVT::v16i16;
4821 PropagateSExt =
true;
4825 SExtVT = MVT::v32i8;
4833 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
4834 if (Src.getSimpleValueType() == MVT::v32i8) {
4842 }
else if (UseLASX) {
4861 EVT ValTy =
N->getValueType(0);
4862 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
4866 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
4868 bool SwapAndRetried =
false;
4871 if (!Subtarget.has32S())
4877 if (ValBits != 32 && ValBits != 64)
4887 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4890 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
4892 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
4893 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
4895 (MaskIdx0 + MaskLen0 <= ValBits)) {
4909 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4912 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
4914 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
4916 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
4917 (MaskIdx0 + MaskLen0 <= ValBits)) {
4932 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4934 (MaskIdx0 + MaskLen0 <= 64) &&
4935 (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) &&
4942 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
4943 : (MaskIdx0 + MaskLen0 - 1),
4955 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4957 MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
4959 (MaskIdx0 + MaskLen0 <= ValBits)) {
4974 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
4976 (CN1 = dyn_cast<ConstantSDNode>(N1)) &&
4982 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
4983 : (MaskIdx0 + MaskLen0 - 1),
4998 unsigned MaskIdx, MaskLen;
4999 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5000 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
5002 MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5024 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5026 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5027 (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
5040 if (!SwapAndRetried) {
5042 SwapAndRetried =
true;
5046 SwapAndRetried =
false;
5058 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
5072 if (!SwapAndRetried) {
5074 SwapAndRetried =
true;
5084 switch (V.getNode()->getOpcode()) {
5086 LoadSDNode *LoadNode = cast<LoadSDNode>(V.getNode());
5095 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
5096 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5103 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
5104 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5179 ISD::CondCode CC = cast<CondCodeSDNode>(
N->getOperand(2))->get();
5181 SDNode *AndNode =
N->getOperand(0).getNode();
5189 SDValue CmpInputValue =
N->getOperand(1);
5197 CN = dyn_cast<ConstantSDNode>(CmpInputValue);
5200 AndInputValue1 = AndInputValue1.
getOperand(0);
5204 if (AndInputValue2 != CmpInputValue)
5237 TruncInputValue1, TruncInputValue2);
5239 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5280 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
5284 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
5319 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
5324template <
unsigned N>
5328 bool IsSigned =
false) {
5330 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
5332 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
5333 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
5335 ": argument out of range.");
5341template <
unsigned N>
5345 EVT ResTy =
Node->getValueType(0);
5346 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
5349 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
5350 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
5352 ": argument out of range.");
5357 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
5363 EVT ResTy =
Node->getValueType(0);
5371 EVT ResTy =
Node->getValueType(0);
5380template <
unsigned N>
5383 EVT ResTy =
Node->getValueType(0);
5384 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5386 if (!isUInt<N>(CImm->getZExtValue())) {
5388 ": argument out of range.");
5398template <
unsigned N>
5401 EVT ResTy =
Node->getValueType(0);
5402 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5404 if (!isUInt<N>(CImm->getZExtValue())) {
5406 ": argument out of range.");
5415template <
unsigned N>
5418 EVT ResTy =
Node->getValueType(0);
5419 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
5421 if (!isUInt<N>(CImm->getZExtValue())) {
5423 ": argument out of range.");
5437 switch (
N->getConstantOperandVal(0)) {
5440 case Intrinsic::loongarch_lsx_vadd_b:
5441 case Intrinsic::loongarch_lsx_vadd_h:
5442 case Intrinsic::loongarch_lsx_vadd_w:
5443 case Intrinsic::loongarch_lsx_vadd_d:
5444 case Intrinsic::loongarch_lasx_xvadd_b:
5445 case Intrinsic::loongarch_lasx_xvadd_h:
5446 case Intrinsic::loongarch_lasx_xvadd_w:
5447 case Intrinsic::loongarch_lasx_xvadd_d:
5450 case Intrinsic::loongarch_lsx_vaddi_bu:
5451 case Intrinsic::loongarch_lsx_vaddi_hu:
5452 case Intrinsic::loongarch_lsx_vaddi_wu:
5453 case Intrinsic::loongarch_lsx_vaddi_du:
5454 case Intrinsic::loongarch_lasx_xvaddi_bu:
5455 case Intrinsic::loongarch_lasx_xvaddi_hu:
5456 case Intrinsic::loongarch_lasx_xvaddi_wu:
5457 case Intrinsic::loongarch_lasx_xvaddi_du:
5459 lowerVectorSplatImm<5>(
N, 2, DAG));
5460 case Intrinsic::loongarch_lsx_vsub_b:
5461 case Intrinsic::loongarch_lsx_vsub_h:
5462 case Intrinsic::loongarch_lsx_vsub_w:
5463 case Intrinsic::loongarch_lsx_vsub_d:
5464 case Intrinsic::loongarch_lasx_xvsub_b:
5465 case Intrinsic::loongarch_lasx_xvsub_h:
5466 case Intrinsic::loongarch_lasx_xvsub_w:
5467 case Intrinsic::loongarch_lasx_xvsub_d:
5470 case Intrinsic::loongarch_lsx_vsubi_bu:
5471 case Intrinsic::loongarch_lsx_vsubi_hu:
5472 case Intrinsic::loongarch_lsx_vsubi_wu:
5473 case Intrinsic::loongarch_lsx_vsubi_du:
5474 case Intrinsic::loongarch_lasx_xvsubi_bu:
5475 case Intrinsic::loongarch_lasx_xvsubi_hu:
5476 case Intrinsic::loongarch_lasx_xvsubi_wu:
5477 case Intrinsic::loongarch_lasx_xvsubi_du:
5479 lowerVectorSplatImm<5>(
N, 2, DAG));
5480 case Intrinsic::loongarch_lsx_vneg_b:
5481 case Intrinsic::loongarch_lsx_vneg_h:
5482 case Intrinsic::loongarch_lsx_vneg_w:
5483 case Intrinsic::loongarch_lsx_vneg_d:
5484 case Intrinsic::loongarch_lasx_xvneg_b:
5485 case Intrinsic::loongarch_lasx_xvneg_h:
5486 case Intrinsic::loongarch_lasx_xvneg_w:
5487 case Intrinsic::loongarch_lasx_xvneg_d:
5491 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
5493 SDLoc(
N),
N->getValueType(0)),
5495 case Intrinsic::loongarch_lsx_vmax_b:
5496 case Intrinsic::loongarch_lsx_vmax_h:
5497 case Intrinsic::loongarch_lsx_vmax_w:
5498 case Intrinsic::loongarch_lsx_vmax_d:
5499 case Intrinsic::loongarch_lasx_xvmax_b:
5500 case Intrinsic::loongarch_lasx_xvmax_h:
5501 case Intrinsic::loongarch_lasx_xvmax_w:
5502 case Intrinsic::loongarch_lasx_xvmax_d:
5505 case Intrinsic::loongarch_lsx_vmax_bu:
5506 case Intrinsic::loongarch_lsx_vmax_hu:
5507 case Intrinsic::loongarch_lsx_vmax_wu:
5508 case Intrinsic::loongarch_lsx_vmax_du:
5509 case Intrinsic::loongarch_lasx_xvmax_bu:
5510 case Intrinsic::loongarch_lasx_xvmax_hu:
5511 case Intrinsic::loongarch_lasx_xvmax_wu:
5512 case Intrinsic::loongarch_lasx_xvmax_du:
5515 case Intrinsic::loongarch_lsx_vmaxi_b:
5516 case Intrinsic::loongarch_lsx_vmaxi_h:
5517 case Intrinsic::loongarch_lsx_vmaxi_w:
5518 case Intrinsic::loongarch_lsx_vmaxi_d:
5519 case Intrinsic::loongarch_lasx_xvmaxi_b:
5520 case Intrinsic::loongarch_lasx_xvmaxi_h:
5521 case Intrinsic::loongarch_lasx_xvmaxi_w:
5522 case Intrinsic::loongarch_lasx_xvmaxi_d:
5524 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
5525 case Intrinsic::loongarch_lsx_vmaxi_bu:
5526 case Intrinsic::loongarch_lsx_vmaxi_hu:
5527 case Intrinsic::loongarch_lsx_vmaxi_wu:
5528 case Intrinsic::loongarch_lsx_vmaxi_du:
5529 case Intrinsic::loongarch_lasx_xvmaxi_bu:
5530 case Intrinsic::loongarch_lasx_xvmaxi_hu:
5531 case Intrinsic::loongarch_lasx_xvmaxi_wu:
5532 case Intrinsic::loongarch_lasx_xvmaxi_du:
5534 lowerVectorSplatImm<5>(
N, 2, DAG));
5535 case Intrinsic::loongarch_lsx_vmin_b:
5536 case Intrinsic::loongarch_lsx_vmin_h:
5537 case Intrinsic::loongarch_lsx_vmin_w:
5538 case Intrinsic::loongarch_lsx_vmin_d:
5539 case Intrinsic::loongarch_lasx_xvmin_b:
5540 case Intrinsic::loongarch_lasx_xvmin_h:
5541 case Intrinsic::loongarch_lasx_xvmin_w:
5542 case Intrinsic::loongarch_lasx_xvmin_d:
5545 case Intrinsic::loongarch_lsx_vmin_bu:
5546 case Intrinsic::loongarch_lsx_vmin_hu:
5547 case Intrinsic::loongarch_lsx_vmin_wu:
5548 case Intrinsic::loongarch_lsx_vmin_du:
5549 case Intrinsic::loongarch_lasx_xvmin_bu:
5550 case Intrinsic::loongarch_lasx_xvmin_hu:
5551 case Intrinsic::loongarch_lasx_xvmin_wu:
5552 case Intrinsic::loongarch_lasx_xvmin_du:
5555 case Intrinsic::loongarch_lsx_vmini_b:
5556 case Intrinsic::loongarch_lsx_vmini_h:
5557 case Intrinsic::loongarch_lsx_vmini_w:
5558 case Intrinsic::loongarch_lsx_vmini_d:
5559 case Intrinsic::loongarch_lasx_xvmini_b:
5560 case Intrinsic::loongarch_lasx_xvmini_h:
5561 case Intrinsic::loongarch_lasx_xvmini_w:
5562 case Intrinsic::loongarch_lasx_xvmini_d:
5564 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
5565 case Intrinsic::loongarch_lsx_vmini_bu:
5566 case Intrinsic::loongarch_lsx_vmini_hu:
5567 case Intrinsic::loongarch_lsx_vmini_wu:
5568 case Intrinsic::loongarch_lsx_vmini_du:
5569 case Intrinsic::loongarch_lasx_xvmini_bu:
5570 case Intrinsic::loongarch_lasx_xvmini_hu:
5571 case Intrinsic::loongarch_lasx_xvmini_wu:
5572 case Intrinsic::loongarch_lasx_xvmini_du:
5574 lowerVectorSplatImm<5>(
N, 2, DAG));
5575 case Intrinsic::loongarch_lsx_vmul_b:
5576 case Intrinsic::loongarch_lsx_vmul_h:
5577 case Intrinsic::loongarch_lsx_vmul_w:
5578 case Intrinsic::loongarch_lsx_vmul_d:
5579 case Intrinsic::loongarch_lasx_xvmul_b:
5580 case Intrinsic::loongarch_lasx_xvmul_h:
5581 case Intrinsic::loongarch_lasx_xvmul_w:
5582 case Intrinsic::loongarch_lasx_xvmul_d:
5585 case Intrinsic::loongarch_lsx_vmadd_b:
5586 case Intrinsic::loongarch_lsx_vmadd_h:
5587 case Intrinsic::loongarch_lsx_vmadd_w:
5588 case Intrinsic::loongarch_lsx_vmadd_d:
5589 case Intrinsic::loongarch_lasx_xvmadd_b:
5590 case Intrinsic::loongarch_lasx_xvmadd_h:
5591 case Intrinsic::loongarch_lasx_xvmadd_w:
5592 case Intrinsic::loongarch_lasx_xvmadd_d: {
5593 EVT ResTy =
N->getValueType(0);
5598 case Intrinsic::loongarch_lsx_vmsub_b:
5599 case Intrinsic::loongarch_lsx_vmsub_h:
5600 case Intrinsic::loongarch_lsx_vmsub_w:
5601 case Intrinsic::loongarch_lsx_vmsub_d:
5602 case Intrinsic::loongarch_lasx_xvmsub_b:
5603 case Intrinsic::loongarch_lasx_xvmsub_h:
5604 case Intrinsic::loongarch_lasx_xvmsub_w:
5605 case Intrinsic::loongarch_lasx_xvmsub_d: {
5606 EVT ResTy =
N->getValueType(0);
5611 case Intrinsic::loongarch_lsx_vdiv_b:
5612 case Intrinsic::loongarch_lsx_vdiv_h:
5613 case Intrinsic::loongarch_lsx_vdiv_w:
5614 case Intrinsic::loongarch_lsx_vdiv_d:
5615 case Intrinsic::loongarch_lasx_xvdiv_b:
5616 case Intrinsic::loongarch_lasx_xvdiv_h:
5617 case Intrinsic::loongarch_lasx_xvdiv_w:
5618 case Intrinsic::loongarch_lasx_xvdiv_d:
5621 case Intrinsic::loongarch_lsx_vdiv_bu:
5622 case Intrinsic::loongarch_lsx_vdiv_hu:
5623 case Intrinsic::loongarch_lsx_vdiv_wu:
5624 case Intrinsic::loongarch_lsx_vdiv_du:
5625 case Intrinsic::loongarch_lasx_xvdiv_bu:
5626 case Intrinsic::loongarch_lasx_xvdiv_hu:
5627 case Intrinsic::loongarch_lasx_xvdiv_wu:
5628 case Intrinsic::loongarch_lasx_xvdiv_du:
5631 case Intrinsic::loongarch_lsx_vmod_b:
5632 case Intrinsic::loongarch_lsx_vmod_h:
5633 case Intrinsic::loongarch_lsx_vmod_w:
5634 case Intrinsic::loongarch_lsx_vmod_d:
5635 case Intrinsic::loongarch_lasx_xvmod_b:
5636 case Intrinsic::loongarch_lasx_xvmod_h:
5637 case Intrinsic::loongarch_lasx_xvmod_w:
5638 case Intrinsic::loongarch_lasx_xvmod_d:
5641 case Intrinsic::loongarch_lsx_vmod_bu:
5642 case Intrinsic::loongarch_lsx_vmod_hu:
5643 case Intrinsic::loongarch_lsx_vmod_wu:
5644 case Intrinsic::loongarch_lsx_vmod_du:
5645 case Intrinsic::loongarch_lasx_xvmod_bu:
5646 case Intrinsic::loongarch_lasx_xvmod_hu:
5647 case Intrinsic::loongarch_lasx_xvmod_wu:
5648 case Intrinsic::loongarch_lasx_xvmod_du:
5651 case Intrinsic::loongarch_lsx_vand_v:
5652 case Intrinsic::loongarch_lasx_xvand_v:
5655 case Intrinsic::loongarch_lsx_vor_v:
5656 case Intrinsic::loongarch_lasx_xvor_v:
5659 case Intrinsic::loongarch_lsx_vxor_v:
5660 case Intrinsic::loongarch_lasx_xvxor_v:
5663 case Intrinsic::loongarch_lsx_vnor_v:
5664 case Intrinsic::loongarch_lasx_xvnor_v: {
5669 case Intrinsic::loongarch_lsx_vandi_b:
5670 case Intrinsic::loongarch_lasx_xvandi_b:
5672 lowerVectorSplatImm<8>(
N, 2, DAG));
5673 case Intrinsic::loongarch_lsx_vori_b:
5674 case Intrinsic::loongarch_lasx_xvori_b:
5676 lowerVectorSplatImm<8>(
N, 2, DAG));
5677 case Intrinsic::loongarch_lsx_vxori_b:
5678 case Intrinsic::loongarch_lasx_xvxori_b:
5680 lowerVectorSplatImm<8>(
N, 2, DAG));
5681 case Intrinsic::loongarch_lsx_vsll_b:
5682 case Intrinsic::loongarch_lsx_vsll_h:
5683 case Intrinsic::loongarch_lsx_vsll_w:
5684 case Intrinsic::loongarch_lsx_vsll_d:
5685 case Intrinsic::loongarch_lasx_xvsll_b:
5686 case Intrinsic::loongarch_lasx_xvsll_h:
5687 case Intrinsic::loongarch_lasx_xvsll_w:
5688 case Intrinsic::loongarch_lasx_xvsll_d:
5691 case Intrinsic::loongarch_lsx_vslli_b:
5692 case Intrinsic::loongarch_lasx_xvslli_b:
5694 lowerVectorSplatImm<3>(
N, 2, DAG));
5695 case Intrinsic::loongarch_lsx_vslli_h:
5696 case Intrinsic::loongarch_lasx_xvslli_h:
5698 lowerVectorSplatImm<4>(
N, 2, DAG));
5699 case Intrinsic::loongarch_lsx_vslli_w:
5700 case Intrinsic::loongarch_lasx_xvslli_w:
5702 lowerVectorSplatImm<5>(
N, 2, DAG));
5703 case Intrinsic::loongarch_lsx_vslli_d:
5704 case Intrinsic::loongarch_lasx_xvslli_d:
5706 lowerVectorSplatImm<6>(
N, 2, DAG));
5707 case Intrinsic::loongarch_lsx_vsrl_b:
5708 case Intrinsic::loongarch_lsx_vsrl_h:
5709 case Intrinsic::loongarch_lsx_vsrl_w:
5710 case Intrinsic::loongarch_lsx_vsrl_d:
5711 case Intrinsic::loongarch_lasx_xvsrl_b:
5712 case Intrinsic::loongarch_lasx_xvsrl_h:
5713 case Intrinsic::loongarch_lasx_xvsrl_w:
5714 case Intrinsic::loongarch_lasx_xvsrl_d:
5717 case Intrinsic::loongarch_lsx_vsrli_b:
5718 case Intrinsic::loongarch_lasx_xvsrli_b:
5720 lowerVectorSplatImm<3>(
N, 2, DAG));
5721 case Intrinsic::loongarch_lsx_vsrli_h:
5722 case Intrinsic::loongarch_lasx_xvsrli_h:
5724 lowerVectorSplatImm<4>(
N, 2, DAG));
5725 case Intrinsic::loongarch_lsx_vsrli_w:
5726 case Intrinsic::loongarch_lasx_xvsrli_w:
5728 lowerVectorSplatImm<5>(
N, 2, DAG));
5729 case Intrinsic::loongarch_lsx_vsrli_d:
5730 case Intrinsic::loongarch_lasx_xvsrli_d:
5732 lowerVectorSplatImm<6>(
N, 2, DAG));
5733 case Intrinsic::loongarch_lsx_vsra_b:
5734 case Intrinsic::loongarch_lsx_vsra_h:
5735 case Intrinsic::loongarch_lsx_vsra_w:
5736 case Intrinsic::loongarch_lsx_vsra_d:
5737 case Intrinsic::loongarch_lasx_xvsra_b:
5738 case Intrinsic::loongarch_lasx_xvsra_h:
5739 case Intrinsic::loongarch_lasx_xvsra_w:
5740 case Intrinsic::loongarch_lasx_xvsra_d:
5743 case Intrinsic::loongarch_lsx_vsrai_b:
5744 case Intrinsic::loongarch_lasx_xvsrai_b:
5746 lowerVectorSplatImm<3>(
N, 2, DAG));
5747 case Intrinsic::loongarch_lsx_vsrai_h:
5748 case Intrinsic::loongarch_lasx_xvsrai_h:
5750 lowerVectorSplatImm<4>(
N, 2, DAG));
5751 case Intrinsic::loongarch_lsx_vsrai_w:
5752 case Intrinsic::loongarch_lasx_xvsrai_w:
5754 lowerVectorSplatImm<5>(
N, 2, DAG));
5755 case Intrinsic::loongarch_lsx_vsrai_d:
5756 case Intrinsic::loongarch_lasx_xvsrai_d:
5758 lowerVectorSplatImm<6>(
N, 2, DAG));
5759 case Intrinsic::loongarch_lsx_vclz_b:
5760 case Intrinsic::loongarch_lsx_vclz_h:
5761 case Intrinsic::loongarch_lsx_vclz_w:
5762 case Intrinsic::loongarch_lsx_vclz_d:
5763 case Intrinsic::loongarch_lasx_xvclz_b:
5764 case Intrinsic::loongarch_lasx_xvclz_h:
5765 case Intrinsic::loongarch_lasx_xvclz_w:
5766 case Intrinsic::loongarch_lasx_xvclz_d:
5768 case Intrinsic::loongarch_lsx_vpcnt_b:
5769 case Intrinsic::loongarch_lsx_vpcnt_h:
5770 case Intrinsic::loongarch_lsx_vpcnt_w:
5771 case Intrinsic::loongarch_lsx_vpcnt_d:
5772 case Intrinsic::loongarch_lasx_xvpcnt_b:
5773 case Intrinsic::loongarch_lasx_xvpcnt_h:
5774 case Intrinsic::loongarch_lasx_xvpcnt_w:
5775 case Intrinsic::loongarch_lasx_xvpcnt_d:
5777 case Intrinsic::loongarch_lsx_vbitclr_b:
5778 case Intrinsic::loongarch_lsx_vbitclr_h:
5779 case Intrinsic::loongarch_lsx_vbitclr_w:
5780 case Intrinsic::loongarch_lsx_vbitclr_d:
5781 case Intrinsic::loongarch_lasx_xvbitclr_b:
5782 case Intrinsic::loongarch_lasx_xvbitclr_h:
5783 case Intrinsic::loongarch_lasx_xvbitclr_w:
5784 case Intrinsic::loongarch_lasx_xvbitclr_d:
5786 case Intrinsic::loongarch_lsx_vbitclri_b:
5787 case Intrinsic::loongarch_lasx_xvbitclri_b:
5788 return lowerVectorBitClearImm<3>(
N, DAG);
5789 case Intrinsic::loongarch_lsx_vbitclri_h:
5790 case Intrinsic::loongarch_lasx_xvbitclri_h:
5791 return lowerVectorBitClearImm<4>(
N, DAG);
5792 case Intrinsic::loongarch_lsx_vbitclri_w:
5793 case Intrinsic::loongarch_lasx_xvbitclri_w:
5794 return lowerVectorBitClearImm<5>(
N, DAG);
5795 case Intrinsic::loongarch_lsx_vbitclri_d:
5796 case Intrinsic::loongarch_lasx_xvbitclri_d:
5797 return lowerVectorBitClearImm<6>(
N, DAG);
5798 case Intrinsic::loongarch_lsx_vbitset_b:
5799 case Intrinsic::loongarch_lsx_vbitset_h:
5800 case Intrinsic::loongarch_lsx_vbitset_w:
5801 case Intrinsic::loongarch_lsx_vbitset_d:
5802 case Intrinsic::loongarch_lasx_xvbitset_b:
5803 case Intrinsic::loongarch_lasx_xvbitset_h:
5804 case Intrinsic::loongarch_lasx_xvbitset_w:
5805 case Intrinsic::loongarch_lasx_xvbitset_d: {
5806 EVT VecTy =
N->getValueType(0);
5812 case Intrinsic::loongarch_lsx_vbitseti_b:
5813 case Intrinsic::loongarch_lasx_xvbitseti_b:
5814 return lowerVectorBitSetImm<3>(
N, DAG);
5815 case Intrinsic::loongarch_lsx_vbitseti_h:
5816 case Intrinsic::loongarch_lasx_xvbitseti_h:
5817 return lowerVectorBitSetImm<4>(
N, DAG);
5818 case Intrinsic::loongarch_lsx_vbitseti_w:
5819 case Intrinsic::loongarch_lasx_xvbitseti_w:
5820 return lowerVectorBitSetImm<5>(
N, DAG);
5821 case Intrinsic::loongarch_lsx_vbitseti_d:
5822 case Intrinsic::loongarch_lasx_xvbitseti_d:
5823 return lowerVectorBitSetImm<6>(
N, DAG);
5824 case Intrinsic::loongarch_lsx_vbitrev_b:
5825 case Intrinsic::loongarch_lsx_vbitrev_h:
5826 case Intrinsic::loongarch_lsx_vbitrev_w:
5827 case Intrinsic::loongarch_lsx_vbitrev_d:
5828 case Intrinsic::loongarch_lasx_xvbitrev_b:
5829 case Intrinsic::loongarch_lasx_xvbitrev_h:
5830 case Intrinsic::loongarch_lasx_xvbitrev_w:
5831 case Intrinsic::loongarch_lasx_xvbitrev_d: {
5832 EVT VecTy =
N->getValueType(0);
5838 case Intrinsic::loongarch_lsx_vbitrevi_b:
5839 case Intrinsic::loongarch_lasx_xvbitrevi_b:
5840 return lowerVectorBitRevImm<3>(
N, DAG);
5841 case Intrinsic::loongarch_lsx_vbitrevi_h:
5842 case Intrinsic::loongarch_lasx_xvbitrevi_h:
5843 return lowerVectorBitRevImm<4>(
N, DAG);
5844 case Intrinsic::loongarch_lsx_vbitrevi_w:
5845 case Intrinsic::loongarch_lasx_xvbitrevi_w:
5846 return lowerVectorBitRevImm<5>(
N, DAG);
5847 case Intrinsic::loongarch_lsx_vbitrevi_d:
5848 case Intrinsic::loongarch_lasx_xvbitrevi_d:
5849 return lowerVectorBitRevImm<6>(
N, DAG);
5850 case Intrinsic::loongarch_lsx_vfadd_s:
5851 case Intrinsic::loongarch_lsx_vfadd_d:
5852 case Intrinsic::loongarch_lasx_xvfadd_s:
5853 case Intrinsic::loongarch_lasx_xvfadd_d:
5856 case Intrinsic::loongarch_lsx_vfsub_s:
5857 case Intrinsic::loongarch_lsx_vfsub_d:
5858 case Intrinsic::loongarch_lasx_xvfsub_s:
5859 case Intrinsic::loongarch_lasx_xvfsub_d:
5862 case Intrinsic::loongarch_lsx_vfmul_s:
5863 case Intrinsic::loongarch_lsx_vfmul_d:
5864 case Intrinsic::loongarch_lasx_xvfmul_s:
5865 case Intrinsic::loongarch_lasx_xvfmul_d:
5868 case Intrinsic::loongarch_lsx_vfdiv_s:
5869 case Intrinsic::loongarch_lsx_vfdiv_d:
5870 case Intrinsic::loongarch_lasx_xvfdiv_s:
5871 case Intrinsic::loongarch_lasx_xvfdiv_d:
5874 case Intrinsic::loongarch_lsx_vfmadd_s:
5875 case Intrinsic::loongarch_lsx_vfmadd_d:
5876 case Intrinsic::loongarch_lasx_xvfmadd_s:
5877 case Intrinsic::loongarch_lasx_xvfmadd_d:
5879 N->getOperand(2),
N->getOperand(3));
5880 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
5882 N->getOperand(1),
N->getOperand(2),
5883 legalizeIntrinsicImmArg<4>(
N, 3, DAG, Subtarget));
5884 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
5885 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
5887 N->getOperand(1),
N->getOperand(2),
5888 legalizeIntrinsicImmArg<3>(
N, 3, DAG, Subtarget));
5889 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
5890 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
5892 N->getOperand(1),
N->getOperand(2),
5893 legalizeIntrinsicImmArg<2>(
N, 3, DAG, Subtarget));
5894 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
5896 N->getOperand(1),
N->getOperand(2),
5897 legalizeIntrinsicImmArg<1>(
N, 3, DAG, Subtarget));
5898 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
5899 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
5900 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
5901 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
5902 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
5903 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
5904 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
5905 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
5909 case Intrinsic::loongarch_lsx_vreplve_b:
5910 case Intrinsic::loongarch_lsx_vreplve_h:
5911 case Intrinsic::loongarch_lsx_vreplve_w:
5912 case Intrinsic::loongarch_lsx_vreplve_d:
5913 case Intrinsic::loongarch_lasx_xvreplve_b:
5914 case Intrinsic::loongarch_lasx_xvreplve_h:
5915 case Intrinsic::loongarch_lasx_xvreplve_w:
5916 case Intrinsic::loongarch_lasx_xvreplve_d:
5946 "Unexpected value type!");
5955 MVT VT =
N->getSimpleValueType(0);
5989 APInt V =
C->getValueAPF().bitcastToAPInt();
6001 switch (
N->getOpcode()) {
6051 MF->
insert(It, BreakMBB);
6055 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->
end());
6056 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
6075 BreakMBB->addSuccessor(SinkMBB);
6087 switch (
MI.getOpcode()) {
6090 case LoongArch::PseudoVBZ:
6091 CondOpc = LoongArch::VSETEQZ_V;
6093 case LoongArch::PseudoVBZ_B:
6094 CondOpc = LoongArch::VSETANYEQZ_B;
6096 case LoongArch::PseudoVBZ_H:
6097 CondOpc = LoongArch::VSETANYEQZ_H;
6099 case LoongArch::PseudoVBZ_W:
6100 CondOpc = LoongArch::VSETANYEQZ_W;
6102 case LoongArch::PseudoVBZ_D:
6103 CondOpc = LoongArch::VSETANYEQZ_D;
6105 case LoongArch::PseudoVBNZ:
6106 CondOpc = LoongArch::VSETNEZ_V;
6108 case LoongArch::PseudoVBNZ_B:
6109 CondOpc = LoongArch::VSETALLNEZ_B;
6111 case LoongArch::PseudoVBNZ_H:
6112 CondOpc = LoongArch::VSETALLNEZ_H;
6114 case LoongArch::PseudoVBNZ_W:
6115 CondOpc = LoongArch::VSETALLNEZ_W;
6117 case LoongArch::PseudoVBNZ_D:
6118 CondOpc = LoongArch::VSETALLNEZ_D;
6120 case LoongArch::PseudoXVBZ:
6121 CondOpc = LoongArch::XVSETEQZ_V;
6123 case LoongArch::PseudoXVBZ_B:
6124 CondOpc = LoongArch::XVSETANYEQZ_B;
6126 case LoongArch::PseudoXVBZ_H:
6127 CondOpc = LoongArch::XVSETANYEQZ_H;
6129 case LoongArch::PseudoXVBZ_W:
6130 CondOpc = LoongArch::XVSETANYEQZ_W;
6132 case LoongArch::PseudoXVBZ_D:
6133 CondOpc = LoongArch::XVSETANYEQZ_D;
6135 case LoongArch::PseudoXVBNZ:
6136 CondOpc = LoongArch::XVSETNEZ_V;
6138 case LoongArch::PseudoXVBNZ_B:
6139 CondOpc = LoongArch::XVSETALLNEZ_B;
6141 case LoongArch::PseudoXVBNZ_H:
6142 CondOpc = LoongArch::XVSETALLNEZ_H;
6144 case LoongArch::PseudoXVBNZ_W:
6145 CondOpc = LoongArch::XVSETALLNEZ_W;
6147 case LoongArch::PseudoXVBNZ_D:
6148 CondOpc = LoongArch::XVSETALLNEZ_D;
6163 F->insert(It, FalseBB);
6164 F->insert(It, TrueBB);
6165 F->insert(It, SinkBB);
6168 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
6172 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
6181 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6189 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6197 MI.getOperand(0).getReg())
6204 MI.eraseFromParent();
6212 unsigned BroadcastOp;
6214 switch (
MI.getOpcode()) {
6217 case LoongArch::PseudoXVINSGR2VR_B:
6219 BroadcastOp = LoongArch::XVREPLGR2VR_B;
6220 InsOp = LoongArch::XVEXTRINS_B;
6222 case LoongArch::PseudoXVINSGR2VR_H:
6224 BroadcastOp = LoongArch::XVREPLGR2VR_H;
6225 InsOp = LoongArch::XVEXTRINS_H;
6237 unsigned Idx =
MI.getOperand(3).getImm();
6239 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
6241 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
6242 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
6245 .
addReg(XSrc, 0, LoongArch::sub_128);
6247 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
6248 : LoongArch::VINSGR2VR_B),
6257 .
addImm(LoongArch::sub_128);
6259 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6260 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6264 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
6275 MI.eraseFromParent();
6282 assert(Subtarget.hasExtLSX());
6289 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6290 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6291 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
6295 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
6296 : LoongArch::VINSGR2VR_W),
6303 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
6307 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
6308 : LoongArch::VPICKVE2GR_W),
6313 MI.eraseFromParent();
6327 unsigned EleBits = 8;
6328 unsigned NotOpc = 0;
6331 switch (
MI.getOpcode()) {
6334 case LoongArch::PseudoVMSKLTZ_B:
6335 MskOpc = LoongArch::VMSKLTZ_B;
6337 case LoongArch::PseudoVMSKLTZ_H:
6338 MskOpc = LoongArch::VMSKLTZ_H;
6341 case LoongArch::PseudoVMSKLTZ_W:
6342 MskOpc = LoongArch::VMSKLTZ_W;
6345 case LoongArch::PseudoVMSKLTZ_D:
6346 MskOpc = LoongArch::VMSKLTZ_D;
6349 case LoongArch::PseudoVMSKGEZ_B:
6350 MskOpc = LoongArch::VMSKGEZ_B;
6352 case LoongArch::PseudoVMSKEQZ_B:
6353 MskOpc = LoongArch::VMSKNZ_B;
6354 NotOpc = LoongArch::VNOR_V;
6356 case LoongArch::PseudoVMSKNEZ_B:
6357 MskOpc = LoongArch::VMSKNZ_B;
6359 case LoongArch::PseudoXVMSKLTZ_B:
6360 MskOpc = LoongArch::XVMSKLTZ_B;
6361 RC = &LoongArch::LASX256RegClass;
6363 case LoongArch::PseudoXVMSKLTZ_H:
6364 MskOpc = LoongArch::XVMSKLTZ_H;
6365 RC = &LoongArch::LASX256RegClass;
6368 case LoongArch::PseudoXVMSKLTZ_W:
6369 MskOpc = LoongArch::XVMSKLTZ_W;
6370 RC = &LoongArch::LASX256RegClass;
6373 case LoongArch::PseudoXVMSKLTZ_D:
6374 MskOpc = LoongArch::XVMSKLTZ_D;
6375 RC = &LoongArch::LASX256RegClass;
6378 case LoongArch::PseudoXVMSKGEZ_B:
6379 MskOpc = LoongArch::XVMSKGEZ_B;
6380 RC = &LoongArch::LASX256RegClass;
6382 case LoongArch::PseudoXVMSKEQZ_B:
6383 MskOpc = LoongArch::XVMSKNZ_B;
6384 NotOpc = LoongArch::XVNOR_V;
6385 RC = &LoongArch::LASX256RegClass;
6387 case LoongArch::PseudoXVMSKNEZ_B:
6388 MskOpc = LoongArch::XVMSKNZ_B;
6389 RC = &LoongArch::LASX256RegClass;
6404 if (
TRI->getRegSizeInBits(*RC) > 128) {
6405 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6406 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6414 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
6415 : LoongArch::BSTRINS_W),
6419 .
addImm(256 / EleBits - 1)
6427 MI.eraseFromParent();
6434 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
6435 "Unexpected instruction");
6447 MI.eraseFromParent();
6454 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
6455 "Unexpected instruction");
6461 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
6471 MI.eraseFromParent();
6476 switch (
MI.getOpcode()) {
6479 case LoongArch::Select_GPR_Using_CC_GPR:
6515 if (
MI.getOperand(2).isReg())
6516 RHS =
MI.getOperand(2).getReg();
6517 auto CC =
static_cast<unsigned>(
MI.getOperand(3).getImm());
6521 SelectDests.
insert(
MI.getOperand(0).getReg());
6525 SequenceMBBI != E; ++SequenceMBBI) {
6526 if (SequenceMBBI->isDebugInstr())
6529 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
6530 !SequenceMBBI->getOperand(2).isReg() ||
6531 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
6532 SequenceMBBI->getOperand(3).getImm() != CC ||
6533 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
6534 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
6536 LastSelectPseudo = &*SequenceMBBI;
6538 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
6541 if (SequenceMBBI->hasUnmodeledSideEffects() ||
6542 SequenceMBBI->mayLoadOrStore() ||
6543 SequenceMBBI->usesCustomInsertionHook())
6546 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
6561 F->insert(
I, IfFalseMBB);
6562 F->insert(
I, TailMBB);
6565 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
6571 TailMBB->
push_back(DebugInstr->removeFromParent());
6575 TailMBB->
splice(TailMBB->
end(), HeadMBB,
6585 if (
MI.getOperand(2).isImm())
6597 auto SelectMBBI =
MI.getIterator();
6598 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
6600 while (SelectMBBI != SelectEnd) {
6601 auto Next = std::next(SelectMBBI);
6605 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
6606 .
addReg(SelectMBBI->getOperand(4).getReg())
6608 .
addReg(SelectMBBI->getOperand(5).getReg())
6615 F->getProperties().resetNoPHIs();
6624 switch (
MI.getOpcode()) {
6627 case LoongArch::DIV_W:
6628 case LoongArch::DIV_WU:
6629 case LoongArch::MOD_W:
6630 case LoongArch::MOD_WU:
6631 case LoongArch::DIV_D:
6632 case LoongArch::DIV_DU:
6633 case LoongArch::MOD_D:
6634 case LoongArch::MOD_DU:
6637 case LoongArch::WRFCSR: {
6639 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
6640 .
addReg(
MI.getOperand(1).getReg());
6641 MI.eraseFromParent();
6644 case LoongArch::RDFCSR: {
6647 MI.getOperand(0).getReg())
6648 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
6650 MI.eraseFromParent();
6653 case LoongArch::Select_GPR_Using_CC_GPR:
6655 case LoongArch::BuildPairF64Pseudo:
6657 case LoongArch::SplitPairF64Pseudo:
6659 case LoongArch::PseudoVBZ:
6660 case LoongArch::PseudoVBZ_B:
6661 case LoongArch::PseudoVBZ_H:
6662 case LoongArch::PseudoVBZ_W:
6663 case LoongArch::PseudoVBZ_D:
6664 case LoongArch::PseudoVBNZ:
6665 case LoongArch::PseudoVBNZ_B:
6666 case LoongArch::PseudoVBNZ_H:
6667 case LoongArch::PseudoVBNZ_W:
6668 case LoongArch::PseudoVBNZ_D:
6669 case LoongArch::PseudoXVBZ:
6670 case LoongArch::PseudoXVBZ_B:
6671 case LoongArch::PseudoXVBZ_H:
6672 case LoongArch::PseudoXVBZ_W:
6673 case LoongArch::PseudoXVBZ_D:
6674 case LoongArch::PseudoXVBNZ:
6675 case LoongArch::PseudoXVBNZ_B:
6676 case LoongArch::PseudoXVBNZ_H:
6677 case LoongArch::PseudoXVBNZ_W:
6678 case LoongArch::PseudoXVBNZ_D:
6680 case LoongArch::PseudoXVINSGR2VR_B:
6681 case LoongArch::PseudoXVINSGR2VR_H:
6683 case LoongArch::PseudoCTPOP:
6685 case LoongArch::PseudoVMSKLTZ_B:
6686 case LoongArch::PseudoVMSKLTZ_H:
6687 case LoongArch::PseudoVMSKLTZ_W:
6688 case LoongArch::PseudoVMSKLTZ_D:
6689 case LoongArch::PseudoVMSKGEZ_B:
6690 case LoongArch::PseudoVMSKEQZ_B:
6691 case LoongArch::PseudoVMSKNEZ_B:
6692 case LoongArch::PseudoXVMSKLTZ_B:
6693 case LoongArch::PseudoXVMSKLTZ_H:
6694 case LoongArch::PseudoXVMSKLTZ_W:
6695 case LoongArch::PseudoXVMSKLTZ_D:
6696 case LoongArch::PseudoXVMSKGEZ_B:
6697 case LoongArch::PseudoXVMSKEQZ_B:
6698 case LoongArch::PseudoXVMSKNEZ_B:
6700 case TargetOpcode::STATEPOINT:
6706 MI.addOperand(*
MI.getMF(),
6708 LoongArch::R1,
true,
6719 unsigned *
Fast)
const {
6720 if (!Subtarget.hasUAL())
6734#define NODE_NAME_CASE(node) \
6735 case LoongArchISD::node: \
6736 return "LoongArchISD::" #node;
6835#undef NODE_NAME_CASE
6848 LoongArch::R7, LoongArch::R8, LoongArch::R9,
6849 LoongArch::R10, LoongArch::R11};
6853 LoongArch::F3, LoongArch::F4, LoongArch::F5,
6854 LoongArch::F6, LoongArch::F7};
6857 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
6858 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
6861 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
6862 LoongArch::VR6, LoongArch::VR7};
6865 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
6866 LoongArch::XR6, LoongArch::XR7};
6872 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
6874 unsigned GRLenInBytes = GRLen / 8;
6907 unsigned ValNo,
MVT ValVT,
6910 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
6911 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
6912 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
6917 if (IsRet && ValNo > 1)
6921 bool UseGPRForFloat =
true;
6931 UseGPRForFloat = ArgFlags.
isVarArg();
6944 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
6947 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
6950 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
6959 "PendingLocs and PendingArgFlags out of sync");
6963 UseGPRForFloat =
true;
6965 if (UseGPRForFloat && ValVT == MVT::f32) {
6968 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
6971 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
6974 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7016 PendingLocs.
size() <= 2) {
7017 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7022 PendingLocs.
clear();
7023 PendingArgFlags.
clear();
7030 unsigned StoreSizeBytes = GRLen / 8;
7033 if (ValVT == MVT::f32 && !UseGPRForFloat)
7035 else if (ValVT == MVT::f64 && !UseGPRForFloat)
7049 if (!PendingLocs.
empty()) {
7051 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7052 for (
auto &It : PendingLocs) {
7054 It.convertToReg(Reg);
7059 PendingLocs.clear();
7060 PendingArgFlags.
clear();
7063 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7064 "Expected an GRLenVT at this stage");
7081void LoongArchTargetLowering::analyzeInputArgs(
7084 LoongArchCCAssignFn Fn)
const {
7086 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7088 Type *ArgTy =
nullptr;
7090 ArgTy = FType->getReturnType();
7091 else if (Ins[i].isOrigArg())
7092 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7096 CCInfo, IsRet, ArgTy)) {
7097 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7104void LoongArchTargetLowering::analyzeOutputArgs(
7107 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7108 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7109 MVT ArgVT = Outs[i].VT;
7110 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7114 CCInfo, IsRet, OrigTy)) {
7115 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7156 if (In.isOrigArg()) {
7161 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
7162 (
BitWidth < 32 && In.Flags.isZExt())) {
7212 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7225 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7255 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
7259 LoongArch::R23, LoongArch::R24, LoongArch::R25,
7260 LoongArch::R26, LoongArch::R27, LoongArch::R28,
7261 LoongArch::R29, LoongArch::R30, LoongArch::R31};
7268 if (LocVT == MVT::f32) {
7271 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
7272 LoongArch::F26, LoongArch::F27};
7279 if (LocVT == MVT::f64) {
7282 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
7283 LoongArch::F30_64, LoongArch::F31_64};
7313 "GHC calling convention requires the F and D extensions");
7318 unsigned GRLenInBytes = Subtarget.
getGRLen() / 8;
7320 std::vector<SDValue> OutChains;
7329 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
7331 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
7348 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
7349 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
7350 assert(ArgPartOffset == 0);
7351 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
7353 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
7377 int VaArgOffset, VarArgsSaveSize;
7383 VarArgsSaveSize = 0;
7385 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() -
Idx);
7386 VaArgOffset = -VarArgsSaveSize;
7392 LoongArchFI->setVarArgsFrameIndex(FI);
7400 VarArgsSaveSize += GRLenInBytes;
7405 for (
unsigned I =
Idx;
I < ArgRegs.
size();
7406 ++
I, VaArgOffset += GRLenInBytes) {
7414 cast<StoreSDNode>(Store.getNode())
7416 ->setValue((
Value *)
nullptr);
7417 OutChains.push_back(Store);
7419 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
7424 if (!OutChains.empty()) {
7425 OutChains.push_back(Chain);
7440 if (
N->getNumValues() != 1)
7442 if (!
N->hasNUsesOfValue(1, 0))
7445 SDNode *Copy = *
N->user_begin();
7451 if (Copy->getGluedNode())
7455 bool HasRet =
false;
7456 for (
SDNode *Node : Copy->users()) {
7465 Chain = Copy->getOperand(0);
7470bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
7474 auto CalleeCC = CLI.CallConv;
7475 auto &Outs = CLI.Outs;
7477 auto CallerCC = Caller.getCallingConv();
7484 for (
auto &VA : ArgLocs)
7490 auto IsCallerStructRet = Caller.hasStructRetAttr();
7491 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
7492 if (IsCallerStructRet || IsCalleeStructRet)
7496 for (
auto &Arg : Outs)
7497 if (Arg.Flags.isByVal())
7502 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
7503 if (CalleeCC != CallerCC) {
7504 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
7505 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
7543 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
7547 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
7553 "site marked musttail");
7560 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7562 if (!Flags.isByVal())
7566 unsigned Size = Flags.getByValSize();
7567 Align Alignment = Flags.getNonZeroByValAlign();
7574 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
7576 false,
nullptr, std::nullopt,
7588 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
7591 SDValue ArgValue = OutVals[OutIdx];
7600 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
7612 if (!StackPtr.getNode())
7624 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
7639 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
7640 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
7641 assert(ArgPartOffset == 0);
7646 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
7647 SDValue PartValue = OutVals[OutIdx + 1];
7648 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
7659 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
7663 for (
const auto &Part : Parts) {
7664 SDValue PartValue = Part.first;
7665 SDValue PartOffset = Part.second;
7672 ArgValue = SpillSlot;
7678 if (Flags.isByVal())
7679 ArgValue = ByValArgs[j++];
7686 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
7687 "for passing parameters");
7690 if (!StackPtr.getNode())
7703 if (!MemOpChains.
empty())
7709 for (
auto &Reg : RegsToPass) {
7710 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
7737 for (
auto &Reg : RegsToPass)
7743 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
7744 assert(Mask &&
"Missing call preserved mask for calling convention");
7762 assert(Subtarget.
is64Bit() &&
"Medium code model requires LA64");
7766 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
7789 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
7792 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
7793 auto &VA = RVLocs[i];
7801 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
7802 assert(VA.needsCustom());
7808 RetValue, RetValue2);
7825 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7829 Outs[i].Flags, CCInfo,
true,
nullptr))
7855 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
7856 SDValue Val = OutVals[OutIdx];
7865 DAG.
getVTList(MVT::i32, MVT::i32), Val);
7869 Register RegHi = RVLocs[++i].getLocReg();
7899 if (!Subtarget.hasExtLSX())
7902 if (VT == MVT::f32) {
7903 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
7904 return (masked == 0x3e000000 || masked == 0x40000000);
7907 if (VT == MVT::f64) {
7908 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
7909 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
7915bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
7916 bool ForCodeSize)
const {
7918 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7920 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7922 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
7933bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
7936 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
7938 if (isa<LoadInst>(
I))
7943 Type *Ty =
I->getOperand(0)->getType();
7962 return Y.getValueType().isScalarInteger() && !isa<ConstantSDNode>(
Y);
7968 unsigned Intrinsic)
const {
7969 switch (Intrinsic) {
7972 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
7973 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
7974 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
7975 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
7977 Info.memVT = MVT::i32;
7978 Info.ptrVal =
I.getArgOperand(0);
7997 "Unable to expand");
7998 unsigned MinWordSize = 4;
8011 Intrinsic::ptrmask, {PtrTy, IntTy},
8012 {
Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8016 Value *PtrLSB = Builder.
CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8018 ShiftAmt = Builder.
CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8020 ConstantInt::get(WordType,
8024 Value *ValOperand_Shifted =
8026 ShiftAmt,
"ValOperand_Shifted");
8029 NewOperand = Builder.
CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8031 NewOperand = ValOperand_Shifted;
8057 if (Subtarget.hasLAM_BH() && Subtarget.
is64Bit() &&
8065 if (Subtarget.hasLAMCAS()) {
8087 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
8089 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
8091 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
8093 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
8095 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
8097 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
8099 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
8101 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
8111 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
8113 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
8115 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
8117 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
8119 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
8121 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
8123 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
8125 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
8137 if (Subtarget.hasLAMCAS())
8149 unsigned GRLen = Subtarget.
getGRLen();
8151 Value *FailureOrdering =
8153 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
8155 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
8162 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
8187 unsigned GRLen = Subtarget.
getGRLen();
8216 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
8219 Builder.
CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
8246 const Constant *PersonalityFn)
const {
8247 return LoongArch::R4;
8251 const Constant *PersonalityFn)
const {
8252 return LoongArch::R5;
8263 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
8264 return RefinementSteps;
8269 int &RefinementSteps,
8270 bool &UseOneConstNR,
8271 bool Reciprocal)
const {
8272 if (Subtarget.hasFrecipe()) {
8276 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8277 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8278 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8279 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8280 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8299 int &RefinementSteps)
const {
8300 if (Subtarget.hasFrecipe()) {
8304 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8305 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8306 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8307 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8308 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8325LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
8345 if (Constraint.
size() == 1) {
8346 switch (Constraint[0]) {
8362 if (Constraint ==
"ZC" || Constraint ==
"ZB")
8378std::pair<unsigned, const TargetRegisterClass *>
8379LoongArchTargetLowering::getRegForInlineAsmConstraint(
8383 if (Constraint.
size() == 1) {
8384 switch (Constraint[0]) {
8389 return std::make_pair(0U, &LoongArch::GPRRegClass);
8391 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
8393 if (Subtarget.hasBasicF() && VT == MVT::f32)
8394 return std::make_pair(0U, &LoongArch::FPR32RegClass);
8395 if (Subtarget.hasBasicD() && VT == MVT::f64)
8396 return std::make_pair(0U, &LoongArch::FPR64RegClass);
8397 if (Subtarget.hasExtLSX() &&
8398 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
8399 return std::make_pair(0U, &LoongArch::LSX128RegClass);
8400 if (Subtarget.hasExtLASX() &&
8401 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
8402 return std::make_pair(0U, &LoongArch::LASX256RegClass);
8422 bool IsFP = Constraint[2] ==
'f';
8423 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
8424 std::pair<unsigned, const TargetRegisterClass *>
R;
8426 TRI, join_items(
"", Temp.first, Temp.second), VT);
8429 unsigned RegNo =
R.first;
8430 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
8431 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
8432 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
8433 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
8443void LoongArchTargetLowering::LowerAsmOperandForConstraint(
8447 if (Constraint.
size() == 1) {
8448 switch (Constraint[0]) {
8451 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8453 if (isInt<16>(CVal))
8460 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8462 if (isInt<12>(CVal))
8469 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op))
8470 if (
C->getZExtValue() == 0)
8476 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
8478 if (isUInt<12>(CVal))
8490#define GET_REGISTER_MATCHER
8491#include "LoongArchGenAsmMatcher.inc"
8497 std::string NewRegName =
Name.second.str();
8504 if (!ReservedRegs.
test(Reg))
8520 if (
auto *ConstNode = dyn_cast<ConstantSDNode>(
C.getNode())) {
8521 const APInt &Imm = ConstNode->getAPIntValue();
8523 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
8524 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
8527 if (ConstNode->hasOneUse() &&
8528 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
8529 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
8535 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
8536 unsigned Shifts = Imm.countr_zero();
8542 APInt ImmPop = Imm.ashr(Shifts);
8543 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
8547 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
8548 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
8549 (ImmSmall - Imm).isPowerOf2())
8559 Type *Ty,
unsigned AS,
8575 !(isShiftedInt<14, 2>(AM.
BaseOffs) && Subtarget.hasUAL()))
8602 return isInt<12>(Imm);
8606 return isInt<12>(Imm);
8613 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
8614 EVT MemVT = LD->getMemoryVT();
8615 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
8626 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
8635 if (
Y.getValueType().isVector())
8638 return !isa<ConstantSDNode>(
Y);
8647 Type *Ty,
bool IsSigned)
const {
8668 Align &PrefAlign)
const {
8669 if (!isa<MemIntrinsic>(CI))
8674 PrefAlign =
Align(8);
8677 PrefAlign =
Align(4);
8692bool LoongArchTargetLowering::splitValueIntoRegisterParts(
8694 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
8695 bool IsABIRegCopy = CC.has_value();
8698 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
8699 PartVT == MVT::f32) {
8714SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
8716 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
8717 bool IsABIRegCopy = CC.has_value();
8719 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
8720 PartVT == MVT::f32) {
8733MVT LoongArchTargetLowering::getRegisterTypeForCallingConv(
LLVMContext &Context,
8737 if (VT == MVT::f16 && Subtarget.hasBasicF())
8743unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
8746 if (VT == MVT::f16 && Subtarget.hasBasicF())
8755 unsigned Depth)
const {
8756 EVT VT =
Op.getValueType();
8758 unsigned Opc =
Op.getOpcode();
8765 MVT SrcVT = Src.getSimpleValueType();
8770 if (OriginalDemandedBits.
countr_zero() >= NumElts)
8774 APInt KnownUndef, KnownZero;
8790 if (KnownSrc.
One[SrcBits - 1])
8792 else if (KnownSrc.
Zero[SrcBits - 1])
8797 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
8804 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)
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
const MCPhysReg ArgFPR32s[]
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VSHUF4I (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 void canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
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 checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue 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 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 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 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 lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
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 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)
#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 lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
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_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
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 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.
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)