30#include "llvm/IR/IntrinsicsLoongArch.h"
40#define DEBUG_TYPE "loongarch-isel-lowering"
45 cl::desc(
"Trap on integer division by zero."),
52 MVT GRLenVT = Subtarget.getGRLenVT();
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)
140 if (Subtarget.is64Bit()) {
168 if (!Subtarget.is64Bit()) {
174 if (Subtarget.hasBasicD())
186 if (Subtarget.hasBasicF()) {
217 if (Subtarget.is64Bit())
220 if (!Subtarget.hasBasicD()) {
222 if (Subtarget.is64Bit()) {
231 if (Subtarget.hasBasicD()) {
263 if (Subtarget.is64Bit())
269 if (Subtarget.hasExtLSX()) {
284 for (
MVT VT : LSXVTs) {
298 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
319 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
321 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
323 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
327 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
345 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
346 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
361 if (Subtarget.hasExtLASX()) {
362 for (
MVT VT : LASXVTs) {
377 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
399 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
401 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
403 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
407 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
429 if (Subtarget.hasExtLSX()) {
436 if (Subtarget.hasExtLASX())
459 if (Subtarget.hasLAMCAS())
462 if (Subtarget.hasSCQ()) {
479 switch (
Op.getOpcode()) {
480 case ISD::ATOMIC_FENCE:
481 return lowerATOMIC_FENCE(
Op, DAG);
483 return lowerEH_DWARF_CFA(
Op, DAG);
485 return lowerGlobalAddress(
Op, DAG);
487 return lowerGlobalTLSAddress(
Op, DAG);
489 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
491 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
493 return lowerINTRINSIC_VOID(
Op, DAG);
495 return lowerBlockAddress(
Op, DAG);
497 return lowerJumpTable(
Op, DAG);
499 return lowerShiftLeftParts(
Op, DAG);
501 return lowerShiftRightParts(
Op, DAG,
true);
503 return lowerShiftRightParts(
Op, DAG,
false);
505 return lowerConstantPool(
Op, DAG);
507 return lowerFP_TO_SINT(
Op, DAG);
509 return lowerBITCAST(
Op, DAG);
511 return lowerUINT_TO_FP(
Op, DAG);
513 return lowerSINT_TO_FP(
Op, DAG);
515 return lowerVASTART(
Op, DAG);
517 return lowerFRAMEADDR(
Op, DAG);
519 return lowerRETURNADDR(
Op, DAG);
521 return lowerWRITE_REGISTER(
Op, DAG);
523 return lowerINSERT_VECTOR_ELT(
Op, DAG);
525 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
527 return lowerBUILD_VECTOR(
Op, DAG);
529 return lowerCONCAT_VECTORS(
Op, DAG);
531 return lowerVECTOR_SHUFFLE(
Op, DAG);
533 return lowerBITREVERSE(
Op, DAG);
535 return lowerSCALAR_TO_VECTOR(
Op, DAG);
537 return lowerPREFETCH(
Op, DAG);
539 return lowerSELECT(
Op, DAG);
541 return lowerBRCOND(
Op, DAG);
542 case ISD::FP_TO_FP16:
543 return lowerFP_TO_FP16(
Op, DAG);
544 case ISD::FP16_TO_FP:
545 return lowerFP16_TO_FP(
Op, DAG);
546 case ISD::FP_TO_BF16:
547 return lowerFP_TO_BF16(
Op, DAG);
548 case ISD::BF16_TO_FP:
549 return lowerBF16_TO_FP(
Op, DAG);
550 case ISD::VECREDUCE_ADD:
551 return lowerVECREDUCE_ADD(
Op, DAG);
552 case ISD::VECREDUCE_AND:
553 case ISD::VECREDUCE_OR:
554 case ISD::VECREDUCE_XOR:
555 case ISD::VECREDUCE_SMAX:
556 case ISD::VECREDUCE_SMIN:
557 case ISD::VECREDUCE_UMAX:
558 case ISD::VECREDUCE_UMIN:
559 return lowerVECREDUCE(
Op, DAG);
576 MVT OpVT =
Op.getSimpleValueType();
582 unsigned LegalVecSize = 128;
583 bool isLASX256Vector =
593 if (isLASX256Vector) {
598 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
604 if (isLASX256Vector) {
629 MVT OpVT =
Op.getSimpleValueType();
643 for (
int i = NumEles; i > 1; i /= 2) {
646 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
655 unsigned IsData =
Op.getConstantOperandVal(4);
660 return Op.getOperand(0);
675 if (
LHS == LHS2 &&
RHS == RHS2) {
680 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
696 MVT VT =
N->getSimpleValueType(0);
727 if (~TrueVal == FalseVal) {
767 unsigned SelOpNo = 0;
777 unsigned ConstSelOpNo = 1;
778 unsigned OtherSelOpNo = 2;
785 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
790 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
796 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
798 std::swap(NewConstOps[0], NewConstOps[1]);
810 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
812 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
815 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
816 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
836 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
850 int64_t
C = RHSC->getSExtValue();
893 MVT VT =
Op.getSimpleValueType();
894 MVT GRLenVT = Subtarget.getGRLenVT();
899 if (
Op.hasOneUse()) {
900 unsigned UseOpc =
Op->user_begin()->getOpcode();
902 SDNode *BinOp = *
Op->user_begin();
909 return lowerSELECT(NewSel, DAG);
949 if (TrueVal - 1 == FalseVal)
951 if (TrueVal + 1 == FalseVal)
958 RHS == TrueV &&
LHS == FalseV) {
990 MVT GRLenVT = Subtarget.getGRLenVT();
1002 Op.getOperand(0),
LHS,
RHS, TargetCC,
1006 Op.getOperand(0), CondV,
Op.getOperand(2));
1016LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1019 MVT OpVT =
Op.getSimpleValueType();
1030 EVT ResTy =
Op->getValueType(0);
1041 for (
unsigned int i = 0; i < NewEltNum; i++) {
1044 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1063 for (
unsigned int i = 0; i < NewEltNum; i++)
1064 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1065 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1083 if (EltBits > 32 || EltBits == 1)
1111 int MaskOffset,
const APInt &Zeroable) {
1112 int Size = Mask.size();
1113 unsigned SizeInBits =
Size * ScalarSizeInBits;
1115 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1116 for (
int i = 0; i <
Size; i += Scale)
1117 for (
int j = 0; j < Shift; ++j)
1118 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1126 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1127 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1132 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1133 for (
int i = 0; i !=
Size; i += Scale) {
1134 unsigned Pos =
Left ? i + Shift : i;
1135 unsigned Low =
Left ? i : i + Shift;
1136 unsigned Len = Scale - Shift;
1141 int ShiftEltBits = ScalarSizeInBits * Scale;
1142 bool ByteShift = ShiftEltBits > 64;
1145 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1149 Scale = ByteShift ? Scale / 2 : Scale;
1155 return (
int)ShiftAmt;
1158 unsigned MaxWidth = 128;
1159 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1160 for (
int Shift = 1; Shift != Scale; ++Shift)
1161 for (
bool Left : {
true,
false})
1162 if (CheckZeros(Shift, Scale,
Left)) {
1163 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1188 const APInt &Zeroable) {
1189 int Size = Mask.size();
1203 Mask,
Size, Zeroable);
1211 "Illegal integer vector type");
1220template <
typename ValType>
1223 unsigned CheckStride,
1225 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1229 if (*
I != -1 && *
I != ExpectedIndex)
1231 ExpectedIndex += ExpectedIndexStride;
1235 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1247 int Size = Mask.size();
1257 int ScalarSizeInBits = VectorSizeInBits /
Size;
1258 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1259 (void)ScalarSizeInBits;
1261 for (
int i = 0; i <
Size; ++i) {
1267 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1284 RepeatedMask.
assign(LaneSize, -1);
1285 int Size = Mask.size();
1286 for (
int i = 0; i <
Size; ++i) {
1287 assert(Mask[i] == -1 || Mask[i] >= 0);
1290 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1297 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1298 if (RepeatedMask[i % LaneSize] < 0)
1300 RepeatedMask[i % LaneSize] = LocalM;
1301 else if (RepeatedMask[i % LaneSize] != LocalM)
1318 int NumElts = RepeatedMask.
size();
1320 int Scale = 16 / NumElts;
1322 for (
int i = 0; i < NumElts; ++i) {
1323 int M = RepeatedMask[i];
1324 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1325 "Unexpected mask index.");
1330 int StartIdx = i - (M % NumElts);
1337 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1340 Rotation = CandidateRotation;
1341 else if (Rotation != CandidateRotation)
1345 SDValue MaskV = M < NumElts ? V1 : V2;
1356 else if (TargetV != MaskV)
1361 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1362 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1371 return Rotation * Scale;
1390 if (ByteRotation <= 0)
1397 int LoByteShift = 16 - ByteRotation;
1398 int HiByteShift = ByteRotation;
1421 const APInt &Zeroable) {
1435 for (
int i = 0; i < NumElements; i++) {
1439 if (i % Scale != 0) {
1450 SDValue V = M < NumElements ? V1 : V2;
1451 M = M % NumElements;
1454 Offset = M - (i / Scale);
1457 if (
Offset % (NumElements / Scale))
1459 }
else if (InputV != V)
1462 if (M != (
Offset + (i / Scale)))
1473 if (
Offset >= (NumElements / 2)) {
1475 Offset -= (NumElements / 2);
1482 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1486 }
while (Scale > 1);
1492 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1493 NumExtElements *= 2) {
1513 int SplatIndex = -1;
1514 for (
const auto &M : Mask) {
1521 if (SplatIndex == -1)
1524 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1526 APInt Imm(64, SplatIndex);
1557 unsigned SubVecSize = 4;
1558 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1561 int SubMask[4] = {-1, -1, -1, -1};
1562 for (
unsigned i = 0; i < SubVecSize; ++i) {
1563 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1569 M -= 4 * (j / SubVecSize);
1570 if (M < 0 || M >= 4)
1576 if (SubMask[i] == -1)
1580 else if (M != -1 && M != SubMask[i])
1587 for (
int i = SubVecSize - 1; i >= 0; --i) {
1600 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1627 const auto &Begin = Mask.begin();
1628 const auto &End = Mask.end();
1629 SDValue OriV1 = V1, OriV2 = V2;
1667 const auto &Begin = Mask.begin();
1668 const auto &End = Mask.end();
1669 SDValue OriV1 = V1, OriV2 = V2;
1708 const auto &Begin = Mask.begin();
1709 const auto &End = Mask.end();
1710 unsigned HalfSize = Mask.size() / 2;
1711 SDValue OriV1 = V1, OriV2 = V2;
1751 const auto &Begin = Mask.begin();
1752 const auto &End = Mask.end();
1753 SDValue OriV1 = V1, OriV2 = V2;
1791 const auto &Begin = Mask.begin();
1792 const auto &Mid = Mask.begin() + Mask.size() / 2;
1793 const auto &End = Mask.end();
1794 SDValue OriV1 = V1, OriV2 = V2;
1833 const auto &Begin = Mask.begin();
1834 const auto &Mid = Mask.begin() + Mask.size() / 2;
1835 const auto &End = Mask.end();
1836 SDValue OriV1 = V1, OriV2 = V2;
1890 "Vector type is unsupported for lsx!");
1892 "Two operands have different types!");
1894 "Unexpected mask size for shuffle!");
1895 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
1897 APInt KnownUndef, KnownZero;
1899 APInt Zeroable = KnownUndef | KnownZero;
1962 int SplatIndex = -1;
1963 for (
const auto &M : Mask) {
1970 if (SplatIndex == -1)
1973 const auto &Begin = Mask.begin();
1974 const auto &End = Mask.end();
1975 unsigned HalfSize = Mask.size() / 2;
1977 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1995 if (Mask.size() <= 4)
2005 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2009 unsigned HalfSize = NumElts / 2;
2010 bool FrontLo =
true, FrontHi =
true;
2011 bool BackLo =
true, BackHi =
true;
2013 auto inRange = [](
int val,
int low,
int high) {
2014 return (val == -1) || (val >= low && val < high);
2017 for (
unsigned i = 0; i < HalfSize; ++i) {
2018 int Fronti = Mask[i];
2019 int Backi = Mask[i + HalfSize];
2021 FrontLo &=
inRange(Fronti, 0, HalfSize);
2022 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2023 BackLo &=
inRange(Backi, 0, HalfSize);
2024 BackHi &=
inRange(Backi, HalfSize, NumElts);
2030 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2034 for (
unsigned i = 0; i < NumElts; ++i)
2061 const auto &Begin = Mask.begin();
2062 const auto &End = Mask.end();
2063 unsigned HalfSize = Mask.size() / 2;
2064 unsigned LeftSize = HalfSize / 2;
2065 SDValue OriV1 = V1, OriV2 = V2;
2072 Mask.size() + HalfSize - LeftSize, 1) &&
2074 Mask.size() + HalfSize + LeftSize, 1))
2085 Mask.size() + HalfSize - LeftSize, 1) &&
2087 Mask.size() + HalfSize + LeftSize, 1))
2100 const auto &Begin = Mask.begin();
2101 const auto &End = Mask.end();
2102 unsigned HalfSize = Mask.size() / 2;
2103 SDValue OriV1 = V1, OriV2 = V2;
2110 Mask.size() + HalfSize, 1))
2121 Mask.size() + HalfSize, 1))
2134 const auto &Begin = Mask.begin();
2135 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2136 const auto &Mid = Mask.begin() + Mask.size() / 2;
2137 const auto &RightMid = Mask.end() - Mask.size() / 4;
2138 const auto &End = Mask.end();
2139 unsigned HalfSize = Mask.size() / 2;
2140 SDValue OriV1 = V1, OriV2 = V2;
2169 const auto &Begin = Mask.begin();
2170 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2171 const auto &Mid = Mask.begin() + Mask.size() / 2;
2172 const auto &RightMid = Mask.end() - Mask.size() / 4;
2173 const auto &End = Mask.end();
2174 unsigned HalfSize = Mask.size() / 2;
2175 SDValue OriV1 = V1, OriV2 = V2;
2205 int MaskSize = Mask.size();
2206 int HalfSize = Mask.size() / 2;
2207 const auto &Begin = Mask.begin();
2208 const auto &Mid = Mask.begin() + HalfSize;
2209 const auto &End = Mask.end();
2221 for (
auto it = Begin; it < Mid; it++) {
2224 else if ((*it >= 0 && *it < HalfSize) ||
2225 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2226 int M = *it < HalfSize ? *it : *it - HalfSize;
2231 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2233 for (
auto it = Mid; it < End; it++) {
2236 else if ((*it >= HalfSize && *it < MaskSize) ||
2237 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2238 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2243 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2273 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2275 int MaskSize = Mask.size();
2276 int HalfSize = Mask.size() / 2;
2279 HalfMaskType preMask =
None, postMask =
None;
2281 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2282 return M < 0 || (M >= 0 && M < HalfSize) ||
2283 (M >= MaskSize && M < MaskSize + HalfSize);
2285 preMask = HighLaneTy;
2286 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2287 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2288 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2290 preMask = LowLaneTy;
2292 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2293 return M < 0 || (M >= 0 && M < HalfSize) ||
2294 (M >= MaskSize && M < MaskSize + HalfSize);
2296 postMask = HighLaneTy;
2297 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2298 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2299 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2301 postMask = LowLaneTy;
2309 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2312 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2325 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2326 *it = *it < 0 ? *it : *it - HalfSize;
2328 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2329 *it = *it < 0 ? *it : *it + HalfSize;
2331 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2344 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2345 *it = *it < 0 ? *it : *it - HalfSize;
2347 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2360 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2361 *it = *it < 0 ? *it : *it + HalfSize;
2384 int Size = Mask.size();
2385 int LaneSize =
Size / 2;
2387 bool LaneCrossing[2] = {
false,
false};
2388 for (
int i = 0; i <
Size; ++i)
2389 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2390 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2393 if (!LaneCrossing[0] && !LaneCrossing[1])
2397 InLaneMask.
assign(Mask.begin(), Mask.end());
2398 for (
int i = 0; i <
Size; ++i) {
2399 int &M = InLaneMask[i];
2402 if (((M %
Size) / LaneSize) != (i / LaneSize))
2403 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2408 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2423 "Vector type is unsupported for lasx!");
2425 "Two operands have different types!");
2427 "Unexpected mask size for shuffle!");
2428 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2429 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2435 APInt KnownUndef, KnownZero;
2437 APInt Zeroable = KnownUndef | KnownZero;
2474 Subtarget, Zeroable)))
2490 ArrayRef<int> OrigMask = SVOp->
getMask();
2493 MVT VT =
Op.getSimpleValueType();
2497 bool V1IsUndef = V1.
isUndef();
2498 bool V2IsUndef = V2.
isUndef();
2499 if (V1IsUndef && V2IsUndef)
2512 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2513 SmallVector<int, 8> NewMask(OrigMask);
2514 for (
int &M : NewMask)
2515 if (M >= NumElements)
2521 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2522 (void)MaskUpperLimit;
2524 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2525 "Out of bounds shuffle index");
2547 std::tie(Res, Chain) =
2548 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2549 if (Subtarget.is64Bit())
2566 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2567 CallOptions,
DL, Chain);
2573 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2579 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2580 if (Subtarget.is64Bit())
2587 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2588 MVT VT =
Op.getSimpleValueType();
2597 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
2614 "Unsupported vector type for broadcast.");
2617 bool IsIdeneity =
true;
2619 for (
int i = 0; i !=
NumOps; i++) {
2621 if (
Op.getOpcode() != ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2633 auto ExtType = LN->getExtensionType();
2639 ? DAG.
getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other)
2641 SDValue Ops[] = {LN->getChain(), LN->getBasePtr(), LN->getOffset()};
2659 for (
unsigned i = 1; i <
Ops.size(); ++i) {
2673 EVT ResTy,
unsigned first) {
2677 first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
2680 Node->op_begin() + first + NumElts);
2689 MVT VT =
Node->getSimpleValueType(0);
2690 EVT ResTy =
Op->getValueType(0);
2693 APInt SplatValue, SplatUndef;
2694 unsigned SplatBitSize;
2697 bool UseSameConstant =
true;
2702 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
2703 (!Subtarget.hasExtLASX() || !Is256Vec))
2709 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
2711 SplatBitSize <= 64) {
2713 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2717 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
2723 if ((Is128Vec && ResTy == MVT::v4i32) ||
2724 (Is256Vec && ResTy == MVT::v8i32))
2730 switch (SplatBitSize) {
2734 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
2737 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
2740 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
2743 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
2751 if (ViaVecTy != ResTy)
2752 Result = DAG.
getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
2760 for (
unsigned i = 0; i < NumElts; ++i) {
2765 ConstantValue = Opi;
2766 else if (ConstantValue != Opi)
2767 UseSameConstant =
false;
2772 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
2774 for (
unsigned i = 0; i < NumElts; ++i) {
2792 BitVector UndefElements;
2793 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
2794 UndefElements.
count() == 0) {
2798 EVT FillTy = Is256Vec
2804 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
2807 unsigned SplatLen = NumElts / SeqLen;
2813 if (SplatEltTy == MVT::i128)
2814 SplatTy = MVT::v4i64;
2824 DL, SplatTy, SrcVec);
2839 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
2840 ResTy == MVT::v4f64) {
2841 unsigned NonUndefCount = 0;
2842 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
2843 if (!
Node->getOperand(i).isUndef()) {
2845 if (NonUndefCount > 1)
2849 if (NonUndefCount == 1)
2862 VecTy, NumElts / 2);
2873 MVT ResVT =
Op.getSimpleValueType();
2877 unsigned NumFreezeUndef = 0;
2878 unsigned NumZero = 0;
2879 unsigned NumNonZero = 0;
2880 unsigned NonZeros = 0;
2881 SmallSet<SDValue, 4> Undefs;
2882 for (
unsigned i = 0; i != NumOperands; ++i) {
2897 assert(i <
sizeof(NonZeros) * CHAR_BIT);
2904 if (NumNonZero > 2) {
2908 Ops.slice(0, NumOperands / 2));
2910 Ops.slice(NumOperands / 2));
2923 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
2925 for (
unsigned i = 0; i != NumOperands; ++i) {
2926 if ((NonZeros & (1 << i)) == 0)
2937LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
2939 MVT EltVT =
Op.getSimpleValueType();
2944 MVT GRLenVT = Subtarget.getGRLenVT();
2976 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
2996LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
2998 MVT VT =
Op.getSimpleValueType();
3020 for (
unsigned i = 0; i < NumElts; ++i)
3043 return DAG.
getNode(ISD::MEMBARRIER,
DL, MVT::Other,
Op.getOperand(0));
3051 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3053 "On LA64, only 64-bit registers can be written.");
3054 return Op.getOperand(0);
3057 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3059 "On LA32, only 32-bit registers can be written.");
3060 return Op.getOperand(0);
3070 "be a constant integer");
3076 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3077 EVT VT =
Op.getValueType();
3080 unsigned Depth =
Op.getConstantOperandVal(0);
3081 int GRLenInBytes = Subtarget.getGRLen() / 8;
3084 int Offset = -(GRLenInBytes * 2);
3096 if (
Op.getConstantOperandVal(0) != 0) {
3098 "return address can only be determined for the current frame");
3104 MVT GRLenVT = Subtarget.getGRLenVT();
3116 auto Size = Subtarget.getGRLen() / 8;
3124 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3134 MachinePointerInfo(SV));
3139 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3140 !Subtarget.hasBasicD() &&
"unexpected target features");
3146 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3160 EVT RetVT =
Op.getValueType();
3166 std::tie(Result, Chain) =
3173 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3174 !Subtarget.hasBasicD() &&
"unexpected target features");
3185 EVT RetVT =
Op.getValueType();
3191 std::tie(Result, Chain) =
3200 EVT VT =
Op.getValueType();
3204 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3205 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3209 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3224 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
3226 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3227 !Subtarget.hasBasicD()) {
3234 return DAG.
getNode(ISD::BITCAST,
DL,
Op.getValueType(), Trunc);
3251 N->getOffset(), Flags);
3259template <
class NodeTy>
3262 bool IsLocal)
const {
3273 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3344 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3346 const GlobalValue *GV =
N->getGlobal();
3358 unsigned Opc,
bool UseGOT,
3362 MVT GRLenVT = Subtarget.getGRLenVT();
3376 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3414 Args.emplace_back(Load, CallTy);
3417 TargetLowering::CallLoweringInfo CLI(DAG);
3432 const GlobalValue *GV =
N->getGlobal();
3446LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3453 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3456 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3469 return getDynamicTLSAddr(
N, DAG,
3470 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3471 : LoongArch::PseudoLA_TLS_GD,
3478 return getDynamicTLSAddr(
N, DAG,
3479 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3480 : LoongArch::PseudoLA_TLS_LD,
3485 return getStaticTLSAddr(
N, DAG,
3486 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3487 : LoongArch::PseudoLA_TLS_IE,
3494 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3498 return getTLSDescAddr(
N, DAG,
3499 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3500 : LoongArch::PseudoLA_TLS_DESC,
3504template <
unsigned N>
3509 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
3510 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
3512 ": argument out of range.");
3519LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3521 switch (
Op.getConstantOperandVal(0)) {
3524 case Intrinsic::thread_pointer: {
3528 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3529 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3530 case Intrinsic::loongarch_lsx_vreplvei_d:
3531 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3533 case Intrinsic::loongarch_lsx_vreplvei_w:
3534 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3535 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3536 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3537 case Intrinsic::loongarch_lasx_xvpickve_d:
3538 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3540 case Intrinsic::loongarch_lasx_xvinsve0_d:
3542 case Intrinsic::loongarch_lsx_vsat_b:
3543 case Intrinsic::loongarch_lsx_vsat_bu:
3544 case Intrinsic::loongarch_lsx_vrotri_b:
3545 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3546 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3547 case Intrinsic::loongarch_lsx_vsrlri_b:
3548 case Intrinsic::loongarch_lsx_vsrari_b:
3549 case Intrinsic::loongarch_lsx_vreplvei_h:
3550 case Intrinsic::loongarch_lasx_xvsat_b:
3551 case Intrinsic::loongarch_lasx_xvsat_bu:
3552 case Intrinsic::loongarch_lasx_xvrotri_b:
3553 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3554 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3555 case Intrinsic::loongarch_lasx_xvsrlri_b:
3556 case Intrinsic::loongarch_lasx_xvsrari_b:
3557 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3558 case Intrinsic::loongarch_lasx_xvpickve_w:
3559 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3561 case Intrinsic::loongarch_lasx_xvinsve0_w:
3563 case Intrinsic::loongarch_lsx_vsat_h:
3564 case Intrinsic::loongarch_lsx_vsat_hu:
3565 case Intrinsic::loongarch_lsx_vrotri_h:
3566 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3567 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3568 case Intrinsic::loongarch_lsx_vsrlri_h:
3569 case Intrinsic::loongarch_lsx_vsrari_h:
3570 case Intrinsic::loongarch_lsx_vreplvei_b:
3571 case Intrinsic::loongarch_lasx_xvsat_h:
3572 case Intrinsic::loongarch_lasx_xvsat_hu:
3573 case Intrinsic::loongarch_lasx_xvrotri_h:
3574 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3575 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3576 case Intrinsic::loongarch_lasx_xvsrlri_h:
3577 case Intrinsic::loongarch_lasx_xvsrari_h:
3578 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3580 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3581 case Intrinsic::loongarch_lsx_vsrani_b_h:
3582 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3583 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3584 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3585 case Intrinsic::loongarch_lsx_vssrani_b_h:
3586 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3587 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3588 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3589 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3590 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3591 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3592 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3593 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3594 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3595 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3596 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3597 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3598 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3599 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3600 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3601 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3602 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3603 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3605 case Intrinsic::loongarch_lsx_vsat_w:
3606 case Intrinsic::loongarch_lsx_vsat_wu:
3607 case Intrinsic::loongarch_lsx_vrotri_w:
3608 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3609 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3610 case Intrinsic::loongarch_lsx_vsrlri_w:
3611 case Intrinsic::loongarch_lsx_vsrari_w:
3612 case Intrinsic::loongarch_lsx_vslei_bu:
3613 case Intrinsic::loongarch_lsx_vslei_hu:
3614 case Intrinsic::loongarch_lsx_vslei_wu:
3615 case Intrinsic::loongarch_lsx_vslei_du:
3616 case Intrinsic::loongarch_lsx_vslti_bu:
3617 case Intrinsic::loongarch_lsx_vslti_hu:
3618 case Intrinsic::loongarch_lsx_vslti_wu:
3619 case Intrinsic::loongarch_lsx_vslti_du:
3620 case Intrinsic::loongarch_lsx_vbsll_v:
3621 case Intrinsic::loongarch_lsx_vbsrl_v:
3622 case Intrinsic::loongarch_lasx_xvsat_w:
3623 case Intrinsic::loongarch_lasx_xvsat_wu:
3624 case Intrinsic::loongarch_lasx_xvrotri_w:
3625 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
3626 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
3627 case Intrinsic::loongarch_lasx_xvsrlri_w:
3628 case Intrinsic::loongarch_lasx_xvsrari_w:
3629 case Intrinsic::loongarch_lasx_xvslei_bu:
3630 case Intrinsic::loongarch_lasx_xvslei_hu:
3631 case Intrinsic::loongarch_lasx_xvslei_wu:
3632 case Intrinsic::loongarch_lasx_xvslei_du:
3633 case Intrinsic::loongarch_lasx_xvslti_bu:
3634 case Intrinsic::loongarch_lasx_xvslti_hu:
3635 case Intrinsic::loongarch_lasx_xvslti_wu:
3636 case Intrinsic::loongarch_lasx_xvslti_du:
3637 case Intrinsic::loongarch_lasx_xvbsll_v:
3638 case Intrinsic::loongarch_lasx_xvbsrl_v:
3640 case Intrinsic::loongarch_lsx_vseqi_b:
3641 case Intrinsic::loongarch_lsx_vseqi_h:
3642 case Intrinsic::loongarch_lsx_vseqi_w:
3643 case Intrinsic::loongarch_lsx_vseqi_d:
3644 case Intrinsic::loongarch_lsx_vslei_b:
3645 case Intrinsic::loongarch_lsx_vslei_h:
3646 case Intrinsic::loongarch_lsx_vslei_w:
3647 case Intrinsic::loongarch_lsx_vslei_d:
3648 case Intrinsic::loongarch_lsx_vslti_b:
3649 case Intrinsic::loongarch_lsx_vslti_h:
3650 case Intrinsic::loongarch_lsx_vslti_w:
3651 case Intrinsic::loongarch_lsx_vslti_d:
3652 case Intrinsic::loongarch_lasx_xvseqi_b:
3653 case Intrinsic::loongarch_lasx_xvseqi_h:
3654 case Intrinsic::loongarch_lasx_xvseqi_w:
3655 case Intrinsic::loongarch_lasx_xvseqi_d:
3656 case Intrinsic::loongarch_lasx_xvslei_b:
3657 case Intrinsic::loongarch_lasx_xvslei_h:
3658 case Intrinsic::loongarch_lasx_xvslei_w:
3659 case Intrinsic::loongarch_lasx_xvslei_d:
3660 case Intrinsic::loongarch_lasx_xvslti_b:
3661 case Intrinsic::loongarch_lasx_xvslti_h:
3662 case Intrinsic::loongarch_lasx_xvslti_w:
3663 case Intrinsic::loongarch_lasx_xvslti_d:
3665 case Intrinsic::loongarch_lsx_vsrlni_h_w:
3666 case Intrinsic::loongarch_lsx_vsrani_h_w:
3667 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
3668 case Intrinsic::loongarch_lsx_vsrarni_h_w:
3669 case Intrinsic::loongarch_lsx_vssrlni_h_w:
3670 case Intrinsic::loongarch_lsx_vssrani_h_w:
3671 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
3672 case Intrinsic::loongarch_lsx_vssrani_hu_w:
3673 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
3674 case Intrinsic::loongarch_lsx_vssrarni_h_w:
3675 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
3676 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
3677 case Intrinsic::loongarch_lsx_vfrstpi_b:
3678 case Intrinsic::loongarch_lsx_vfrstpi_h:
3679 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
3680 case Intrinsic::loongarch_lasx_xvsrani_h_w:
3681 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
3682 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
3683 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
3684 case Intrinsic::loongarch_lasx_xvssrani_h_w:
3685 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
3686 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
3687 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
3688 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
3689 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
3690 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
3691 case Intrinsic::loongarch_lasx_xvfrstpi_b:
3692 case Intrinsic::loongarch_lasx_xvfrstpi_h:
3694 case Intrinsic::loongarch_lsx_vsat_d:
3695 case Intrinsic::loongarch_lsx_vsat_du:
3696 case Intrinsic::loongarch_lsx_vrotri_d:
3697 case Intrinsic::loongarch_lsx_vsrlri_d:
3698 case Intrinsic::loongarch_lsx_vsrari_d:
3699 case Intrinsic::loongarch_lasx_xvsat_d:
3700 case Intrinsic::loongarch_lasx_xvsat_du:
3701 case Intrinsic::loongarch_lasx_xvrotri_d:
3702 case Intrinsic::loongarch_lasx_xvsrlri_d:
3703 case Intrinsic::loongarch_lasx_xvsrari_d:
3705 case Intrinsic::loongarch_lsx_vsrlni_w_d:
3706 case Intrinsic::loongarch_lsx_vsrani_w_d:
3707 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
3708 case Intrinsic::loongarch_lsx_vsrarni_w_d:
3709 case Intrinsic::loongarch_lsx_vssrlni_w_d:
3710 case Intrinsic::loongarch_lsx_vssrani_w_d:
3711 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
3712 case Intrinsic::loongarch_lsx_vssrani_wu_d:
3713 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
3714 case Intrinsic::loongarch_lsx_vssrarni_w_d:
3715 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
3716 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
3717 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
3718 case Intrinsic::loongarch_lasx_xvsrani_w_d:
3719 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
3720 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
3721 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
3722 case Intrinsic::loongarch_lasx_xvssrani_w_d:
3723 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
3724 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
3725 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
3726 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
3727 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
3728 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
3730 case Intrinsic::loongarch_lsx_vsrlni_d_q:
3731 case Intrinsic::loongarch_lsx_vsrani_d_q:
3732 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
3733 case Intrinsic::loongarch_lsx_vsrarni_d_q:
3734 case Intrinsic::loongarch_lsx_vssrlni_d_q:
3735 case Intrinsic::loongarch_lsx_vssrani_d_q:
3736 case Intrinsic::loongarch_lsx_vssrlni_du_q:
3737 case Intrinsic::loongarch_lsx_vssrani_du_q:
3738 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
3739 case Intrinsic::loongarch_lsx_vssrarni_d_q:
3740 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
3741 case Intrinsic::loongarch_lsx_vssrarni_du_q:
3742 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
3743 case Intrinsic::loongarch_lasx_xvsrani_d_q:
3744 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
3745 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
3746 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
3747 case Intrinsic::loongarch_lasx_xvssrani_d_q:
3748 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
3749 case Intrinsic::loongarch_lasx_xvssrani_du_q:
3750 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
3751 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
3752 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
3753 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
3755 case Intrinsic::loongarch_lsx_vnori_b:
3756 case Intrinsic::loongarch_lsx_vshuf4i_b:
3757 case Intrinsic::loongarch_lsx_vshuf4i_h:
3758 case Intrinsic::loongarch_lsx_vshuf4i_w:
3759 case Intrinsic::loongarch_lasx_xvnori_b:
3760 case Intrinsic::loongarch_lasx_xvshuf4i_b:
3761 case Intrinsic::loongarch_lasx_xvshuf4i_h:
3762 case Intrinsic::loongarch_lasx_xvshuf4i_w:
3763 case Intrinsic::loongarch_lasx_xvpermi_d:
3765 case Intrinsic::loongarch_lsx_vshuf4i_d:
3766 case Intrinsic::loongarch_lsx_vpermi_w:
3767 case Intrinsic::loongarch_lsx_vbitseli_b:
3768 case Intrinsic::loongarch_lsx_vextrins_b:
3769 case Intrinsic::loongarch_lsx_vextrins_h:
3770 case Intrinsic::loongarch_lsx_vextrins_w:
3771 case Intrinsic::loongarch_lsx_vextrins_d:
3772 case Intrinsic::loongarch_lasx_xvshuf4i_d:
3773 case Intrinsic::loongarch_lasx_xvpermi_w:
3774 case Intrinsic::loongarch_lasx_xvpermi_q:
3775 case Intrinsic::loongarch_lasx_xvbitseli_b:
3776 case Intrinsic::loongarch_lasx_xvextrins_b:
3777 case Intrinsic::loongarch_lasx_xvextrins_h:
3778 case Intrinsic::loongarch_lasx_xvextrins_w:
3779 case Intrinsic::loongarch_lasx_xvextrins_d:
3781 case Intrinsic::loongarch_lsx_vrepli_b:
3782 case Intrinsic::loongarch_lsx_vrepli_h:
3783 case Intrinsic::loongarch_lsx_vrepli_w:
3784 case Intrinsic::loongarch_lsx_vrepli_d:
3785 case Intrinsic::loongarch_lasx_xvrepli_b:
3786 case Intrinsic::loongarch_lasx_xvrepli_h:
3787 case Intrinsic::loongarch_lasx_xvrepli_w:
3788 case Intrinsic::loongarch_lasx_xvrepli_d:
3790 case Intrinsic::loongarch_lsx_vldi:
3791 case Intrinsic::loongarch_lasx_xvldi:
3807LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
3810 MVT GRLenVT = Subtarget.getGRLenVT();
3811 EVT VT =
Op.getValueType();
3813 const StringRef ErrorMsgOOR =
"argument out of range";
3814 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3815 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3817 switch (
Op.getConstantOperandVal(1)) {
3820 case Intrinsic::loongarch_crc_w_b_w:
3821 case Intrinsic::loongarch_crc_w_h_w:
3822 case Intrinsic::loongarch_crc_w_w_w:
3823 case Intrinsic::loongarch_crc_w_d_w:
3824 case Intrinsic::loongarch_crcc_w_b_w:
3825 case Intrinsic::loongarch_crcc_w_h_w:
3826 case Intrinsic::loongarch_crcc_w_w_w:
3827 case Intrinsic::loongarch_crcc_w_d_w:
3829 case Intrinsic::loongarch_csrrd_w:
3830 case Intrinsic::loongarch_csrrd_d: {
3831 unsigned Imm =
Op.getConstantOperandVal(2);
3837 case Intrinsic::loongarch_csrwr_w:
3838 case Intrinsic::loongarch_csrwr_d: {
3839 unsigned Imm =
Op.getConstantOperandVal(3);
3843 {Chain,
Op.getOperand(2),
3846 case Intrinsic::loongarch_csrxchg_w:
3847 case Intrinsic::loongarch_csrxchg_d: {
3848 unsigned Imm =
Op.getConstantOperandVal(4);
3852 {Chain,
Op.getOperand(2),
Op.getOperand(3),
3855 case Intrinsic::loongarch_iocsrrd_d: {
3860#define IOCSRRD_CASE(NAME, NODE) \
3861 case Intrinsic::loongarch_##NAME: { \
3862 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
3863 {Chain, Op.getOperand(2)}); \
3869 case Intrinsic::loongarch_cpucfg: {
3871 {Chain,
Op.getOperand(2)});
3873 case Intrinsic::loongarch_lddir_d: {
3874 unsigned Imm =
Op.getConstantOperandVal(3);
3879 case Intrinsic::loongarch_movfcsr2gr: {
3880 if (!Subtarget.hasBasicF())
3882 unsigned Imm =
Op.getConstantOperandVal(2);
3888 case Intrinsic::loongarch_lsx_vld:
3889 case Intrinsic::loongarch_lsx_vldrepl_b:
3890 case Intrinsic::loongarch_lasx_xvld:
3891 case Intrinsic::loongarch_lasx_xvldrepl_b:
3895 case Intrinsic::loongarch_lsx_vldrepl_h:
3896 case Intrinsic::loongarch_lasx_xvldrepl_h:
3900 Op,
"argument out of range or not a multiple of 2", DAG)
3902 case Intrinsic::loongarch_lsx_vldrepl_w:
3903 case Intrinsic::loongarch_lasx_xvldrepl_w:
3907 Op,
"argument out of range or not a multiple of 4", DAG)
3909 case Intrinsic::loongarch_lsx_vldrepl_d:
3910 case Intrinsic::loongarch_lasx_xvldrepl_d:
3914 Op,
"argument out of range or not a multiple of 8", DAG)
3925 return Op.getOperand(0);
3931 MVT GRLenVT = Subtarget.getGRLenVT();
3933 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
3935 const StringRef ErrorMsgOOR =
"argument out of range";
3936 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3937 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
3938 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3940 switch (IntrinsicEnum) {
3944 case Intrinsic::loongarch_cacop_d:
3945 case Intrinsic::loongarch_cacop_w: {
3946 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
3948 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
3957 case Intrinsic::loongarch_dbar: {
3964 case Intrinsic::loongarch_ibar: {
3971 case Intrinsic::loongarch_break: {
3978 case Intrinsic::loongarch_movgr2fcsr: {
3979 if (!Subtarget.hasBasicF())
3989 case Intrinsic::loongarch_syscall: {
3996#define IOCSRWR_CASE(NAME, NODE) \
3997 case Intrinsic::loongarch_##NAME: { \
3998 SDValue Op3 = Op.getOperand(3); \
3999 return Subtarget.is64Bit() \
4000 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4001 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4002 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4003 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4010 case Intrinsic::loongarch_iocsrwr_d: {
4011 return !Subtarget.is64Bit()
4018#define ASRT_LE_GT_CASE(NAME) \
4019 case Intrinsic::loongarch_##NAME: { \
4020 return !Subtarget.is64Bit() \
4021 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4026#undef ASRT_LE_GT_CASE
4027 case Intrinsic::loongarch_ldpte_d: {
4028 unsigned Imm =
Op.getConstantOperandVal(3);
4029 return !Subtarget.is64Bit()
4034 case Intrinsic::loongarch_lsx_vst:
4035 case Intrinsic::loongarch_lasx_xvst:
4039 case Intrinsic::loongarch_lasx_xvstelm_b:
4044 case Intrinsic::loongarch_lsx_vstelm_b:
4049 case Intrinsic::loongarch_lasx_xvstelm_h:
4054 Op,
"argument out of range or not a multiple of 2", DAG)
4056 case Intrinsic::loongarch_lsx_vstelm_h:
4061 Op,
"argument out of range or not a multiple of 2", DAG)
4063 case Intrinsic::loongarch_lasx_xvstelm_w:
4068 Op,
"argument out of range or not a multiple of 4", DAG)
4070 case Intrinsic::loongarch_lsx_vstelm_w:
4075 Op,
"argument out of range or not a multiple of 4", DAG)
4077 case Intrinsic::loongarch_lasx_xvstelm_d:
4082 Op,
"argument out of range or not a multiple of 8", DAG)
4084 case Intrinsic::loongarch_lsx_vstelm_d:
4089 Op,
"argument out of range or not a multiple of 8", DAG)
4100 EVT VT =
Lo.getValueType();
4141 EVT VT =
Lo.getValueType();
4233 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4234 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4238 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4244 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4271 StringRef ErrorMsg,
bool WithChain =
true) {
4276 Results.push_back(
N->getOperand(0));
4279template <
unsigned N>
4284 const StringRef ErrorMsgOOR =
"argument out of range";
4285 unsigned Imm =
Node->getConstantOperandVal(2);
4319 switch (
N->getConstantOperandVal(0)) {
4322 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4326 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4327 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4331 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4335 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4339 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4340 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4344 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4348 case Intrinsic::loongarch_lsx_bz_b:
4349 case Intrinsic::loongarch_lsx_bz_h:
4350 case Intrinsic::loongarch_lsx_bz_w:
4351 case Intrinsic::loongarch_lsx_bz_d:
4352 case Intrinsic::loongarch_lasx_xbz_b:
4353 case Intrinsic::loongarch_lasx_xbz_h:
4354 case Intrinsic::loongarch_lasx_xbz_w:
4355 case Intrinsic::loongarch_lasx_xbz_d:
4359 case Intrinsic::loongarch_lsx_bz_v:
4360 case Intrinsic::loongarch_lasx_xbz_v:
4364 case Intrinsic::loongarch_lsx_bnz_b:
4365 case Intrinsic::loongarch_lsx_bnz_h:
4366 case Intrinsic::loongarch_lsx_bnz_w:
4367 case Intrinsic::loongarch_lsx_bnz_d:
4368 case Intrinsic::loongarch_lasx_xbnz_b:
4369 case Intrinsic::loongarch_lasx_xbnz_h:
4370 case Intrinsic::loongarch_lasx_xbnz_w:
4371 case Intrinsic::loongarch_lasx_xbnz_d:
4375 case Intrinsic::loongarch_lsx_bnz_v:
4376 case Intrinsic::loongarch_lasx_xbnz_v:
4386 assert(
N->getValueType(0) == MVT::i128 &&
4387 "AtomicCmpSwap on types less than 128 should be legal");
4391 switch (
MemOp->getMergedOrdering()) {
4395 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4399 Opcode = LoongArch::PseudoCmpXchg128;
4406 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4407 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4408 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4409 NewVal.first, NewVal.second,
N->getOperand(0)};
4412 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4423 EVT VT =
N->getValueType(0);
4424 switch (
N->getOpcode()) {
4429 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4430 "Unexpected custom legalisation");
4437 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4438 "Unexpected custom legalisation");
4440 Subtarget.hasDiv32() && VT == MVT::i32
4447 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4448 "Unexpected custom legalisation");
4456 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4457 "Unexpected custom legalisation");
4461 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4462 "Unexpected custom legalisation");
4469 if (Src.getValueType() == MVT::f16)
4470 Src = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Src);
4480 EVT OpVT = Src.getValueType();
4484 std::tie(Result, Chain) =
4489 case ISD::BITCAST: {
4491 EVT SrcVT = Src.getValueType();
4492 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
4493 Subtarget.hasBasicF()) {
4497 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
4499 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4507 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4508 "Unexpected custom legalisation");
4511 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4517 assert((VT == MVT::i16 || VT == MVT::i32) &&
4518 "Unexpected custom legalization");
4519 MVT GRLenVT = Subtarget.getGRLenVT();
4539 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
4540 "Unexpected custom legalization");
4541 MVT GRLenVT = Subtarget.getGRLenVT();
4559 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4560 "Unexpected custom legalisation");
4567 MVT GRLenVT = Subtarget.getGRLenVT();
4568 const StringRef ErrorMsgOOR =
"argument out of range";
4569 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4570 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4572 switch (
N->getConstantOperandVal(1)) {
4575 case Intrinsic::loongarch_movfcsr2gr: {
4576 if (!Subtarget.hasBasicF()) {
4593#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4594 case Intrinsic::loongarch_##NAME: { \
4595 SDValue NODE = DAG.getNode( \
4596 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4597 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4598 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4599 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4600 Results.push_back(NODE.getValue(1)); \
4609#undef CRC_CASE_EXT_BINARYOP
4611#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4612 case Intrinsic::loongarch_##NAME: { \
4613 SDValue NODE = DAG.getNode( \
4614 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4616 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4617 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4618 Results.push_back(NODE.getValue(1)); \
4623#undef CRC_CASE_EXT_UNARYOP
4624#define CSR_CASE(ID) \
4625 case Intrinsic::loongarch_##ID: { \
4626 if (!Subtarget.is64Bit()) \
4627 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
4635 case Intrinsic::loongarch_csrrd_w: {
4649 case Intrinsic::loongarch_csrwr_w: {
4650 unsigned Imm =
N->getConstantOperandVal(3);
4664 case Intrinsic::loongarch_csrxchg_w: {
4665 unsigned Imm =
N->getConstantOperandVal(4);
4680#define IOCSRRD_CASE(NAME, NODE) \
4681 case Intrinsic::loongarch_##NAME: { \
4682 SDValue IOCSRRDResults = \
4683 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4684 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
4685 Results.push_back( \
4686 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
4687 Results.push_back(IOCSRRDResults.getValue(1)); \
4694 case Intrinsic::loongarch_cpucfg: {
4703 case Intrinsic::loongarch_lddir_d: {
4704 if (!Subtarget.is64Bit()) {
4714 if (Subtarget.is64Bit())
4716 "On LA64, only 64-bit registers can be read.");
4719 "On LA32, only 32-bit registers can be read.");
4721 Results.push_back(
N->getOperand(0));
4732 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
4740 case ISD::ATOMIC_CMP_SWAP: {
4745 MVT VT =
N->getSimpleValueType(0);
4751 EVT InVT = In.getValueType();
4762 for (
unsigned I = 0;
I < MinElts; ++
I)
4763 TruncMask[
I] = Scale *
I;
4765 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
4766 MVT SVT = In.getSimpleValueType().getScalarType();
4772 "Illegal vector type in truncation");
4791 SDValue FirstOperand =
N->getOperand(0);
4792 SDValue SecondOperand =
N->getOperand(1);
4793 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
4794 EVT ValTy =
N->getValueType(0);
4797 unsigned SMIdx, SMLen;
4803 if (!Subtarget.has32S())
4825 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
4840 if (SMIdx + SMLen > ValTy.getSizeInBits())
4859 NewOperand = FirstOperand;
4862 msb = lsb + SMLen - 1;
4866 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
4879 if (!Subtarget.has32S())
4891 SDValue FirstOperand =
N->getOperand(0);
4893 EVT ValTy =
N->getValueType(0);
4896 unsigned MaskIdx, MaskLen;
4911 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
4927 switch (Src.getOpcode()) {
4930 return Src.getOperand(0).getValueSizeInBits() ==
Size;
4940 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
4953 switch (Src.getOpcode()) {
4963 Src.getOpcode(),
DL, SExtVT,
4969 DL, SExtVT, Src.getOperand(0),
4981 EVT VT =
N->getValueType(0);
4983 EVT SrcVT = Src.getValueType();
4985 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
4990 EVT CmpVT = Src.getOperand(0).getValueType();
4995 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5023 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5030 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5054 EVT VT =
N->getValueType(0);
5056 EVT SrcVT = Src.getValueType();
5072 bool UseLASX =
false;
5073 bool PropagateSExt =
false;
5075 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5076 EVT CmpVT = Src.getOperand(0).getValueType();
5085 SExtVT = MVT::v2i64;
5088 SExtVT = MVT::v4i32;
5090 SExtVT = MVT::v4i64;
5092 PropagateSExt =
true;
5096 SExtVT = MVT::v8i16;
5098 SExtVT = MVT::v8i32;
5100 PropagateSExt =
true;
5104 SExtVT = MVT::v16i8;
5106 SExtVT = MVT::v16i16;
5108 PropagateSExt =
true;
5112 SExtVT = MVT::v32i8;
5120 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5121 if (Src.getSimpleValueType() == MVT::v32i8) {
5129 }
else if (UseLASX) {
5148 EVT ValTy =
N->getValueType(0);
5149 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5152 unsigned ValBits = ValTy.getSizeInBits();
5153 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5155 bool SwapAndRetried =
false;
5158 if (!Subtarget.has32S())
5164 if (ValBits != 32 && ValBits != 64)
5179 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5182 (MaskIdx0 + MaskLen0 <= ValBits)) {
5203 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5204 (MaskIdx0 + MaskLen0 <= ValBits)) {
5221 (MaskIdx0 + MaskLen0 <= 64) &&
5229 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5230 : (MaskIdx0 + MaskLen0 - 1),
5246 (MaskIdx0 + MaskLen0 <= ValBits)) {
5269 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5270 : (MaskIdx0 + MaskLen0 - 1),
5285 unsigned MaskIdx, MaskLen;
5286 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5313 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5327 if (!SwapAndRetried) {
5329 SwapAndRetried =
true;
5333 SwapAndRetried =
false;
5359 if (!SwapAndRetried) {
5361 SwapAndRetried =
true;
5371 switch (V.getNode()->getOpcode()) {
5383 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5391 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5468 SDNode *AndNode =
N->getOperand(0).getNode();
5476 SDValue CmpInputValue =
N->getOperand(1);
5487 AndInputValue1 = AndInputValue1.
getOperand(0);
5491 if (AndInputValue2 != CmpInputValue)
5524 TruncInputValue1, TruncInputValue2);
5526 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5567 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
5595 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
5629 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
5645 EVT VT =
N->getValueType(0);
5648 if (TrueV == FalseV)
5680 {LHS, RHS, CC, TrueV, FalseV});
5685template <
unsigned N>
5689 bool IsSigned =
false) {
5693 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5694 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5696 ": argument out of range.");
5702template <
unsigned N>
5706 EVT ResTy =
Node->getValueType(0);
5710 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5711 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5713 ": argument out of range.");
5718 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
5724 EVT ResTy =
Node->getValueType(0);
5732 EVT ResTy =
Node->getValueType(0);
5741template <
unsigned N>
5744 EVT ResTy =
Node->getValueType(0);
5749 ": argument out of range.");
5759template <
unsigned N>
5762 EVT ResTy =
Node->getValueType(0);
5767 ": argument out of range.");
5776template <
unsigned N>
5779 EVT ResTy =
Node->getValueType(0);
5784 ": argument out of range.");
5798 switch (
N->getConstantOperandVal(0)) {
5801 case Intrinsic::loongarch_lsx_vadd_b:
5802 case Intrinsic::loongarch_lsx_vadd_h:
5803 case Intrinsic::loongarch_lsx_vadd_w:
5804 case Intrinsic::loongarch_lsx_vadd_d:
5805 case Intrinsic::loongarch_lasx_xvadd_b:
5806 case Intrinsic::loongarch_lasx_xvadd_h:
5807 case Intrinsic::loongarch_lasx_xvadd_w:
5808 case Intrinsic::loongarch_lasx_xvadd_d:
5811 case Intrinsic::loongarch_lsx_vaddi_bu:
5812 case Intrinsic::loongarch_lsx_vaddi_hu:
5813 case Intrinsic::loongarch_lsx_vaddi_wu:
5814 case Intrinsic::loongarch_lsx_vaddi_du:
5815 case Intrinsic::loongarch_lasx_xvaddi_bu:
5816 case Intrinsic::loongarch_lasx_xvaddi_hu:
5817 case Intrinsic::loongarch_lasx_xvaddi_wu:
5818 case Intrinsic::loongarch_lasx_xvaddi_du:
5821 case Intrinsic::loongarch_lsx_vsub_b:
5822 case Intrinsic::loongarch_lsx_vsub_h:
5823 case Intrinsic::loongarch_lsx_vsub_w:
5824 case Intrinsic::loongarch_lsx_vsub_d:
5825 case Intrinsic::loongarch_lasx_xvsub_b:
5826 case Intrinsic::loongarch_lasx_xvsub_h:
5827 case Intrinsic::loongarch_lasx_xvsub_w:
5828 case Intrinsic::loongarch_lasx_xvsub_d:
5831 case Intrinsic::loongarch_lsx_vsubi_bu:
5832 case Intrinsic::loongarch_lsx_vsubi_hu:
5833 case Intrinsic::loongarch_lsx_vsubi_wu:
5834 case Intrinsic::loongarch_lsx_vsubi_du:
5835 case Intrinsic::loongarch_lasx_xvsubi_bu:
5836 case Intrinsic::loongarch_lasx_xvsubi_hu:
5837 case Intrinsic::loongarch_lasx_xvsubi_wu:
5838 case Intrinsic::loongarch_lasx_xvsubi_du:
5841 case Intrinsic::loongarch_lsx_vneg_b:
5842 case Intrinsic::loongarch_lsx_vneg_h:
5843 case Intrinsic::loongarch_lsx_vneg_w:
5844 case Intrinsic::loongarch_lsx_vneg_d:
5845 case Intrinsic::loongarch_lasx_xvneg_b:
5846 case Intrinsic::loongarch_lasx_xvneg_h:
5847 case Intrinsic::loongarch_lasx_xvneg_w:
5848 case Intrinsic::loongarch_lasx_xvneg_d:
5852 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
5854 SDLoc(
N),
N->getValueType(0)),
5856 case Intrinsic::loongarch_lsx_vmax_b:
5857 case Intrinsic::loongarch_lsx_vmax_h:
5858 case Intrinsic::loongarch_lsx_vmax_w:
5859 case Intrinsic::loongarch_lsx_vmax_d:
5860 case Intrinsic::loongarch_lasx_xvmax_b:
5861 case Intrinsic::loongarch_lasx_xvmax_h:
5862 case Intrinsic::loongarch_lasx_xvmax_w:
5863 case Intrinsic::loongarch_lasx_xvmax_d:
5866 case Intrinsic::loongarch_lsx_vmax_bu:
5867 case Intrinsic::loongarch_lsx_vmax_hu:
5868 case Intrinsic::loongarch_lsx_vmax_wu:
5869 case Intrinsic::loongarch_lsx_vmax_du:
5870 case Intrinsic::loongarch_lasx_xvmax_bu:
5871 case Intrinsic::loongarch_lasx_xvmax_hu:
5872 case Intrinsic::loongarch_lasx_xvmax_wu:
5873 case Intrinsic::loongarch_lasx_xvmax_du:
5876 case Intrinsic::loongarch_lsx_vmaxi_b:
5877 case Intrinsic::loongarch_lsx_vmaxi_h:
5878 case Intrinsic::loongarch_lsx_vmaxi_w:
5879 case Intrinsic::loongarch_lsx_vmaxi_d:
5880 case Intrinsic::loongarch_lasx_xvmaxi_b:
5881 case Intrinsic::loongarch_lasx_xvmaxi_h:
5882 case Intrinsic::loongarch_lasx_xvmaxi_w:
5883 case Intrinsic::loongarch_lasx_xvmaxi_d:
5886 case Intrinsic::loongarch_lsx_vmaxi_bu:
5887 case Intrinsic::loongarch_lsx_vmaxi_hu:
5888 case Intrinsic::loongarch_lsx_vmaxi_wu:
5889 case Intrinsic::loongarch_lsx_vmaxi_du:
5890 case Intrinsic::loongarch_lasx_xvmaxi_bu:
5891 case Intrinsic::loongarch_lasx_xvmaxi_hu:
5892 case Intrinsic::loongarch_lasx_xvmaxi_wu:
5893 case Intrinsic::loongarch_lasx_xvmaxi_du:
5896 case Intrinsic::loongarch_lsx_vmin_b:
5897 case Intrinsic::loongarch_lsx_vmin_h:
5898 case Intrinsic::loongarch_lsx_vmin_w:
5899 case Intrinsic::loongarch_lsx_vmin_d:
5900 case Intrinsic::loongarch_lasx_xvmin_b:
5901 case Intrinsic::loongarch_lasx_xvmin_h:
5902 case Intrinsic::loongarch_lasx_xvmin_w:
5903 case Intrinsic::loongarch_lasx_xvmin_d:
5906 case Intrinsic::loongarch_lsx_vmin_bu:
5907 case Intrinsic::loongarch_lsx_vmin_hu:
5908 case Intrinsic::loongarch_lsx_vmin_wu:
5909 case Intrinsic::loongarch_lsx_vmin_du:
5910 case Intrinsic::loongarch_lasx_xvmin_bu:
5911 case Intrinsic::loongarch_lasx_xvmin_hu:
5912 case Intrinsic::loongarch_lasx_xvmin_wu:
5913 case Intrinsic::loongarch_lasx_xvmin_du:
5916 case Intrinsic::loongarch_lsx_vmini_b:
5917 case Intrinsic::loongarch_lsx_vmini_h:
5918 case Intrinsic::loongarch_lsx_vmini_w:
5919 case Intrinsic::loongarch_lsx_vmini_d:
5920 case Intrinsic::loongarch_lasx_xvmini_b:
5921 case Intrinsic::loongarch_lasx_xvmini_h:
5922 case Intrinsic::loongarch_lasx_xvmini_w:
5923 case Intrinsic::loongarch_lasx_xvmini_d:
5926 case Intrinsic::loongarch_lsx_vmini_bu:
5927 case Intrinsic::loongarch_lsx_vmini_hu:
5928 case Intrinsic::loongarch_lsx_vmini_wu:
5929 case Intrinsic::loongarch_lsx_vmini_du:
5930 case Intrinsic::loongarch_lasx_xvmini_bu:
5931 case Intrinsic::loongarch_lasx_xvmini_hu:
5932 case Intrinsic::loongarch_lasx_xvmini_wu:
5933 case Intrinsic::loongarch_lasx_xvmini_du:
5936 case Intrinsic::loongarch_lsx_vmul_b:
5937 case Intrinsic::loongarch_lsx_vmul_h:
5938 case Intrinsic::loongarch_lsx_vmul_w:
5939 case Intrinsic::loongarch_lsx_vmul_d:
5940 case Intrinsic::loongarch_lasx_xvmul_b:
5941 case Intrinsic::loongarch_lasx_xvmul_h:
5942 case Intrinsic::loongarch_lasx_xvmul_w:
5943 case Intrinsic::loongarch_lasx_xvmul_d:
5946 case Intrinsic::loongarch_lsx_vmadd_b:
5947 case Intrinsic::loongarch_lsx_vmadd_h:
5948 case Intrinsic::loongarch_lsx_vmadd_w:
5949 case Intrinsic::loongarch_lsx_vmadd_d:
5950 case Intrinsic::loongarch_lasx_xvmadd_b:
5951 case Intrinsic::loongarch_lasx_xvmadd_h:
5952 case Intrinsic::loongarch_lasx_xvmadd_w:
5953 case Intrinsic::loongarch_lasx_xvmadd_d: {
5954 EVT ResTy =
N->getValueType(0);
5959 case Intrinsic::loongarch_lsx_vmsub_b:
5960 case Intrinsic::loongarch_lsx_vmsub_h:
5961 case Intrinsic::loongarch_lsx_vmsub_w:
5962 case Intrinsic::loongarch_lsx_vmsub_d:
5963 case Intrinsic::loongarch_lasx_xvmsub_b:
5964 case Intrinsic::loongarch_lasx_xvmsub_h:
5965 case Intrinsic::loongarch_lasx_xvmsub_w:
5966 case Intrinsic::loongarch_lasx_xvmsub_d: {
5967 EVT ResTy =
N->getValueType(0);
5972 case Intrinsic::loongarch_lsx_vdiv_b:
5973 case Intrinsic::loongarch_lsx_vdiv_h:
5974 case Intrinsic::loongarch_lsx_vdiv_w:
5975 case Intrinsic::loongarch_lsx_vdiv_d:
5976 case Intrinsic::loongarch_lasx_xvdiv_b:
5977 case Intrinsic::loongarch_lasx_xvdiv_h:
5978 case Intrinsic::loongarch_lasx_xvdiv_w:
5979 case Intrinsic::loongarch_lasx_xvdiv_d:
5982 case Intrinsic::loongarch_lsx_vdiv_bu:
5983 case Intrinsic::loongarch_lsx_vdiv_hu:
5984 case Intrinsic::loongarch_lsx_vdiv_wu:
5985 case Intrinsic::loongarch_lsx_vdiv_du:
5986 case Intrinsic::loongarch_lasx_xvdiv_bu:
5987 case Intrinsic::loongarch_lasx_xvdiv_hu:
5988 case Intrinsic::loongarch_lasx_xvdiv_wu:
5989 case Intrinsic::loongarch_lasx_xvdiv_du:
5992 case Intrinsic::loongarch_lsx_vmod_b:
5993 case Intrinsic::loongarch_lsx_vmod_h:
5994 case Intrinsic::loongarch_lsx_vmod_w:
5995 case Intrinsic::loongarch_lsx_vmod_d:
5996 case Intrinsic::loongarch_lasx_xvmod_b:
5997 case Intrinsic::loongarch_lasx_xvmod_h:
5998 case Intrinsic::loongarch_lasx_xvmod_w:
5999 case Intrinsic::loongarch_lasx_xvmod_d:
6002 case Intrinsic::loongarch_lsx_vmod_bu:
6003 case Intrinsic::loongarch_lsx_vmod_hu:
6004 case Intrinsic::loongarch_lsx_vmod_wu:
6005 case Intrinsic::loongarch_lsx_vmod_du:
6006 case Intrinsic::loongarch_lasx_xvmod_bu:
6007 case Intrinsic::loongarch_lasx_xvmod_hu:
6008 case Intrinsic::loongarch_lasx_xvmod_wu:
6009 case Intrinsic::loongarch_lasx_xvmod_du:
6012 case Intrinsic::loongarch_lsx_vand_v:
6013 case Intrinsic::loongarch_lasx_xvand_v:
6016 case Intrinsic::loongarch_lsx_vor_v:
6017 case Intrinsic::loongarch_lasx_xvor_v:
6020 case Intrinsic::loongarch_lsx_vxor_v:
6021 case Intrinsic::loongarch_lasx_xvxor_v:
6024 case Intrinsic::loongarch_lsx_vnor_v:
6025 case Intrinsic::loongarch_lasx_xvnor_v: {
6030 case Intrinsic::loongarch_lsx_vandi_b:
6031 case Intrinsic::loongarch_lasx_xvandi_b:
6034 case Intrinsic::loongarch_lsx_vori_b:
6035 case Intrinsic::loongarch_lasx_xvori_b:
6038 case Intrinsic::loongarch_lsx_vxori_b:
6039 case Intrinsic::loongarch_lasx_xvxori_b:
6042 case Intrinsic::loongarch_lsx_vsll_b:
6043 case Intrinsic::loongarch_lsx_vsll_h:
6044 case Intrinsic::loongarch_lsx_vsll_w:
6045 case Intrinsic::loongarch_lsx_vsll_d:
6046 case Intrinsic::loongarch_lasx_xvsll_b:
6047 case Intrinsic::loongarch_lasx_xvsll_h:
6048 case Intrinsic::loongarch_lasx_xvsll_w:
6049 case Intrinsic::loongarch_lasx_xvsll_d:
6052 case Intrinsic::loongarch_lsx_vslli_b:
6053 case Intrinsic::loongarch_lasx_xvslli_b:
6056 case Intrinsic::loongarch_lsx_vslli_h:
6057 case Intrinsic::loongarch_lasx_xvslli_h:
6060 case Intrinsic::loongarch_lsx_vslli_w:
6061 case Intrinsic::loongarch_lasx_xvslli_w:
6064 case Intrinsic::loongarch_lsx_vslli_d:
6065 case Intrinsic::loongarch_lasx_xvslli_d:
6068 case Intrinsic::loongarch_lsx_vsrl_b:
6069 case Intrinsic::loongarch_lsx_vsrl_h:
6070 case Intrinsic::loongarch_lsx_vsrl_w:
6071 case Intrinsic::loongarch_lsx_vsrl_d:
6072 case Intrinsic::loongarch_lasx_xvsrl_b:
6073 case Intrinsic::loongarch_lasx_xvsrl_h:
6074 case Intrinsic::loongarch_lasx_xvsrl_w:
6075 case Intrinsic::loongarch_lasx_xvsrl_d:
6078 case Intrinsic::loongarch_lsx_vsrli_b:
6079 case Intrinsic::loongarch_lasx_xvsrli_b:
6082 case Intrinsic::loongarch_lsx_vsrli_h:
6083 case Intrinsic::loongarch_lasx_xvsrli_h:
6086 case Intrinsic::loongarch_lsx_vsrli_w:
6087 case Intrinsic::loongarch_lasx_xvsrli_w:
6090 case Intrinsic::loongarch_lsx_vsrli_d:
6091 case Intrinsic::loongarch_lasx_xvsrli_d:
6094 case Intrinsic::loongarch_lsx_vsra_b:
6095 case Intrinsic::loongarch_lsx_vsra_h:
6096 case Intrinsic::loongarch_lsx_vsra_w:
6097 case Intrinsic::loongarch_lsx_vsra_d:
6098 case Intrinsic::loongarch_lasx_xvsra_b:
6099 case Intrinsic::loongarch_lasx_xvsra_h:
6100 case Intrinsic::loongarch_lasx_xvsra_w:
6101 case Intrinsic::loongarch_lasx_xvsra_d:
6104 case Intrinsic::loongarch_lsx_vsrai_b:
6105 case Intrinsic::loongarch_lasx_xvsrai_b:
6108 case Intrinsic::loongarch_lsx_vsrai_h:
6109 case Intrinsic::loongarch_lasx_xvsrai_h:
6112 case Intrinsic::loongarch_lsx_vsrai_w:
6113 case Intrinsic::loongarch_lasx_xvsrai_w:
6116 case Intrinsic::loongarch_lsx_vsrai_d:
6117 case Intrinsic::loongarch_lasx_xvsrai_d:
6120 case Intrinsic::loongarch_lsx_vclz_b:
6121 case Intrinsic::loongarch_lsx_vclz_h:
6122 case Intrinsic::loongarch_lsx_vclz_w:
6123 case Intrinsic::loongarch_lsx_vclz_d:
6124 case Intrinsic::loongarch_lasx_xvclz_b:
6125 case Intrinsic::loongarch_lasx_xvclz_h:
6126 case Intrinsic::loongarch_lasx_xvclz_w:
6127 case Intrinsic::loongarch_lasx_xvclz_d:
6129 case Intrinsic::loongarch_lsx_vpcnt_b:
6130 case Intrinsic::loongarch_lsx_vpcnt_h:
6131 case Intrinsic::loongarch_lsx_vpcnt_w:
6132 case Intrinsic::loongarch_lsx_vpcnt_d:
6133 case Intrinsic::loongarch_lasx_xvpcnt_b:
6134 case Intrinsic::loongarch_lasx_xvpcnt_h:
6135 case Intrinsic::loongarch_lasx_xvpcnt_w:
6136 case Intrinsic::loongarch_lasx_xvpcnt_d:
6138 case Intrinsic::loongarch_lsx_vbitclr_b:
6139 case Intrinsic::loongarch_lsx_vbitclr_h:
6140 case Intrinsic::loongarch_lsx_vbitclr_w:
6141 case Intrinsic::loongarch_lsx_vbitclr_d:
6142 case Intrinsic::loongarch_lasx_xvbitclr_b:
6143 case Intrinsic::loongarch_lasx_xvbitclr_h:
6144 case Intrinsic::loongarch_lasx_xvbitclr_w:
6145 case Intrinsic::loongarch_lasx_xvbitclr_d:
6147 case Intrinsic::loongarch_lsx_vbitclri_b:
6148 case Intrinsic::loongarch_lasx_xvbitclri_b:
6150 case Intrinsic::loongarch_lsx_vbitclri_h:
6151 case Intrinsic::loongarch_lasx_xvbitclri_h:
6153 case Intrinsic::loongarch_lsx_vbitclri_w:
6154 case Intrinsic::loongarch_lasx_xvbitclri_w:
6156 case Intrinsic::loongarch_lsx_vbitclri_d:
6157 case Intrinsic::loongarch_lasx_xvbitclri_d:
6159 case Intrinsic::loongarch_lsx_vbitset_b:
6160 case Intrinsic::loongarch_lsx_vbitset_h:
6161 case Intrinsic::loongarch_lsx_vbitset_w:
6162 case Intrinsic::loongarch_lsx_vbitset_d:
6163 case Intrinsic::loongarch_lasx_xvbitset_b:
6164 case Intrinsic::loongarch_lasx_xvbitset_h:
6165 case Intrinsic::loongarch_lasx_xvbitset_w:
6166 case Intrinsic::loongarch_lasx_xvbitset_d: {
6167 EVT VecTy =
N->getValueType(0);
6173 case Intrinsic::loongarch_lsx_vbitseti_b:
6174 case Intrinsic::loongarch_lasx_xvbitseti_b:
6176 case Intrinsic::loongarch_lsx_vbitseti_h:
6177 case Intrinsic::loongarch_lasx_xvbitseti_h:
6179 case Intrinsic::loongarch_lsx_vbitseti_w:
6180 case Intrinsic::loongarch_lasx_xvbitseti_w:
6182 case Intrinsic::loongarch_lsx_vbitseti_d:
6183 case Intrinsic::loongarch_lasx_xvbitseti_d:
6185 case Intrinsic::loongarch_lsx_vbitrev_b:
6186 case Intrinsic::loongarch_lsx_vbitrev_h:
6187 case Intrinsic::loongarch_lsx_vbitrev_w:
6188 case Intrinsic::loongarch_lsx_vbitrev_d:
6189 case Intrinsic::loongarch_lasx_xvbitrev_b:
6190 case Intrinsic::loongarch_lasx_xvbitrev_h:
6191 case Intrinsic::loongarch_lasx_xvbitrev_w:
6192 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6193 EVT VecTy =
N->getValueType(0);
6199 case Intrinsic::loongarch_lsx_vbitrevi_b:
6200 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6202 case Intrinsic::loongarch_lsx_vbitrevi_h:
6203 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6205 case Intrinsic::loongarch_lsx_vbitrevi_w:
6206 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6208 case Intrinsic::loongarch_lsx_vbitrevi_d:
6209 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6211 case Intrinsic::loongarch_lsx_vfadd_s:
6212 case Intrinsic::loongarch_lsx_vfadd_d:
6213 case Intrinsic::loongarch_lasx_xvfadd_s:
6214 case Intrinsic::loongarch_lasx_xvfadd_d:
6217 case Intrinsic::loongarch_lsx_vfsub_s:
6218 case Intrinsic::loongarch_lsx_vfsub_d:
6219 case Intrinsic::loongarch_lasx_xvfsub_s:
6220 case Intrinsic::loongarch_lasx_xvfsub_d:
6223 case Intrinsic::loongarch_lsx_vfmul_s:
6224 case Intrinsic::loongarch_lsx_vfmul_d:
6225 case Intrinsic::loongarch_lasx_xvfmul_s:
6226 case Intrinsic::loongarch_lasx_xvfmul_d:
6229 case Intrinsic::loongarch_lsx_vfdiv_s:
6230 case Intrinsic::loongarch_lsx_vfdiv_d:
6231 case Intrinsic::loongarch_lasx_xvfdiv_s:
6232 case Intrinsic::loongarch_lasx_xvfdiv_d:
6235 case Intrinsic::loongarch_lsx_vfmadd_s:
6236 case Intrinsic::loongarch_lsx_vfmadd_d:
6237 case Intrinsic::loongarch_lasx_xvfmadd_s:
6238 case Intrinsic::loongarch_lasx_xvfmadd_d:
6240 N->getOperand(2),
N->getOperand(3));
6241 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6243 N->getOperand(1),
N->getOperand(2),
6245 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6246 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6248 N->getOperand(1),
N->getOperand(2),
6250 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6251 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6253 N->getOperand(1),
N->getOperand(2),
6255 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6257 N->getOperand(1),
N->getOperand(2),
6259 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6260 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6261 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6262 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6263 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6264 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6265 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6266 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6270 case Intrinsic::loongarch_lsx_vreplve_b:
6271 case Intrinsic::loongarch_lsx_vreplve_h:
6272 case Intrinsic::loongarch_lsx_vreplve_w:
6273 case Intrinsic::loongarch_lsx_vreplve_d:
6274 case Intrinsic::loongarch_lasx_xvreplve_b:
6275 case Intrinsic::loongarch_lasx_xvreplve_h:
6276 case Intrinsic::loongarch_lasx_xvreplve_w:
6277 case Intrinsic::loongarch_lasx_xvreplve_d:
6307 "Unexpected value type!");
6316 MVT VT =
N->getSimpleValueType(0);
6350 APInt V =
C->getValueAPF().bitcastToAPInt();
6366 MVT EltVT =
N->getSimpleValueType(0);
6398 switch (
N->getOpcode()) {
6452 MF->
insert(It, BreakMBB);
6456 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
6457 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
6469 MBB->addSuccessor(BreakMBB);
6470 MBB->addSuccessor(SinkMBB);
6476 BreakMBB->addSuccessor(SinkMBB);
6488 switch (
MI.getOpcode()) {
6491 case LoongArch::PseudoVBZ:
6492 CondOpc = LoongArch::VSETEQZ_V;
6494 case LoongArch::PseudoVBZ_B:
6495 CondOpc = LoongArch::VSETANYEQZ_B;
6497 case LoongArch::PseudoVBZ_H:
6498 CondOpc = LoongArch::VSETANYEQZ_H;
6500 case LoongArch::PseudoVBZ_W:
6501 CondOpc = LoongArch::VSETANYEQZ_W;
6503 case LoongArch::PseudoVBZ_D:
6504 CondOpc = LoongArch::VSETANYEQZ_D;
6506 case LoongArch::PseudoVBNZ:
6507 CondOpc = LoongArch::VSETNEZ_V;
6509 case LoongArch::PseudoVBNZ_B:
6510 CondOpc = LoongArch::VSETALLNEZ_B;
6512 case LoongArch::PseudoVBNZ_H:
6513 CondOpc = LoongArch::VSETALLNEZ_H;
6515 case LoongArch::PseudoVBNZ_W:
6516 CondOpc = LoongArch::VSETALLNEZ_W;
6518 case LoongArch::PseudoVBNZ_D:
6519 CondOpc = LoongArch::VSETALLNEZ_D;
6521 case LoongArch::PseudoXVBZ:
6522 CondOpc = LoongArch::XVSETEQZ_V;
6524 case LoongArch::PseudoXVBZ_B:
6525 CondOpc = LoongArch::XVSETANYEQZ_B;
6527 case LoongArch::PseudoXVBZ_H:
6528 CondOpc = LoongArch::XVSETANYEQZ_H;
6530 case LoongArch::PseudoXVBZ_W:
6531 CondOpc = LoongArch::XVSETANYEQZ_W;
6533 case LoongArch::PseudoXVBZ_D:
6534 CondOpc = LoongArch::XVSETANYEQZ_D;
6536 case LoongArch::PseudoXVBNZ:
6537 CondOpc = LoongArch::XVSETNEZ_V;
6539 case LoongArch::PseudoXVBNZ_B:
6540 CondOpc = LoongArch::XVSETALLNEZ_B;
6542 case LoongArch::PseudoXVBNZ_H:
6543 CondOpc = LoongArch::XVSETALLNEZ_H;
6545 case LoongArch::PseudoXVBNZ_W:
6546 CondOpc = LoongArch::XVSETALLNEZ_W;
6548 case LoongArch::PseudoXVBNZ_D:
6549 CondOpc = LoongArch::XVSETALLNEZ_D;
6564 F->insert(It, FalseBB);
6565 F->insert(It, TrueBB);
6566 F->insert(It, SinkBB);
6569 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
6573 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
6582 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6590 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6598 MI.getOperand(0).getReg())
6605 MI.eraseFromParent();
6613 unsigned BroadcastOp;
6615 switch (
MI.getOpcode()) {
6618 case LoongArch::PseudoXVINSGR2VR_B:
6620 BroadcastOp = LoongArch::XVREPLGR2VR_B;
6621 InsOp = LoongArch::XVEXTRINS_B;
6623 case LoongArch::PseudoXVINSGR2VR_H:
6625 BroadcastOp = LoongArch::XVREPLGR2VR_H;
6626 InsOp = LoongArch::XVEXTRINS_H;
6638 unsigned Idx =
MI.getOperand(3).getImm();
6640 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
6642 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
6643 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
6646 .
addReg(XSrc, 0, LoongArch::sub_128);
6648 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
6649 : LoongArch::VINSGR2VR_B),
6658 .
addImm(LoongArch::sub_128);
6660 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6661 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6665 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
6668 .
addImm(Idx >= HalfSize ? 48 : 18);
6673 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
6676 MI.eraseFromParent();
6683 assert(Subtarget.hasExtLSX());
6690 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6691 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6692 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
6696 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
6697 : LoongArch::VINSGR2VR_W),
6704 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
6708 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
6709 : LoongArch::VPICKVE2GR_W),
6714 MI.eraseFromParent();
6728 unsigned EleBits = 8;
6729 unsigned NotOpc = 0;
6732 switch (
MI.getOpcode()) {
6735 case LoongArch::PseudoVMSKLTZ_B:
6736 MskOpc = LoongArch::VMSKLTZ_B;
6738 case LoongArch::PseudoVMSKLTZ_H:
6739 MskOpc = LoongArch::VMSKLTZ_H;
6742 case LoongArch::PseudoVMSKLTZ_W:
6743 MskOpc = LoongArch::VMSKLTZ_W;
6746 case LoongArch::PseudoVMSKLTZ_D:
6747 MskOpc = LoongArch::VMSKLTZ_D;
6750 case LoongArch::PseudoVMSKGEZ_B:
6751 MskOpc = LoongArch::VMSKGEZ_B;
6753 case LoongArch::PseudoVMSKEQZ_B:
6754 MskOpc = LoongArch::VMSKNZ_B;
6755 NotOpc = LoongArch::VNOR_V;
6757 case LoongArch::PseudoVMSKNEZ_B:
6758 MskOpc = LoongArch::VMSKNZ_B;
6760 case LoongArch::PseudoXVMSKLTZ_B:
6761 MskOpc = LoongArch::XVMSKLTZ_B;
6762 RC = &LoongArch::LASX256RegClass;
6764 case LoongArch::PseudoXVMSKLTZ_H:
6765 MskOpc = LoongArch::XVMSKLTZ_H;
6766 RC = &LoongArch::LASX256RegClass;
6769 case LoongArch::PseudoXVMSKLTZ_W:
6770 MskOpc = LoongArch::XVMSKLTZ_W;
6771 RC = &LoongArch::LASX256RegClass;
6774 case LoongArch::PseudoXVMSKLTZ_D:
6775 MskOpc = LoongArch::XVMSKLTZ_D;
6776 RC = &LoongArch::LASX256RegClass;
6779 case LoongArch::PseudoXVMSKGEZ_B:
6780 MskOpc = LoongArch::XVMSKGEZ_B;
6781 RC = &LoongArch::LASX256RegClass;
6783 case LoongArch::PseudoXVMSKEQZ_B:
6784 MskOpc = LoongArch::XVMSKNZ_B;
6785 NotOpc = LoongArch::XVNOR_V;
6786 RC = &LoongArch::LASX256RegClass;
6788 case LoongArch::PseudoXVMSKNEZ_B:
6789 MskOpc = LoongArch::XVMSKNZ_B;
6790 RC = &LoongArch::LASX256RegClass;
6805 if (
TRI->getRegSizeInBits(*RC) > 128) {
6806 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6807 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6815 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
6816 : LoongArch::BSTRINS_W),
6820 .
addImm(256 / EleBits - 1)
6828 MI.eraseFromParent();
6835 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
6836 "Unexpected instruction");
6848 MI.eraseFromParent();
6855 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
6856 "Unexpected instruction");
6862 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
6872 MI.eraseFromParent();
6877 switch (
MI.getOpcode()) {
6880 case LoongArch::Select_GPR_Using_CC_GPR:
6916 if (
MI.getOperand(2).isReg())
6917 RHS =
MI.getOperand(2).getReg();
6918 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
6922 SelectDests.
insert(
MI.getOperand(0).getReg());
6926 SequenceMBBI !=
E; ++SequenceMBBI) {
6927 if (SequenceMBBI->isDebugInstr())
6930 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
6931 !SequenceMBBI->getOperand(2).isReg() ||
6932 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
6933 SequenceMBBI->getOperand(3).getImm() != CC ||
6934 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
6935 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
6937 LastSelectPseudo = &*SequenceMBBI;
6939 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
6942 if (SequenceMBBI->hasUnmodeledSideEffects() ||
6943 SequenceMBBI->mayLoadOrStore() ||
6944 SequenceMBBI->usesCustomInsertionHook())
6947 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
6962 F->insert(
I, IfFalseMBB);
6963 F->insert(
I, TailMBB);
6966 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
6972 TailMBB->
push_back(DebugInstr->removeFromParent());
6976 TailMBB->
splice(TailMBB->
end(), HeadMBB,
6986 if (
MI.getOperand(2).isImm())
6998 auto SelectMBBI =
MI.getIterator();
6999 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7001 while (SelectMBBI != SelectEnd) {
7002 auto Next = std::next(SelectMBBI);
7006 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7007 .
addReg(SelectMBBI->getOperand(4).getReg())
7009 .
addReg(SelectMBBI->getOperand(5).getReg())
7016 F->getProperties().resetNoPHIs();
7022 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7025 switch (
MI.getOpcode()) {
7028 case LoongArch::DIV_W:
7029 case LoongArch::DIV_WU:
7030 case LoongArch::MOD_W:
7031 case LoongArch::MOD_WU:
7032 case LoongArch::DIV_D:
7033 case LoongArch::DIV_DU:
7034 case LoongArch::MOD_D:
7035 case LoongArch::MOD_DU:
7038 case LoongArch::WRFCSR: {
7040 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7041 .
addReg(
MI.getOperand(1).getReg());
7042 MI.eraseFromParent();
7045 case LoongArch::RDFCSR: {
7046 MachineInstr *ReadFCSR =
7048 MI.getOperand(0).getReg())
7049 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
7051 MI.eraseFromParent();
7054 case LoongArch::Select_GPR_Using_CC_GPR:
7056 case LoongArch::BuildPairF64Pseudo:
7058 case LoongArch::SplitPairF64Pseudo:
7060 case LoongArch::PseudoVBZ:
7061 case LoongArch::PseudoVBZ_B:
7062 case LoongArch::PseudoVBZ_H:
7063 case LoongArch::PseudoVBZ_W:
7064 case LoongArch::PseudoVBZ_D:
7065 case LoongArch::PseudoVBNZ:
7066 case LoongArch::PseudoVBNZ_B:
7067 case LoongArch::PseudoVBNZ_H:
7068 case LoongArch::PseudoVBNZ_W:
7069 case LoongArch::PseudoVBNZ_D:
7070 case LoongArch::PseudoXVBZ:
7071 case LoongArch::PseudoXVBZ_B:
7072 case LoongArch::PseudoXVBZ_H:
7073 case LoongArch::PseudoXVBZ_W:
7074 case LoongArch::PseudoXVBZ_D:
7075 case LoongArch::PseudoXVBNZ:
7076 case LoongArch::PseudoXVBNZ_B:
7077 case LoongArch::PseudoXVBNZ_H:
7078 case LoongArch::PseudoXVBNZ_W:
7079 case LoongArch::PseudoXVBNZ_D:
7081 case LoongArch::PseudoXVINSGR2VR_B:
7082 case LoongArch::PseudoXVINSGR2VR_H:
7084 case LoongArch::PseudoCTPOP:
7086 case LoongArch::PseudoVMSKLTZ_B:
7087 case LoongArch::PseudoVMSKLTZ_H:
7088 case LoongArch::PseudoVMSKLTZ_W:
7089 case LoongArch::PseudoVMSKLTZ_D:
7090 case LoongArch::PseudoVMSKGEZ_B:
7091 case LoongArch::PseudoVMSKEQZ_B:
7092 case LoongArch::PseudoVMSKNEZ_B:
7093 case LoongArch::PseudoXVMSKLTZ_B:
7094 case LoongArch::PseudoXVMSKLTZ_H:
7095 case LoongArch::PseudoXVMSKLTZ_W:
7096 case LoongArch::PseudoXVMSKLTZ_D:
7097 case LoongArch::PseudoXVMSKGEZ_B:
7098 case LoongArch::PseudoXVMSKEQZ_B:
7099 case LoongArch::PseudoXVMSKNEZ_B:
7101 case TargetOpcode::STATEPOINT:
7107 MI.addOperand(*
MI.getMF(),
7109 LoongArch::R1,
true,
7112 if (!Subtarget.is64Bit())
7120 unsigned *
Fast)
const {
7121 if (!Subtarget.hasUAL())
7135#define NODE_NAME_CASE(node) \
7136 case LoongArchISD::node: \
7137 return "LoongArchISD::" #node;
7239#undef NODE_NAME_CASE
7252 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7253 LoongArch::R10, LoongArch::R11};
7257 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7258 LoongArch::F6, LoongArch::F7};
7261 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7262 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7265 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7266 LoongArch::VR6, LoongArch::VR7};
7269 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7270 LoongArch::XR6, LoongArch::XR7};
7276 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7278 unsigned GRLenInBytes = GRLen / 8;
7289 State.AllocateStack(GRLenInBytes, StackAlign),
7292 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7303 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7311 unsigned ValNo,
MVT ValVT,
7314 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7315 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7316 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7321 if (IsRet && ValNo > 1)
7325 bool UseGPRForFloat =
true;
7335 UseGPRForFloat = ArgFlags.
isVarArg();
7348 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7351 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7352 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
7354 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7360 State.getPendingArgFlags();
7363 "PendingLocs and PendingArgFlags out of sync");
7367 UseGPRForFloat =
true;
7369 if (UseGPRForFloat && ValVT == MVT::f32) {
7372 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7375 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7378 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7420 PendingLocs.
size() <= 2) {
7421 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7426 PendingLocs.
clear();
7427 PendingArgFlags.
clear();
7434 unsigned StoreSizeBytes = GRLen / 8;
7437 if (ValVT == MVT::f32 && !UseGPRForFloat) {
7439 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
7443 UseGPRForFloat =
false;
7444 StoreSizeBytes = 16;
7445 StackAlign =
Align(16);
7448 UseGPRForFloat =
false;
7449 StoreSizeBytes = 32;
7450 StackAlign =
Align(32);
7456 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
7460 if (!PendingLocs.
empty()) {
7462 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7463 for (
auto &It : PendingLocs) {
7465 It.convertToReg(
Reg);
7470 PendingLocs.clear();
7471 PendingArgFlags.
clear();
7474 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7475 "Expected an GRLenVT at this stage");
7492void LoongArchTargetLowering::analyzeInputArgs(
7495 LoongArchCCAssignFn Fn)
const {
7497 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7498 MVT ArgVT =
Ins[i].VT;
7499 Type *ArgTy =
nullptr;
7501 ArgTy = FType->getReturnType();
7502 else if (Ins[i].isOrigArg())
7503 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7507 CCInfo, IsRet, ArgTy)) {
7508 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7515void LoongArchTargetLowering::analyzeOutputArgs(
7518 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7519 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7520 MVT ArgVT = Outs[i].VT;
7521 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7525 CCInfo, IsRet, OrigTy)) {
7526 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7567 if (In.isOrigArg()) {
7572 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
7573 (
BitWidth < 32 && In.Flags.isZExt())) {
7623 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7636 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7656 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
7666 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
7670 LoongArch::R23, LoongArch::R24, LoongArch::R25,
7671 LoongArch::R26, LoongArch::R27, LoongArch::R28,
7672 LoongArch::R29, LoongArch::R30, LoongArch::R31};
7679 if (LocVT == MVT::f32) {
7682 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
7683 LoongArch::F26, LoongArch::F27};
7690 if (LocVT == MVT::f64) {
7693 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
7694 LoongArch::F30_64, LoongArch::F31_64};
7724 "GHC calling convention requires the F and D extensions");
7728 MVT GRLenVT = Subtarget.getGRLenVT();
7729 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
7731 std::vector<SDValue> OutChains;
7740 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
7742 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
7759 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
7760 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
7761 assert(ArgPartOffset == 0);
7762 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
7764 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
7788 int VaArgOffset, VarArgsSaveSize;
7792 if (ArgRegs.
size() == Idx) {
7794 VarArgsSaveSize = 0;
7796 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
7797 VaArgOffset = -VarArgsSaveSize;
7803 LoongArchFI->setVarArgsFrameIndex(FI);
7811 VarArgsSaveSize += GRLenInBytes;
7816 for (
unsigned I = Idx;
I < ArgRegs.
size();
7817 ++
I, VaArgOffset += GRLenInBytes) {
7818 const Register Reg = RegInfo.createVirtualRegister(RC);
7819 RegInfo.addLiveIn(ArgRegs[
I], Reg);
7827 ->setValue((
Value *)
nullptr);
7828 OutChains.push_back(Store);
7830 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
7835 if (!OutChains.empty()) {
7836 OutChains.push_back(Chain);
7851 if (
N->getNumValues() != 1)
7853 if (!
N->hasNUsesOfValue(1, 0))
7856 SDNode *Copy = *
N->user_begin();
7862 if (Copy->getGluedNode())
7866 bool HasRet =
false;
7876 Chain = Copy->getOperand(0);
7881bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
7885 auto CalleeCC = CLI.CallConv;
7886 auto &Outs = CLI.Outs;
7888 auto CallerCC = Caller.getCallingConv();
7895 for (
auto &VA : ArgLocs)
7901 auto IsCallerStructRet = Caller.hasStructRetAttr();
7902 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
7903 if (IsCallerStructRet || IsCalleeStructRet)
7907 for (
auto &Arg : Outs)
7908 if (Arg.Flags.isByVal())
7913 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
7914 if (CalleeCC != CallerCC) {
7915 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
7916 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
7942 MVT GRLenVT = Subtarget.getGRLenVT();
7954 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
7958 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
7964 "site marked musttail");
7971 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7973 if (!Flags.isByVal())
7977 unsigned Size = Flags.getByValSize();
7978 Align Alignment = Flags.getNonZeroByValAlign();
7985 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
7987 false,
nullptr, std::nullopt,
7999 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8002 SDValue ArgValue = OutVals[OutIdx];
8011 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8023 if (!StackPtr.getNode())
8035 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8050 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8051 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8052 assert(ArgPartOffset == 0);
8057 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8058 SDValue PartValue = OutVals[OutIdx + 1];
8059 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8074 for (
const auto &Part : Parts) {
8075 SDValue PartValue = Part.first;
8076 SDValue PartOffset = Part.second;
8083 ArgValue = SpillSlot;
8089 if (Flags.isByVal())
8090 ArgValue = ByValArgs[j++];
8097 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8098 "for passing parameters");
8101 if (!StackPtr.getNode())
8114 if (!MemOpChains.
empty())
8120 for (
auto &Reg : RegsToPass) {
8121 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8143 Ops.push_back(Chain);
8144 Ops.push_back(Callee);
8148 for (
auto &Reg : RegsToPass)
8149 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8154 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8155 assert(Mask &&
"Missing call preserved mask for calling convention");
8161 Ops.push_back(Glue);
8173 assert(Subtarget.is64Bit() &&
"Medium code model requires LA64");
8177 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8200 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8203 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8204 auto &VA = RVLocs[i];
8212 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8213 assert(VA.needsCustom());
8219 RetValue, RetValue2);
8232 const Type *RetTy)
const {
8234 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8236 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8240 Outs[i].Flags, CCInfo,
true,
nullptr))
8266 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8267 SDValue Val = OutVals[OutIdx];
8276 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8280 Register RegHi = RVLocs[++i].getLocReg();
8310 if (!Subtarget.hasExtLSX())
8313 if (VT == MVT::f32) {
8314 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8315 return (masked == 0x3e000000 || masked == 0x40000000);
8318 if (VT == MVT::f64) {
8319 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8320 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8326bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8327 bool ForCodeSize)
const {
8329 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8331 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8333 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8344bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8354 Type *Ty =
I->getOperand(0)->getType();
8356 unsigned Size = Ty->getIntegerBitWidth();
8383 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8384 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8385 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8386 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8388 Info.memVT = MVT::i32;
8389 Info.ptrVal =
I.getArgOperand(0);
8391 Info.align =
Align(4);
8408 "Unable to expand");
8409 unsigned MinWordSize = 4;
8421 Value *AlignedAddr = Builder.CreateIntrinsic(
8422 Intrinsic::ptrmask, {PtrTy, IntTy},
8423 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8426 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
8427 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8428 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
8429 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8430 Value *Mask = Builder.CreateShl(
8431 ConstantInt::get(WordType,
8434 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
8435 Value *ValOperand_Shifted =
8436 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
8437 ShiftAmt,
"ValOperand_Shifted");
8440 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8442 NewOperand = ValOperand_Shifted;
8445 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
8448 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
8449 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
8468 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
8476 if (Subtarget.hasLAMCAS()) {
8498 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
8500 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
8502 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
8504 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
8506 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
8508 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
8510 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
8512 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
8522 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
8524 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
8526 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
8528 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
8530 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
8532 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
8534 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
8536 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
8548 if (Subtarget.hasLAMCAS())
8560 unsigned GRLen = Subtarget.getGRLen();
8562 Value *FailureOrdering =
8563 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
8564 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
8566 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
8567 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
8568 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
8569 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
8572 Value *Result = Builder.CreateIntrinsic(
8573 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
8575 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
8591 Builder.CreateNot(Mask,
"Inv_Mask"),
8598 unsigned GRLen = Subtarget.getGRLen();
8607 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
8608 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
8609 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
8625 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
8626 Result = Builder.CreateCall(LlwOpScwLoop,
8627 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
8630 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
8634 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
8657 const Constant *PersonalityFn)
const {
8658 return LoongArch::R4;
8662 const Constant *PersonalityFn)
const {
8663 return LoongArch::R5;
8674 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
8675 return RefinementSteps;
8680 int &RefinementSteps,
8681 bool &UseOneConstNR,
8682 bool Reciprocal)
const {
8683 if (Subtarget.hasFrecipe()) {
8687 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8688 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8689 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8690 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8691 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8710 int &RefinementSteps)
const {
8711 if (Subtarget.hasFrecipe()) {
8715 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8716 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8717 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8718 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8719 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8736LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
8756 if (Constraint.
size() == 1) {
8757 switch (Constraint[0]) {
8773 if (Constraint ==
"ZC" || Constraint ==
"ZB")
8782 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
8789std::pair<unsigned, const TargetRegisterClass *>
8790LoongArchTargetLowering::getRegForInlineAsmConstraint(
8794 if (Constraint.
size() == 1) {
8795 switch (Constraint[0]) {
8800 return std::make_pair(0U, &LoongArch::GPRRegClass);
8802 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
8804 if (Subtarget.hasBasicF() && VT == MVT::f32)
8805 return std::make_pair(0U, &LoongArch::FPR32RegClass);
8806 if (Subtarget.hasBasicD() && VT == MVT::f64)
8807 return std::make_pair(0U, &LoongArch::FPR64RegClass);
8808 if (Subtarget.hasExtLSX() &&
8809 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
8810 return std::make_pair(0U, &LoongArch::LSX128RegClass);
8811 if (Subtarget.hasExtLASX() &&
8812 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
8813 return std::make_pair(0U, &LoongArch::LASX256RegClass);
8833 bool IsFP = Constraint[2] ==
'f';
8834 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
8835 std::pair<unsigned, const TargetRegisterClass *>
R;
8840 unsigned RegNo =
R.first;
8841 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
8842 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
8843 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
8844 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
8854void LoongArchTargetLowering::LowerAsmOperandForConstraint(
8858 if (Constraint.
size() == 1) {
8859 switch (Constraint[0]) {
8863 uint64_t CVal =
C->getSExtValue();
8866 Subtarget.getGRLenVT()));
8872 uint64_t CVal =
C->getSExtValue();
8875 Subtarget.getGRLenVT()));
8881 if (
C->getZExtValue() == 0)
8888 uint64_t CVal =
C->getZExtValue();
8901#define GET_REGISTER_MATCHER
8902#include "LoongArchGenAsmMatcher.inc"
8908 std::string NewRegName = Name.second.str();
8914 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
8915 if (!ReservedRegs.
test(Reg))
8932 const APInt &Imm = ConstNode->getAPIntValue();
8934 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
8935 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
8938 if (ConstNode->hasOneUse() &&
8939 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
8940 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
8946 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
8947 unsigned Shifts = Imm.countr_zero();
8953 APInt ImmPop = Imm.ashr(Shifts);
8954 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
8958 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
8959 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
8960 (ImmSmall - Imm).isPowerOf2())
8970 Type *Ty,
unsigned AS,
9025 EVT MemVT = LD->getMemoryVT();
9026 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
9037 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
9046 if (
Y.getValueType().isVector())
9058 Type *Ty,
bool IsSigned)
const {
9059 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
9068 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
9069 Type.getSizeInBits() < Subtarget.getGRLen()))
9079 Align &PrefAlign)
const {
9083 if (Subtarget.is64Bit()) {
9085 PrefAlign =
Align(8);
9088 PrefAlign =
Align(4);
9103bool LoongArchTargetLowering::splitValueIntoRegisterParts(
9105 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
9106 bool IsABIRegCopy = CC.has_value();
9109 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9110 PartVT == MVT::f32) {
9113 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
9117 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f32, Val);
9125SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
9127 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
9128 bool IsABIRegCopy = CC.has_value();
9130 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9131 PartVT == MVT::f32) {
9135 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
9137 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
9148 if (VT == MVT::f16 && Subtarget.hasBasicF())
9154unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
9157 if (VT == MVT::f16 && Subtarget.hasBasicF())
9166 unsigned Depth)
const {
9167 EVT VT =
Op.getValueType();
9169 unsigned Opc =
Op.getOpcode();
9176 MVT SrcVT = Src.getSimpleValueType();
9181 if (OriginalDemandedBits.
countr_zero() >= NumElts)
9185 APInt KnownUndef, KnownZero;
9201 if (KnownSrc.
One[SrcBits - 1])
9203 else if (KnownSrc.
Zero[SrcBits - 1])
9208 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
9215 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(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue performEXTRACT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VSHUF.
static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
size_type count() const
count - Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
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.
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.
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 getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(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.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & 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,...
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-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
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.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
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 "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ 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.
@ 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.
@ ADD
Simple integer binary arithmetic operators.
@ 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.
@ 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...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ 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.
@ 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.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ 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.
@ 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),...
@ 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.
@ 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.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > 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.
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Align getNonZeroOrigAlign() const
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
bool isBeforeLegalize() 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)