31#include "llvm/IR/IntrinsicsLoongArch.h"
41#define DEBUG_TYPE "loongarch-isel-lowering"
56 cl::desc(
"Maximum number of instructions used (including code sequence "
57 "to generate the value and moving the value to FPR) when "
58 "materializing floating-point immediates (default = 3)"),
62 "Materialize FP immediate within 2 instructions"),
64 "Materialize FP immediate within 3 instructions"),
66 "Materialize FP immediate within 4 instructions"),
68 "Materialize FP immediate within 5 instructions"),
70 "Materialize FP immediate within 6 instructions "
71 "(behaves same as 5 on loongarch64)")));
74 cl::desc(
"Trap on integer division by zero."),
81 MVT GRLenVT = Subtarget.getGRLenVT();
86 if (Subtarget.hasBasicF())
88 if (Subtarget.hasBasicD())
92 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
94 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
96 if (Subtarget.hasExtLSX())
100 if (Subtarget.hasExtLASX())
101 for (
MVT VT : LASXVTs)
169 if (Subtarget.is64Bit()) {
197 if (!Subtarget.is64Bit()) {
203 if (Subtarget.hasBasicD())
215 if (Subtarget.hasBasicF()) {
247 if (Subtarget.is64Bit()) {
252 if (!Subtarget.hasBasicD()) {
254 if (Subtarget.is64Bit()) {
263 if (Subtarget.hasBasicD()) {
296 if (Subtarget.is64Bit()) {
304 if (Subtarget.hasExtLSX()) {
319 for (
MVT VT : LSXVTs) {
333 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
355 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
357 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
359 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
363 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
388 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
389 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
404 if (Subtarget.hasExtLASX()) {
405 for (
MVT VT : LASXVTs) {
420 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
443 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
445 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
447 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
451 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
480 if (Subtarget.hasExtLSX()) {
487 if (Subtarget.hasExtLASX())
510 if (Subtarget.hasLAMCAS())
513 if (Subtarget.hasSCQ()) {
530 switch (
Op.getOpcode()) {
531 case ISD::ATOMIC_FENCE:
532 return lowerATOMIC_FENCE(
Op, DAG);
534 return lowerEH_DWARF_CFA(
Op, DAG);
536 return lowerGlobalAddress(
Op, DAG);
538 return lowerGlobalTLSAddress(
Op, DAG);
540 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
542 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
544 return lowerINTRINSIC_VOID(
Op, DAG);
546 return lowerBlockAddress(
Op, DAG);
548 return lowerJumpTable(
Op, DAG);
550 return lowerShiftLeftParts(
Op, DAG);
552 return lowerShiftRightParts(
Op, DAG,
true);
554 return lowerShiftRightParts(
Op, DAG,
false);
556 return lowerConstantPool(
Op, DAG);
558 return lowerFP_TO_SINT(
Op, DAG);
560 return lowerBITCAST(
Op, DAG);
562 return lowerUINT_TO_FP(
Op, DAG);
564 return lowerSINT_TO_FP(
Op, DAG);
566 return lowerVASTART(
Op, DAG);
568 return lowerFRAMEADDR(
Op, DAG);
570 return lowerRETURNADDR(
Op, DAG);
572 return lowerWRITE_REGISTER(
Op, DAG);
574 return lowerINSERT_VECTOR_ELT(
Op, DAG);
576 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
578 return lowerBUILD_VECTOR(
Op, DAG);
580 return lowerCONCAT_VECTORS(
Op, DAG);
582 return lowerVECTOR_SHUFFLE(
Op, DAG);
584 return lowerBITREVERSE(
Op, DAG);
586 return lowerSCALAR_TO_VECTOR(
Op, DAG);
588 return lowerPREFETCH(
Op, DAG);
590 return lowerSELECT(
Op, DAG);
592 return lowerBRCOND(
Op, DAG);
593 case ISD::FP_TO_FP16:
594 return lowerFP_TO_FP16(
Op, DAG);
595 case ISD::FP16_TO_FP:
596 return lowerFP16_TO_FP(
Op, DAG);
597 case ISD::FP_TO_BF16:
598 return lowerFP_TO_BF16(
Op, DAG);
599 case ISD::BF16_TO_FP:
600 return lowerBF16_TO_FP(
Op, DAG);
601 case ISD::VECREDUCE_ADD:
602 return lowerVECREDUCE_ADD(
Op, DAG);
603 case ISD::VECREDUCE_AND:
604 case ISD::VECREDUCE_OR:
605 case ISD::VECREDUCE_XOR:
606 case ISD::VECREDUCE_SMAX:
607 case ISD::VECREDUCE_SMIN:
608 case ISD::VECREDUCE_UMAX:
609 case ISD::VECREDUCE_UMIN:
610 return lowerVECREDUCE(
Op, DAG);
612 return lowerConstantFP(
Op, DAG);
619 EVT VT =
Op.getValueType();
624 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
625 (VT == MVT::f64 && Subtarget.hasBasicD()));
642 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.
is64Bit()) ? 2 : 1);
684 MVT OpVT =
Op.getSimpleValueType();
691 unsigned LegalVecSize = 128;
692 bool isLASX256Vector =
702 if (isLASX256Vector) {
707 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
713 if (isLASX256Vector) {
739 MVT OpVT =
Op.getSimpleValueType();
752 MVT GRLenVT = Subtarget.getGRLenVT();
754 for (
int i = NumEles; i > 1; i /= 2) {
757 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
766 unsigned IsData =
Op.getConstantOperandVal(4);
771 return Op.getOperand(0);
786 if (
LHS == LHS2 &&
RHS == RHS2) {
791 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
807 MVT VT =
N->getSimpleValueType(0);
838 if (~TrueVal == FalseVal) {
878 unsigned SelOpNo = 0;
888 unsigned ConstSelOpNo = 1;
889 unsigned OtherSelOpNo = 2;
896 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
901 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
907 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
909 std::swap(NewConstOps[0], NewConstOps[1]);
921 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
923 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
926 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
927 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
947 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
961 int64_t
C = RHSC->getSExtValue();
1004 MVT VT =
Op.getSimpleValueType();
1005 MVT GRLenVT = Subtarget.getGRLenVT();
1010 if (
Op.hasOneUse()) {
1011 unsigned UseOpc =
Op->user_begin()->getOpcode();
1013 SDNode *BinOp = *
Op->user_begin();
1020 return lowerSELECT(NewSel, DAG);
1060 if (TrueVal - 1 == FalseVal)
1062 if (TrueVal + 1 == FalseVal)
1069 RHS == TrueV &&
LHS == FalseV) {
1101 MVT GRLenVT = Subtarget.getGRLenVT();
1113 Op.getOperand(0),
LHS,
RHS, TargetCC,
1117 Op.getOperand(0), CondV,
Op.getOperand(2));
1127LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1130 MVT OpVT =
Op.getSimpleValueType();
1141 EVT ResTy =
Op->getValueType(0);
1146 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1156 for (
unsigned int i = 0; i < NewEltNum; i++) {
1159 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1178 for (
unsigned int i = 0; i < NewEltNum; i++)
1179 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1180 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1198 if (EltBits > 32 || EltBits == 1)
1226 int MaskOffset,
const APInt &Zeroable) {
1227 int Size = Mask.size();
1228 unsigned SizeInBits =
Size * ScalarSizeInBits;
1230 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1231 for (
int i = 0; i <
Size; i += Scale)
1232 for (
int j = 0; j < Shift; ++j)
1233 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1241 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1242 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1247 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1248 for (
int i = 0; i !=
Size; i += Scale) {
1249 unsigned Pos =
Left ? i + Shift : i;
1250 unsigned Low =
Left ? i : i + Shift;
1251 unsigned Len = Scale - Shift;
1256 int ShiftEltBits = ScalarSizeInBits * Scale;
1257 bool ByteShift = ShiftEltBits > 64;
1260 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1264 Scale = ByteShift ? Scale / 2 : Scale;
1270 return (
int)ShiftAmt;
1273 unsigned MaxWidth = 128;
1274 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1275 for (
int Shift = 1; Shift != Scale; ++Shift)
1276 for (
bool Left : {
true,
false})
1277 if (CheckZeros(Shift, Scale,
Left)) {
1278 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1303 const APInt &Zeroable) {
1304 int Size = Mask.size();
1318 Mask,
Size, Zeroable);
1326 "Illegal integer vector type");
1335template <
typename ValType>
1338 unsigned CheckStride,
1340 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1344 if (*
I != -1 && *
I != ExpectedIndex)
1346 ExpectedIndex += ExpectedIndexStride;
1350 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1362 int Size = Mask.size();
1372 int ScalarSizeInBits = VectorSizeInBits /
Size;
1373 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1374 (void)ScalarSizeInBits;
1376 for (
int i = 0; i <
Size; ++i) {
1382 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1399 RepeatedMask.
assign(LaneSize, -1);
1400 int Size = Mask.size();
1401 for (
int i = 0; i <
Size; ++i) {
1402 assert(Mask[i] == -1 || Mask[i] >= 0);
1405 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1412 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1413 if (RepeatedMask[i % LaneSize] < 0)
1415 RepeatedMask[i % LaneSize] = LocalM;
1416 else if (RepeatedMask[i % LaneSize] != LocalM)
1433 int NumElts = RepeatedMask.
size();
1435 int Scale = 16 / NumElts;
1437 for (
int i = 0; i < NumElts; ++i) {
1438 int M = RepeatedMask[i];
1439 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1440 "Unexpected mask index.");
1445 int StartIdx = i - (M % NumElts);
1452 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1455 Rotation = CandidateRotation;
1456 else if (Rotation != CandidateRotation)
1460 SDValue MaskV = M < NumElts ? V1 : V2;
1471 else if (TargetV != MaskV)
1476 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1477 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1486 return Rotation * Scale;
1505 if (ByteRotation <= 0)
1512 int LoByteShift = 16 - ByteRotation;
1513 int HiByteShift = ByteRotation;
1536 const APInt &Zeroable) {
1550 for (
int i = 0; i < NumElements; i++) {
1554 if (i % Scale != 0) {
1565 SDValue V = M < NumElements ? V1 : V2;
1566 M = M % NumElements;
1569 Offset = M - (i / Scale);
1572 if (
Offset % (NumElements / Scale))
1574 }
else if (InputV != V)
1577 if (M != (
Offset + (i / Scale)))
1588 if (
Offset >= (NumElements / 2)) {
1590 Offset -= (NumElements / 2);
1597 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1601 }
while (Scale > 1);
1607 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1608 NumExtElements *= 2) {
1628 int SplatIndex = -1;
1629 for (
const auto &M : Mask) {
1636 if (SplatIndex == -1)
1639 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1671 unsigned SubVecSize = 4;
1672 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1675 int SubMask[4] = {-1, -1, -1, -1};
1676 for (
unsigned i = 0; i < SubVecSize; ++i) {
1677 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1683 M -= 4 * (j / SubVecSize);
1684 if (M < 0 || M >= 4)
1690 if (SubMask[i] == -1)
1694 else if (M != -1 && M != SubMask[i])
1701 for (
int i = SubVecSize - 1; i >= 0; --i) {
1714 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1736 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
1745 for (
int i = 0; i < WidenNumElts; ++i)
1746 WidenMask[i] = WidenNumElts - 1 - i;
1778 const auto &Begin = Mask.begin();
1779 const auto &End = Mask.end();
1780 SDValue OriV1 = V1, OriV2 = V2;
1818 const auto &Begin = Mask.begin();
1819 const auto &End = Mask.end();
1820 SDValue OriV1 = V1, OriV2 = V2;
1859 const auto &Begin = Mask.begin();
1860 const auto &End = Mask.end();
1861 unsigned HalfSize = Mask.size() / 2;
1862 SDValue OriV1 = V1, OriV2 = V2;
1902 const auto &Begin = Mask.begin();
1903 const auto &End = Mask.end();
1904 SDValue OriV1 = V1, OriV2 = V2;
1942 const auto &Begin = Mask.begin();
1943 const auto &Mid = Mask.begin() + Mask.size() / 2;
1944 const auto &End = Mask.end();
1945 SDValue OriV1 = V1, OriV2 = V2;
1984 const auto &Begin = Mask.begin();
1985 const auto &Mid = Mask.begin() + Mask.size() / 2;
1986 const auto &End = Mask.end();
1987 SDValue OriV1 = V1, OriV2 = V2;
2042 "Vector type is unsupported for lsx!");
2044 "Two operands have different types!");
2046 "Unexpected mask size for shuffle!");
2047 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2049 APInt KnownUndef, KnownZero;
2051 APInt Zeroable = KnownUndef | KnownZero;
2118 int SplatIndex = -1;
2119 for (
const auto &M : Mask) {
2126 if (SplatIndex == -1)
2129 const auto &Begin = Mask.begin();
2130 const auto &End = Mask.end();
2131 int HalfSize = Mask.size() / 2;
2133 if (SplatIndex >= HalfSize)
2136 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2154 if (Mask.size() <= 4)
2165 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2168 unsigned MaskImm = 0;
2169 for (
unsigned i = 0; i < Mask.size(); ++i) {
2172 MaskImm |= Mask[i] << (i * 2);
2184 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2188 unsigned HalfSize = NumElts / 2;
2189 bool FrontLo =
true, FrontHi =
true;
2190 bool BackLo =
true, BackHi =
true;
2192 auto inRange = [](
int val,
int low,
int high) {
2193 return (val == -1) || (val >= low && val < high);
2196 for (
unsigned i = 0; i < HalfSize; ++i) {
2197 int Fronti = Mask[i];
2198 int Backi = Mask[i + HalfSize];
2200 FrontLo &=
inRange(Fronti, 0, HalfSize);
2201 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2202 BackLo &=
inRange(Backi, 0, HalfSize);
2203 BackHi &=
inRange(Backi, HalfSize, NumElts);
2209 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2214 for (
unsigned i = 0; i < NumElts; ++i)
2241 const auto &Begin = Mask.begin();
2242 const auto &End = Mask.end();
2243 unsigned HalfSize = Mask.size() / 2;
2244 unsigned LeftSize = HalfSize / 2;
2245 SDValue OriV1 = V1, OriV2 = V2;
2252 Mask.size() + HalfSize - LeftSize, 1) &&
2254 Mask.size() + HalfSize + LeftSize, 1))
2265 Mask.size() + HalfSize - LeftSize, 1) &&
2267 Mask.size() + HalfSize + LeftSize, 1))
2280 const auto &Begin = Mask.begin();
2281 const auto &End = Mask.end();
2282 unsigned HalfSize = Mask.size() / 2;
2283 SDValue OriV1 = V1, OriV2 = V2;
2290 Mask.size() + HalfSize, 1))
2301 Mask.size() + HalfSize, 1))
2314 const auto &Begin = Mask.begin();
2315 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2316 const auto &Mid = Mask.begin() + Mask.size() / 2;
2317 const auto &RightMid = Mask.end() - Mask.size() / 4;
2318 const auto &End = Mask.end();
2319 unsigned HalfSize = Mask.size() / 2;
2320 SDValue OriV1 = V1, OriV2 = V2;
2349 const auto &Begin = Mask.begin();
2350 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2351 const auto &Mid = Mask.begin() + Mask.size() / 2;
2352 const auto &RightMid = Mask.end() - Mask.size() / 4;
2353 const auto &End = Mask.end();
2354 unsigned HalfSize = Mask.size() / 2;
2355 SDValue OriV1 = V1, OriV2 = V2;
2386 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2391 int MaskSize = Mask.size();
2397 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2399 for (
int i = 0; i < MaskSize; ++i) {
2400 if (Mask[i] ==
Base + i || Mask[i] == -1)
2402 if (Mask[i] != Replaced)
2413 int Idx = checkReplaceOne(0, MaskSize);
2419 Idx = checkReplaceOne(MaskSize, 0);
2432 int MaskSize = Mask.size();
2433 int HalfSize = Mask.size() / 2;
2434 const auto &Begin = Mask.begin();
2435 const auto &Mid = Mask.begin() + HalfSize;
2436 const auto &End = Mask.end();
2448 for (
auto it = Begin; it < Mid; it++) {
2451 else if ((*it >= 0 && *it < HalfSize) ||
2452 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2453 int M = *it < HalfSize ? *it : *it - HalfSize;
2458 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2460 for (
auto it = Mid; it < End; it++) {
2463 else if ((*it >= HalfSize && *it < MaskSize) ||
2464 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2465 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2470 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2502 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2504 int MaskSize = Mask.size();
2505 int HalfSize = Mask.size() / 2;
2508 HalfMaskType preMask =
None, postMask =
None;
2510 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2511 return M < 0 || (M >= 0 && M < HalfSize) ||
2512 (M >= MaskSize && M < MaskSize + HalfSize);
2514 preMask = HighLaneTy;
2515 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2516 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2517 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2519 preMask = LowLaneTy;
2521 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2522 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2523 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2525 postMask = LowLaneTy;
2526 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2527 return M < 0 || (M >= 0 && M < HalfSize) ||
2528 (M >= MaskSize && M < MaskSize + HalfSize);
2530 postMask = HighLaneTy;
2538 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2541 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2554 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2555 *it = *it < 0 ? *it : *it - HalfSize;
2557 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2558 *it = *it < 0 ? *it : *it + HalfSize;
2560 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2573 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2574 *it = *it < 0 ? *it : *it - HalfSize;
2576 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2589 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2590 *it = *it < 0 ? *it : *it + HalfSize;
2615 int Size = Mask.size();
2616 int LaneSize =
Size / 2;
2618 bool LaneCrossing[2] = {
false,
false};
2619 for (
int i = 0; i <
Size; ++i)
2620 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2621 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2624 if (!LaneCrossing[0] && !LaneCrossing[1])
2628 InLaneMask.
assign(Mask.begin(), Mask.end());
2629 for (
int i = 0; i <
Size; ++i) {
2630 int &M = InLaneMask[i];
2633 if (((M %
Size) / LaneSize) != (i / LaneSize))
2634 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2639 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2654 "Vector type is unsupported for lasx!");
2656 "Two operands have different types!");
2658 "Unexpected mask size for shuffle!");
2659 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2660 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2662 APInt KnownUndef, KnownZero;
2664 APInt Zeroable = KnownUndef | KnownZero;
2741 ArrayRef<int> OrigMask = SVOp->
getMask();
2744 MVT VT =
Op.getSimpleValueType();
2748 bool V1IsUndef = V1.
isUndef();
2749 bool V2IsUndef = V2.
isUndef();
2750 if (V1IsUndef && V2IsUndef)
2763 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2764 SmallVector<int, 8> NewMask(OrigMask);
2765 for (
int &M : NewMask)
2766 if (M >= NumElements)
2772 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2773 (void)MaskUpperLimit;
2775 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2776 "Out of bounds shuffle index");
2798 std::tie(Res, Chain) =
2799 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2800 if (Subtarget.is64Bit())
2817 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2818 CallOptions,
DL, Chain);
2824 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2830 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2831 if (Subtarget.is64Bit())
2838 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2839 MVT VT =
Op.getSimpleValueType();
2848 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
2865 "Unsupported vector type for broadcast.");
2868 bool IsIdeneity =
true;
2870 for (
int i = 0; i !=
NumOps; i++) {
2872 if (
Op.getOpcode() != ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2884 auto ExtType = LN->getExtensionType();
2890 ? DAG.
getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other)
2892 SDValue Ops[] = {LN->getChain(), LN->getBasePtr(), LN->getOffset()};
2910 for (
unsigned i = 1; i <
Ops.size(); ++i) {
2924 EVT ResTy,
unsigned first) {
2927 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
2930 Node->op_begin() + first + NumElts);
2939 MVT VT =
Node->getSimpleValueType(0);
2940 EVT ResTy =
Op->getValueType(0);
2943 APInt SplatValue, SplatUndef;
2944 unsigned SplatBitSize;
2947 bool UseSameConstant =
true;
2952 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
2953 (!Subtarget.hasExtLASX() || !Is256Vec))
2959 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
2961 SplatBitSize <= 64) {
2963 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2967 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
2974 if ((Is128Vec && ResTy == MVT::v4i32) ||
2975 (Is256Vec && ResTy == MVT::v8i32))
2981 switch (SplatBitSize) {
2985 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
2988 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
2991 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
2994 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3002 if (ViaVecTy != ResTy)
3003 Result = DAG.
getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
3011 for (
unsigned i = 0; i < NumElts; ++i) {
3016 ConstantValue = Opi;
3017 else if (ConstantValue != Opi)
3018 UseSameConstant =
false;
3023 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3025 for (
unsigned i = 0; i < NumElts; ++i) {
3043 BitVector UndefElements;
3044 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3045 UndefElements.
count() == 0) {
3049 EVT FillTy = Is256Vec
3055 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3058 unsigned SplatLen = NumElts / SeqLen;
3064 if (SplatEltTy == MVT::i128)
3065 SplatTy = MVT::v4i64;
3075 DL, SplatTy, SrcVec);
3090 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3091 ResTy == MVT::v4f64) {
3092 unsigned NonUndefCount = 0;
3093 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3094 if (!
Node->getOperand(i).isUndef()) {
3096 if (NonUndefCount > 1)
3100 if (NonUndefCount == 1)
3113 VecTy, NumElts / 2);
3124 MVT ResVT =
Op.getSimpleValueType();
3128 unsigned NumFreezeUndef = 0;
3129 unsigned NumZero = 0;
3130 unsigned NumNonZero = 0;
3131 unsigned NonZeros = 0;
3132 SmallSet<SDValue, 4> Undefs;
3133 for (
unsigned i = 0; i != NumOperands; ++i) {
3148 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3155 if (NumNonZero > 2) {
3159 Ops.slice(0, NumOperands / 2));
3161 Ops.slice(NumOperands / 2));
3174 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3176 for (
unsigned i = 0; i != NumOperands; ++i) {
3177 if ((NonZeros & (1 << i)) == 0)
3188LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3190 MVT EltVT =
Op.getSimpleValueType();
3195 MVT GRLenVT = Subtarget.getGRLenVT();
3227 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3247LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3249 MVT VT =
Op.getSimpleValueType();
3272 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3274 for (
unsigned i = 0; i < NumElts; ++i) {
3282 for (
unsigned i = 0; i < NumElts; ++i) {
3291 for (
unsigned i = 0; i < NumElts; ++i)
3315 return DAG.
getNode(ISD::MEMBARRIER,
DL, MVT::Other,
Op.getOperand(0));
3323 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3325 "On LA64, only 64-bit registers can be written.");
3326 return Op.getOperand(0);
3329 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3331 "On LA32, only 32-bit registers can be written.");
3332 return Op.getOperand(0);
3342 "be a constant integer");
3348 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3349 EVT VT =
Op.getValueType();
3352 unsigned Depth =
Op.getConstantOperandVal(0);
3353 int GRLenInBytes = Subtarget.getGRLen() / 8;
3356 int Offset = -(GRLenInBytes * 2);
3368 if (
Op.getConstantOperandVal(0) != 0) {
3370 "return address can only be determined for the current frame");
3376 MVT GRLenVT = Subtarget.getGRLenVT();
3388 auto Size = Subtarget.getGRLen() / 8;
3396 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3406 MachinePointerInfo(SV));
3411 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3412 !Subtarget.hasBasicD() &&
"unexpected target features");
3418 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3432 EVT RetVT =
Op.getValueType();
3438 std::tie(Result, Chain) =
3445 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3446 !Subtarget.hasBasicD() &&
"unexpected target features");
3457 EVT RetVT =
Op.getValueType();
3463 std::tie(Result, Chain) =
3472 EVT VT =
Op.getValueType();
3476 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3477 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3481 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3496 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
3498 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3499 !Subtarget.hasBasicD()) {
3506 return DAG.
getNode(ISD::BITCAST,
DL,
Op.getValueType(), Trunc);
3523 N->getOffset(), Flags);
3531template <
class NodeTy>
3534 bool IsLocal)
const {
3545 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3616 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3618 const GlobalValue *GV =
N->getGlobal();
3630 unsigned Opc,
bool UseGOT,
3634 MVT GRLenVT = Subtarget.getGRLenVT();
3648 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3686 Args.emplace_back(Load, CallTy);
3689 TargetLowering::CallLoweringInfo CLI(DAG);
3704 const GlobalValue *GV =
N->getGlobal();
3718LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3725 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3728 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3741 return getDynamicTLSAddr(
N, DAG,
3742 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3743 : LoongArch::PseudoLA_TLS_GD,
3750 return getDynamicTLSAddr(
N, DAG,
3751 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3752 : LoongArch::PseudoLA_TLS_LD,
3757 return getStaticTLSAddr(
N, DAG,
3758 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3759 : LoongArch::PseudoLA_TLS_IE,
3766 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3770 return getTLSDescAddr(
N, DAG,
3771 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3772 : LoongArch::PseudoLA_TLS_DESC,
3776template <
unsigned N>
3781 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
3782 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
3784 ": argument out of range.");
3791LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3793 switch (
Op.getConstantOperandVal(0)) {
3796 case Intrinsic::thread_pointer: {
3800 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3801 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3802 case Intrinsic::loongarch_lsx_vreplvei_d:
3803 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3805 case Intrinsic::loongarch_lsx_vreplvei_w:
3806 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3807 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3808 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3809 case Intrinsic::loongarch_lasx_xvpickve_d:
3810 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3812 case Intrinsic::loongarch_lasx_xvinsve0_d:
3814 case Intrinsic::loongarch_lsx_vsat_b:
3815 case Intrinsic::loongarch_lsx_vsat_bu:
3816 case Intrinsic::loongarch_lsx_vrotri_b:
3817 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3818 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3819 case Intrinsic::loongarch_lsx_vsrlri_b:
3820 case Intrinsic::loongarch_lsx_vsrari_b:
3821 case Intrinsic::loongarch_lsx_vreplvei_h:
3822 case Intrinsic::loongarch_lasx_xvsat_b:
3823 case Intrinsic::loongarch_lasx_xvsat_bu:
3824 case Intrinsic::loongarch_lasx_xvrotri_b:
3825 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3826 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3827 case Intrinsic::loongarch_lasx_xvsrlri_b:
3828 case Intrinsic::loongarch_lasx_xvsrari_b:
3829 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3830 case Intrinsic::loongarch_lasx_xvpickve_w:
3831 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3833 case Intrinsic::loongarch_lasx_xvinsve0_w:
3835 case Intrinsic::loongarch_lsx_vsat_h:
3836 case Intrinsic::loongarch_lsx_vsat_hu:
3837 case Intrinsic::loongarch_lsx_vrotri_h:
3838 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3839 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3840 case Intrinsic::loongarch_lsx_vsrlri_h:
3841 case Intrinsic::loongarch_lsx_vsrari_h:
3842 case Intrinsic::loongarch_lsx_vreplvei_b:
3843 case Intrinsic::loongarch_lasx_xvsat_h:
3844 case Intrinsic::loongarch_lasx_xvsat_hu:
3845 case Intrinsic::loongarch_lasx_xvrotri_h:
3846 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3847 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3848 case Intrinsic::loongarch_lasx_xvsrlri_h:
3849 case Intrinsic::loongarch_lasx_xvsrari_h:
3850 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3852 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3853 case Intrinsic::loongarch_lsx_vsrani_b_h:
3854 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3855 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3856 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3857 case Intrinsic::loongarch_lsx_vssrani_b_h:
3858 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3859 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3860 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3861 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3862 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3863 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3864 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3865 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3866 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3867 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3868 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3869 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3870 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3871 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3872 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3873 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3874 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3875 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3877 case Intrinsic::loongarch_lsx_vsat_w:
3878 case Intrinsic::loongarch_lsx_vsat_wu:
3879 case Intrinsic::loongarch_lsx_vrotri_w:
3880 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3881 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3882 case Intrinsic::loongarch_lsx_vsrlri_w:
3883 case Intrinsic::loongarch_lsx_vsrari_w:
3884 case Intrinsic::loongarch_lsx_vslei_bu:
3885 case Intrinsic::loongarch_lsx_vslei_hu:
3886 case Intrinsic::loongarch_lsx_vslei_wu:
3887 case Intrinsic::loongarch_lsx_vslei_du:
3888 case Intrinsic::loongarch_lsx_vslti_bu:
3889 case Intrinsic::loongarch_lsx_vslti_hu:
3890 case Intrinsic::loongarch_lsx_vslti_wu:
3891 case Intrinsic::loongarch_lsx_vslti_du:
3892 case Intrinsic::loongarch_lsx_vbsll_v:
3893 case Intrinsic::loongarch_lsx_vbsrl_v:
3894 case Intrinsic::loongarch_lasx_xvsat_w:
3895 case Intrinsic::loongarch_lasx_xvsat_wu:
3896 case Intrinsic::loongarch_lasx_xvrotri_w:
3897 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
3898 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
3899 case Intrinsic::loongarch_lasx_xvsrlri_w:
3900 case Intrinsic::loongarch_lasx_xvsrari_w:
3901 case Intrinsic::loongarch_lasx_xvslei_bu:
3902 case Intrinsic::loongarch_lasx_xvslei_hu:
3903 case Intrinsic::loongarch_lasx_xvslei_wu:
3904 case Intrinsic::loongarch_lasx_xvslei_du:
3905 case Intrinsic::loongarch_lasx_xvslti_bu:
3906 case Intrinsic::loongarch_lasx_xvslti_hu:
3907 case Intrinsic::loongarch_lasx_xvslti_wu:
3908 case Intrinsic::loongarch_lasx_xvslti_du:
3909 case Intrinsic::loongarch_lasx_xvbsll_v:
3910 case Intrinsic::loongarch_lasx_xvbsrl_v:
3912 case Intrinsic::loongarch_lsx_vseqi_b:
3913 case Intrinsic::loongarch_lsx_vseqi_h:
3914 case Intrinsic::loongarch_lsx_vseqi_w:
3915 case Intrinsic::loongarch_lsx_vseqi_d:
3916 case Intrinsic::loongarch_lsx_vslei_b:
3917 case Intrinsic::loongarch_lsx_vslei_h:
3918 case Intrinsic::loongarch_lsx_vslei_w:
3919 case Intrinsic::loongarch_lsx_vslei_d:
3920 case Intrinsic::loongarch_lsx_vslti_b:
3921 case Intrinsic::loongarch_lsx_vslti_h:
3922 case Intrinsic::loongarch_lsx_vslti_w:
3923 case Intrinsic::loongarch_lsx_vslti_d:
3924 case Intrinsic::loongarch_lasx_xvseqi_b:
3925 case Intrinsic::loongarch_lasx_xvseqi_h:
3926 case Intrinsic::loongarch_lasx_xvseqi_w:
3927 case Intrinsic::loongarch_lasx_xvseqi_d:
3928 case Intrinsic::loongarch_lasx_xvslei_b:
3929 case Intrinsic::loongarch_lasx_xvslei_h:
3930 case Intrinsic::loongarch_lasx_xvslei_w:
3931 case Intrinsic::loongarch_lasx_xvslei_d:
3932 case Intrinsic::loongarch_lasx_xvslti_b:
3933 case Intrinsic::loongarch_lasx_xvslti_h:
3934 case Intrinsic::loongarch_lasx_xvslti_w:
3935 case Intrinsic::loongarch_lasx_xvslti_d:
3937 case Intrinsic::loongarch_lsx_vsrlni_h_w:
3938 case Intrinsic::loongarch_lsx_vsrani_h_w:
3939 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
3940 case Intrinsic::loongarch_lsx_vsrarni_h_w:
3941 case Intrinsic::loongarch_lsx_vssrlni_h_w:
3942 case Intrinsic::loongarch_lsx_vssrani_h_w:
3943 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
3944 case Intrinsic::loongarch_lsx_vssrani_hu_w:
3945 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
3946 case Intrinsic::loongarch_lsx_vssrarni_h_w:
3947 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
3948 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
3949 case Intrinsic::loongarch_lsx_vfrstpi_b:
3950 case Intrinsic::loongarch_lsx_vfrstpi_h:
3951 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
3952 case Intrinsic::loongarch_lasx_xvsrani_h_w:
3953 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
3954 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
3955 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
3956 case Intrinsic::loongarch_lasx_xvssrani_h_w:
3957 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
3958 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
3959 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
3960 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
3961 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
3962 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
3963 case Intrinsic::loongarch_lasx_xvfrstpi_b:
3964 case Intrinsic::loongarch_lasx_xvfrstpi_h:
3966 case Intrinsic::loongarch_lsx_vsat_d:
3967 case Intrinsic::loongarch_lsx_vsat_du:
3968 case Intrinsic::loongarch_lsx_vrotri_d:
3969 case Intrinsic::loongarch_lsx_vsrlri_d:
3970 case Intrinsic::loongarch_lsx_vsrari_d:
3971 case Intrinsic::loongarch_lasx_xvsat_d:
3972 case Intrinsic::loongarch_lasx_xvsat_du:
3973 case Intrinsic::loongarch_lasx_xvrotri_d:
3974 case Intrinsic::loongarch_lasx_xvsrlri_d:
3975 case Intrinsic::loongarch_lasx_xvsrari_d:
3977 case Intrinsic::loongarch_lsx_vsrlni_w_d:
3978 case Intrinsic::loongarch_lsx_vsrani_w_d:
3979 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
3980 case Intrinsic::loongarch_lsx_vsrarni_w_d:
3981 case Intrinsic::loongarch_lsx_vssrlni_w_d:
3982 case Intrinsic::loongarch_lsx_vssrani_w_d:
3983 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
3984 case Intrinsic::loongarch_lsx_vssrani_wu_d:
3985 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
3986 case Intrinsic::loongarch_lsx_vssrarni_w_d:
3987 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
3988 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
3989 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
3990 case Intrinsic::loongarch_lasx_xvsrani_w_d:
3991 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
3992 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
3993 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
3994 case Intrinsic::loongarch_lasx_xvssrani_w_d:
3995 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
3996 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
3997 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
3998 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
3999 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4000 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4002 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4003 case Intrinsic::loongarch_lsx_vsrani_d_q:
4004 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4005 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4006 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4007 case Intrinsic::loongarch_lsx_vssrani_d_q:
4008 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4009 case Intrinsic::loongarch_lsx_vssrani_du_q:
4010 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4011 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4012 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4013 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4014 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4015 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4016 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4017 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4018 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4019 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4020 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4021 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4022 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4023 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4024 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4025 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4027 case Intrinsic::loongarch_lsx_vnori_b:
4028 case Intrinsic::loongarch_lsx_vshuf4i_b:
4029 case Intrinsic::loongarch_lsx_vshuf4i_h:
4030 case Intrinsic::loongarch_lsx_vshuf4i_w:
4031 case Intrinsic::loongarch_lasx_xvnori_b:
4032 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4033 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4034 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4035 case Intrinsic::loongarch_lasx_xvpermi_d:
4037 case Intrinsic::loongarch_lsx_vshuf4i_d:
4038 case Intrinsic::loongarch_lsx_vpermi_w:
4039 case Intrinsic::loongarch_lsx_vbitseli_b:
4040 case Intrinsic::loongarch_lsx_vextrins_b:
4041 case Intrinsic::loongarch_lsx_vextrins_h:
4042 case Intrinsic::loongarch_lsx_vextrins_w:
4043 case Intrinsic::loongarch_lsx_vextrins_d:
4044 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4045 case Intrinsic::loongarch_lasx_xvpermi_w:
4046 case Intrinsic::loongarch_lasx_xvpermi_q:
4047 case Intrinsic::loongarch_lasx_xvbitseli_b:
4048 case Intrinsic::loongarch_lasx_xvextrins_b:
4049 case Intrinsic::loongarch_lasx_xvextrins_h:
4050 case Intrinsic::loongarch_lasx_xvextrins_w:
4051 case Intrinsic::loongarch_lasx_xvextrins_d:
4053 case Intrinsic::loongarch_lsx_vrepli_b:
4054 case Intrinsic::loongarch_lsx_vrepli_h:
4055 case Intrinsic::loongarch_lsx_vrepli_w:
4056 case Intrinsic::loongarch_lsx_vrepli_d:
4057 case Intrinsic::loongarch_lasx_xvrepli_b:
4058 case Intrinsic::loongarch_lasx_xvrepli_h:
4059 case Intrinsic::loongarch_lasx_xvrepli_w:
4060 case Intrinsic::loongarch_lasx_xvrepli_d:
4062 case Intrinsic::loongarch_lsx_vldi:
4063 case Intrinsic::loongarch_lasx_xvldi:
4079LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4082 MVT GRLenVT = Subtarget.getGRLenVT();
4083 EVT VT =
Op.getValueType();
4085 const StringRef ErrorMsgOOR =
"argument out of range";
4086 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4087 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4089 switch (
Op.getConstantOperandVal(1)) {
4092 case Intrinsic::loongarch_crc_w_b_w:
4093 case Intrinsic::loongarch_crc_w_h_w:
4094 case Intrinsic::loongarch_crc_w_w_w:
4095 case Intrinsic::loongarch_crc_w_d_w:
4096 case Intrinsic::loongarch_crcc_w_b_w:
4097 case Intrinsic::loongarch_crcc_w_h_w:
4098 case Intrinsic::loongarch_crcc_w_w_w:
4099 case Intrinsic::loongarch_crcc_w_d_w:
4101 case Intrinsic::loongarch_csrrd_w:
4102 case Intrinsic::loongarch_csrrd_d: {
4103 unsigned Imm =
Op.getConstantOperandVal(2);
4109 case Intrinsic::loongarch_csrwr_w:
4110 case Intrinsic::loongarch_csrwr_d: {
4111 unsigned Imm =
Op.getConstantOperandVal(3);
4115 {Chain,
Op.getOperand(2),
4118 case Intrinsic::loongarch_csrxchg_w:
4119 case Intrinsic::loongarch_csrxchg_d: {
4120 unsigned Imm =
Op.getConstantOperandVal(4);
4124 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4127 case Intrinsic::loongarch_iocsrrd_d: {
4132#define IOCSRRD_CASE(NAME, NODE) \
4133 case Intrinsic::loongarch_##NAME: { \
4134 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4135 {Chain, Op.getOperand(2)}); \
4141 case Intrinsic::loongarch_cpucfg: {
4143 {Chain,
Op.getOperand(2)});
4145 case Intrinsic::loongarch_lddir_d: {
4146 unsigned Imm =
Op.getConstantOperandVal(3);
4151 case Intrinsic::loongarch_movfcsr2gr: {
4152 if (!Subtarget.hasBasicF())
4154 unsigned Imm =
Op.getConstantOperandVal(2);
4160 case Intrinsic::loongarch_lsx_vld:
4161 case Intrinsic::loongarch_lsx_vldrepl_b:
4162 case Intrinsic::loongarch_lasx_xvld:
4163 case Intrinsic::loongarch_lasx_xvldrepl_b:
4167 case Intrinsic::loongarch_lsx_vldrepl_h:
4168 case Intrinsic::loongarch_lasx_xvldrepl_h:
4172 Op,
"argument out of range or not a multiple of 2", DAG)
4174 case Intrinsic::loongarch_lsx_vldrepl_w:
4175 case Intrinsic::loongarch_lasx_xvldrepl_w:
4179 Op,
"argument out of range or not a multiple of 4", DAG)
4181 case Intrinsic::loongarch_lsx_vldrepl_d:
4182 case Intrinsic::loongarch_lasx_xvldrepl_d:
4186 Op,
"argument out of range or not a multiple of 8", DAG)
4197 return Op.getOperand(0);
4203 MVT GRLenVT = Subtarget.getGRLenVT();
4205 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4207 const StringRef ErrorMsgOOR =
"argument out of range";
4208 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4209 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4210 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4212 switch (IntrinsicEnum) {
4216 case Intrinsic::loongarch_cacop_d:
4217 case Intrinsic::loongarch_cacop_w: {
4218 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4220 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4229 case Intrinsic::loongarch_dbar: {
4236 case Intrinsic::loongarch_ibar: {
4243 case Intrinsic::loongarch_break: {
4250 case Intrinsic::loongarch_movgr2fcsr: {
4251 if (!Subtarget.hasBasicF())
4261 case Intrinsic::loongarch_syscall: {
4268#define IOCSRWR_CASE(NAME, NODE) \
4269 case Intrinsic::loongarch_##NAME: { \
4270 SDValue Op3 = Op.getOperand(3); \
4271 return Subtarget.is64Bit() \
4272 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4273 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4274 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4275 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4282 case Intrinsic::loongarch_iocsrwr_d: {
4283 return !Subtarget.is64Bit()
4290#define ASRT_LE_GT_CASE(NAME) \
4291 case Intrinsic::loongarch_##NAME: { \
4292 return !Subtarget.is64Bit() \
4293 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4298#undef ASRT_LE_GT_CASE
4299 case Intrinsic::loongarch_ldpte_d: {
4300 unsigned Imm =
Op.getConstantOperandVal(3);
4301 return !Subtarget.is64Bit()
4306 case Intrinsic::loongarch_lsx_vst:
4307 case Intrinsic::loongarch_lasx_xvst:
4311 case Intrinsic::loongarch_lasx_xvstelm_b:
4316 case Intrinsic::loongarch_lsx_vstelm_b:
4321 case Intrinsic::loongarch_lasx_xvstelm_h:
4326 Op,
"argument out of range or not a multiple of 2", DAG)
4328 case Intrinsic::loongarch_lsx_vstelm_h:
4333 Op,
"argument out of range or not a multiple of 2", DAG)
4335 case Intrinsic::loongarch_lasx_xvstelm_w:
4340 Op,
"argument out of range or not a multiple of 4", DAG)
4342 case Intrinsic::loongarch_lsx_vstelm_w:
4347 Op,
"argument out of range or not a multiple of 4", DAG)
4349 case Intrinsic::loongarch_lasx_xvstelm_d:
4354 Op,
"argument out of range or not a multiple of 8", DAG)
4356 case Intrinsic::loongarch_lsx_vstelm_d:
4361 Op,
"argument out of range or not a multiple of 8", DAG)
4372 EVT VT =
Lo.getValueType();
4413 EVT VT =
Lo.getValueType();
4505 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4506 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4510 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4516 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4543 StringRef ErrorMsg,
bool WithChain =
true) {
4548 Results.push_back(
N->getOperand(0));
4551template <
unsigned N>
4556 const StringRef ErrorMsgOOR =
"argument out of range";
4557 unsigned Imm =
Node->getConstantOperandVal(2);
4591 switch (
N->getConstantOperandVal(0)) {
4594 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4598 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4599 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4603 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4607 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4611 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4612 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4616 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4620 case Intrinsic::loongarch_lsx_bz_b:
4621 case Intrinsic::loongarch_lsx_bz_h:
4622 case Intrinsic::loongarch_lsx_bz_w:
4623 case Intrinsic::loongarch_lsx_bz_d:
4624 case Intrinsic::loongarch_lasx_xbz_b:
4625 case Intrinsic::loongarch_lasx_xbz_h:
4626 case Intrinsic::loongarch_lasx_xbz_w:
4627 case Intrinsic::loongarch_lasx_xbz_d:
4631 case Intrinsic::loongarch_lsx_bz_v:
4632 case Intrinsic::loongarch_lasx_xbz_v:
4636 case Intrinsic::loongarch_lsx_bnz_b:
4637 case Intrinsic::loongarch_lsx_bnz_h:
4638 case Intrinsic::loongarch_lsx_bnz_w:
4639 case Intrinsic::loongarch_lsx_bnz_d:
4640 case Intrinsic::loongarch_lasx_xbnz_b:
4641 case Intrinsic::loongarch_lasx_xbnz_h:
4642 case Intrinsic::loongarch_lasx_xbnz_w:
4643 case Intrinsic::loongarch_lasx_xbnz_d:
4647 case Intrinsic::loongarch_lsx_bnz_v:
4648 case Intrinsic::loongarch_lasx_xbnz_v:
4658 assert(
N->getValueType(0) == MVT::i128 &&
4659 "AtomicCmpSwap on types less than 128 should be legal");
4663 switch (
MemOp->getMergedOrdering()) {
4667 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4671 Opcode = LoongArch::PseudoCmpXchg128;
4678 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4679 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4680 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4681 NewVal.first, NewVal.second,
N->getOperand(0)};
4684 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4695 EVT VT =
N->getValueType(0);
4696 switch (
N->getOpcode()) {
4701 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4702 "Unexpected custom legalisation");
4709 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4710 "Unexpected custom legalisation");
4712 Subtarget.hasDiv32() && VT == MVT::i32
4719 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4720 "Unexpected custom legalisation");
4728 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4729 "Unexpected custom legalisation");
4733 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4734 "Unexpected custom legalisation");
4741 if (Src.getValueType() == MVT::f16)
4742 Src = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Src);
4752 EVT OpVT = Src.getValueType();
4756 std::tie(Result, Chain) =
4761 case ISD::BITCAST: {
4763 EVT SrcVT = Src.getValueType();
4764 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
4765 Subtarget.hasBasicF()) {
4769 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
4771 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4779 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4780 "Unexpected custom legalisation");
4783 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4789 assert((VT == MVT::i16 || VT == MVT::i32) &&
4790 "Unexpected custom legalization");
4791 MVT GRLenVT = Subtarget.getGRLenVT();
4811 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
4812 "Unexpected custom legalization");
4813 MVT GRLenVT = Subtarget.getGRLenVT();
4831 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4832 "Unexpected custom legalisation");
4839 MVT GRLenVT = Subtarget.getGRLenVT();
4840 const StringRef ErrorMsgOOR =
"argument out of range";
4841 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4842 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4844 switch (
N->getConstantOperandVal(1)) {
4847 case Intrinsic::loongarch_movfcsr2gr: {
4848 if (!Subtarget.hasBasicF()) {
4865#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4866 case Intrinsic::loongarch_##NAME: { \
4867 SDValue NODE = DAG.getNode( \
4868 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4869 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4870 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4871 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4872 Results.push_back(NODE.getValue(1)); \
4881#undef CRC_CASE_EXT_BINARYOP
4883#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4884 case Intrinsic::loongarch_##NAME: { \
4885 SDValue NODE = DAG.getNode( \
4886 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4888 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4889 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4890 Results.push_back(NODE.getValue(1)); \
4895#undef CRC_CASE_EXT_UNARYOP
4896#define CSR_CASE(ID) \
4897 case Intrinsic::loongarch_##ID: { \
4898 if (!Subtarget.is64Bit()) \
4899 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
4907 case Intrinsic::loongarch_csrrd_w: {
4921 case Intrinsic::loongarch_csrwr_w: {
4922 unsigned Imm =
N->getConstantOperandVal(3);
4936 case Intrinsic::loongarch_csrxchg_w: {
4937 unsigned Imm =
N->getConstantOperandVal(4);
4952#define IOCSRRD_CASE(NAME, NODE) \
4953 case Intrinsic::loongarch_##NAME: { \
4954 SDValue IOCSRRDResults = \
4955 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4956 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
4957 Results.push_back( \
4958 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
4959 Results.push_back(IOCSRRDResults.getValue(1)); \
4966 case Intrinsic::loongarch_cpucfg: {
4975 case Intrinsic::loongarch_lddir_d: {
4976 if (!Subtarget.is64Bit()) {
4986 if (Subtarget.is64Bit())
4988 "On LA64, only 64-bit registers can be read.");
4991 "On LA32, only 32-bit registers can be read.");
4993 Results.push_back(
N->getOperand(0));
5004 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5012 case ISD::ATOMIC_CMP_SWAP: {
5017 MVT VT =
N->getSimpleValueType(0);
5023 EVT InVT = In.getValueType();
5034 for (
unsigned I = 0;
I < MinElts; ++
I)
5035 TruncMask[
I] = Scale *
I;
5037 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5038 MVT SVT = In.getSimpleValueType().getScalarType();
5044 "Illegal vector type in truncation");
5063 SDValue FirstOperand =
N->getOperand(0);
5064 SDValue SecondOperand =
N->getOperand(1);
5065 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5066 EVT ValTy =
N->getValueType(0);
5069 unsigned SMIdx, SMLen;
5075 if (!Subtarget.has32S())
5097 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
5112 if (SMIdx + SMLen > ValTy.getSizeInBits())
5131 NewOperand = FirstOperand;
5134 msb = lsb + SMLen - 1;
5138 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5151 if (!Subtarget.has32S())
5163 SDValue FirstOperand =
N->getOperand(0);
5165 EVT ValTy =
N->getValueType(0);
5168 unsigned MaskIdx, MaskLen;
5183 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5199 switch (Src.getOpcode()) {
5202 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5212 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5225 switch (Src.getOpcode()) {
5235 Src.getOpcode(),
DL, SExtVT,
5241 DL, SExtVT, Src.getOperand(0),
5253 EVT VT =
N->getValueType(0);
5255 EVT SrcVT = Src.getValueType();
5257 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5262 EVT CmpVT = Src.getOperand(0).getValueType();
5267 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5295 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5302 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5326 EVT VT =
N->getValueType(0);
5328 EVT SrcVT = Src.getValueType();
5345 bool UseLASX =
false;
5346 bool PropagateSExt =
false;
5348 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
5349 EVT CmpVT = Src.getOperand(0).getValueType();
5358 SExtVT = MVT::v2i64;
5361 SExtVT = MVT::v4i32;
5363 SExtVT = MVT::v4i64;
5365 PropagateSExt =
true;
5369 SExtVT = MVT::v8i16;
5371 SExtVT = MVT::v8i32;
5373 PropagateSExt =
true;
5377 SExtVT = MVT::v16i8;
5379 SExtVT = MVT::v16i16;
5381 PropagateSExt =
true;
5385 SExtVT = MVT::v32i8;
5393 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5394 if (Src.getSimpleValueType() == MVT::v32i8) {
5402 }
else if (UseLASX) {
5421 EVT ValTy =
N->getValueType(0);
5422 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5425 unsigned ValBits = ValTy.getSizeInBits();
5426 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5428 bool SwapAndRetried =
false;
5431 if (!Subtarget.has32S())
5437 if (ValBits != 32 && ValBits != 64)
5452 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5455 (MaskIdx0 + MaskLen0 <= ValBits)) {
5476 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5477 (MaskIdx0 + MaskLen0 <= ValBits)) {
5494 (MaskIdx0 + MaskLen0 <= 64) &&
5502 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5503 : (MaskIdx0 + MaskLen0 - 1),
5519 (MaskIdx0 + MaskLen0 <= ValBits)) {
5542 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5543 : (MaskIdx0 + MaskLen0 - 1),
5558 unsigned MaskIdx, MaskLen;
5559 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5586 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5600 if (!SwapAndRetried) {
5602 SwapAndRetried =
true;
5606 SwapAndRetried =
false;
5632 if (!SwapAndRetried) {
5634 SwapAndRetried =
true;
5644 switch (V.getNode()->getOpcode()) {
5656 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5664 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5741 SDNode *AndNode =
N->getOperand(0).getNode();
5749 SDValue CmpInputValue =
N->getOperand(1);
5760 AndInputValue1 = AndInputValue1.
getOperand(0);
5764 if (AndInputValue2 != CmpInputValue)
5797 TruncInputValue1, TruncInputValue2);
5799 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5840 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
5868 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
5902 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
5918 EVT VT =
N->getValueType(0);
5921 if (TrueV == FalseV)
5953 {LHS, RHS, CC, TrueV, FalseV});
5958template <
unsigned N>
5962 bool IsSigned =
false) {
5966 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5967 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5969 ": argument out of range.");
5975template <
unsigned N>
5979 EVT ResTy =
Node->getValueType(0);
5983 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5984 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5986 ": argument out of range.");
5991 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
5997 EVT ResTy =
Node->getValueType(0);
6005 EVT ResTy =
Node->getValueType(0);
6014template <
unsigned N>
6017 EVT ResTy =
Node->getValueType(0);
6022 ": argument out of range.");
6032template <
unsigned N>
6035 EVT ResTy =
Node->getValueType(0);
6040 ": argument out of range.");
6049template <
unsigned N>
6052 EVT ResTy =
Node->getValueType(0);
6057 ": argument out of range.");
6066template <
unsigned W>
6069 unsigned Imm =
N->getConstantOperandVal(2);
6071 const StringRef ErrorMsg =
"argument out of range";
6073 return DAG.
getUNDEF(
N->getValueType(0));
6079 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6087 switch (
N->getConstantOperandVal(0)) {
6090 case Intrinsic::loongarch_lsx_vadd_b:
6091 case Intrinsic::loongarch_lsx_vadd_h:
6092 case Intrinsic::loongarch_lsx_vadd_w:
6093 case Intrinsic::loongarch_lsx_vadd_d:
6094 case Intrinsic::loongarch_lasx_xvadd_b:
6095 case Intrinsic::loongarch_lasx_xvadd_h:
6096 case Intrinsic::loongarch_lasx_xvadd_w:
6097 case Intrinsic::loongarch_lasx_xvadd_d:
6100 case Intrinsic::loongarch_lsx_vaddi_bu:
6101 case Intrinsic::loongarch_lsx_vaddi_hu:
6102 case Intrinsic::loongarch_lsx_vaddi_wu:
6103 case Intrinsic::loongarch_lsx_vaddi_du:
6104 case Intrinsic::loongarch_lasx_xvaddi_bu:
6105 case Intrinsic::loongarch_lasx_xvaddi_hu:
6106 case Intrinsic::loongarch_lasx_xvaddi_wu:
6107 case Intrinsic::loongarch_lasx_xvaddi_du:
6110 case Intrinsic::loongarch_lsx_vsub_b:
6111 case Intrinsic::loongarch_lsx_vsub_h:
6112 case Intrinsic::loongarch_lsx_vsub_w:
6113 case Intrinsic::loongarch_lsx_vsub_d:
6114 case Intrinsic::loongarch_lasx_xvsub_b:
6115 case Intrinsic::loongarch_lasx_xvsub_h:
6116 case Intrinsic::loongarch_lasx_xvsub_w:
6117 case Intrinsic::loongarch_lasx_xvsub_d:
6120 case Intrinsic::loongarch_lsx_vsubi_bu:
6121 case Intrinsic::loongarch_lsx_vsubi_hu:
6122 case Intrinsic::loongarch_lsx_vsubi_wu:
6123 case Intrinsic::loongarch_lsx_vsubi_du:
6124 case Intrinsic::loongarch_lasx_xvsubi_bu:
6125 case Intrinsic::loongarch_lasx_xvsubi_hu:
6126 case Intrinsic::loongarch_lasx_xvsubi_wu:
6127 case Intrinsic::loongarch_lasx_xvsubi_du:
6130 case Intrinsic::loongarch_lsx_vneg_b:
6131 case Intrinsic::loongarch_lsx_vneg_h:
6132 case Intrinsic::loongarch_lsx_vneg_w:
6133 case Intrinsic::loongarch_lsx_vneg_d:
6134 case Intrinsic::loongarch_lasx_xvneg_b:
6135 case Intrinsic::loongarch_lasx_xvneg_h:
6136 case Intrinsic::loongarch_lasx_xvneg_w:
6137 case Intrinsic::loongarch_lasx_xvneg_d:
6141 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6143 SDLoc(
N),
N->getValueType(0)),
6145 case Intrinsic::loongarch_lsx_vmax_b:
6146 case Intrinsic::loongarch_lsx_vmax_h:
6147 case Intrinsic::loongarch_lsx_vmax_w:
6148 case Intrinsic::loongarch_lsx_vmax_d:
6149 case Intrinsic::loongarch_lasx_xvmax_b:
6150 case Intrinsic::loongarch_lasx_xvmax_h:
6151 case Intrinsic::loongarch_lasx_xvmax_w:
6152 case Intrinsic::loongarch_lasx_xvmax_d:
6155 case Intrinsic::loongarch_lsx_vmax_bu:
6156 case Intrinsic::loongarch_lsx_vmax_hu:
6157 case Intrinsic::loongarch_lsx_vmax_wu:
6158 case Intrinsic::loongarch_lsx_vmax_du:
6159 case Intrinsic::loongarch_lasx_xvmax_bu:
6160 case Intrinsic::loongarch_lasx_xvmax_hu:
6161 case Intrinsic::loongarch_lasx_xvmax_wu:
6162 case Intrinsic::loongarch_lasx_xvmax_du:
6165 case Intrinsic::loongarch_lsx_vmaxi_b:
6166 case Intrinsic::loongarch_lsx_vmaxi_h:
6167 case Intrinsic::loongarch_lsx_vmaxi_w:
6168 case Intrinsic::loongarch_lsx_vmaxi_d:
6169 case Intrinsic::loongarch_lasx_xvmaxi_b:
6170 case Intrinsic::loongarch_lasx_xvmaxi_h:
6171 case Intrinsic::loongarch_lasx_xvmaxi_w:
6172 case Intrinsic::loongarch_lasx_xvmaxi_d:
6175 case Intrinsic::loongarch_lsx_vmaxi_bu:
6176 case Intrinsic::loongarch_lsx_vmaxi_hu:
6177 case Intrinsic::loongarch_lsx_vmaxi_wu:
6178 case Intrinsic::loongarch_lsx_vmaxi_du:
6179 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6180 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6181 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6182 case Intrinsic::loongarch_lasx_xvmaxi_du:
6185 case Intrinsic::loongarch_lsx_vmin_b:
6186 case Intrinsic::loongarch_lsx_vmin_h:
6187 case Intrinsic::loongarch_lsx_vmin_w:
6188 case Intrinsic::loongarch_lsx_vmin_d:
6189 case Intrinsic::loongarch_lasx_xvmin_b:
6190 case Intrinsic::loongarch_lasx_xvmin_h:
6191 case Intrinsic::loongarch_lasx_xvmin_w:
6192 case Intrinsic::loongarch_lasx_xvmin_d:
6195 case Intrinsic::loongarch_lsx_vmin_bu:
6196 case Intrinsic::loongarch_lsx_vmin_hu:
6197 case Intrinsic::loongarch_lsx_vmin_wu:
6198 case Intrinsic::loongarch_lsx_vmin_du:
6199 case Intrinsic::loongarch_lasx_xvmin_bu:
6200 case Intrinsic::loongarch_lasx_xvmin_hu:
6201 case Intrinsic::loongarch_lasx_xvmin_wu:
6202 case Intrinsic::loongarch_lasx_xvmin_du:
6205 case Intrinsic::loongarch_lsx_vmini_b:
6206 case Intrinsic::loongarch_lsx_vmini_h:
6207 case Intrinsic::loongarch_lsx_vmini_w:
6208 case Intrinsic::loongarch_lsx_vmini_d:
6209 case Intrinsic::loongarch_lasx_xvmini_b:
6210 case Intrinsic::loongarch_lasx_xvmini_h:
6211 case Intrinsic::loongarch_lasx_xvmini_w:
6212 case Intrinsic::loongarch_lasx_xvmini_d:
6215 case Intrinsic::loongarch_lsx_vmini_bu:
6216 case Intrinsic::loongarch_lsx_vmini_hu:
6217 case Intrinsic::loongarch_lsx_vmini_wu:
6218 case Intrinsic::loongarch_lsx_vmini_du:
6219 case Intrinsic::loongarch_lasx_xvmini_bu:
6220 case Intrinsic::loongarch_lasx_xvmini_hu:
6221 case Intrinsic::loongarch_lasx_xvmini_wu:
6222 case Intrinsic::loongarch_lasx_xvmini_du:
6225 case Intrinsic::loongarch_lsx_vmul_b:
6226 case Intrinsic::loongarch_lsx_vmul_h:
6227 case Intrinsic::loongarch_lsx_vmul_w:
6228 case Intrinsic::loongarch_lsx_vmul_d:
6229 case Intrinsic::loongarch_lasx_xvmul_b:
6230 case Intrinsic::loongarch_lasx_xvmul_h:
6231 case Intrinsic::loongarch_lasx_xvmul_w:
6232 case Intrinsic::loongarch_lasx_xvmul_d:
6235 case Intrinsic::loongarch_lsx_vmadd_b:
6236 case Intrinsic::loongarch_lsx_vmadd_h:
6237 case Intrinsic::loongarch_lsx_vmadd_w:
6238 case Intrinsic::loongarch_lsx_vmadd_d:
6239 case Intrinsic::loongarch_lasx_xvmadd_b:
6240 case Intrinsic::loongarch_lasx_xvmadd_h:
6241 case Intrinsic::loongarch_lasx_xvmadd_w:
6242 case Intrinsic::loongarch_lasx_xvmadd_d: {
6243 EVT ResTy =
N->getValueType(0);
6248 case Intrinsic::loongarch_lsx_vmsub_b:
6249 case Intrinsic::loongarch_lsx_vmsub_h:
6250 case Intrinsic::loongarch_lsx_vmsub_w:
6251 case Intrinsic::loongarch_lsx_vmsub_d:
6252 case Intrinsic::loongarch_lasx_xvmsub_b:
6253 case Intrinsic::loongarch_lasx_xvmsub_h:
6254 case Intrinsic::loongarch_lasx_xvmsub_w:
6255 case Intrinsic::loongarch_lasx_xvmsub_d: {
6256 EVT ResTy =
N->getValueType(0);
6261 case Intrinsic::loongarch_lsx_vdiv_b:
6262 case Intrinsic::loongarch_lsx_vdiv_h:
6263 case Intrinsic::loongarch_lsx_vdiv_w:
6264 case Intrinsic::loongarch_lsx_vdiv_d:
6265 case Intrinsic::loongarch_lasx_xvdiv_b:
6266 case Intrinsic::loongarch_lasx_xvdiv_h:
6267 case Intrinsic::loongarch_lasx_xvdiv_w:
6268 case Intrinsic::loongarch_lasx_xvdiv_d:
6271 case Intrinsic::loongarch_lsx_vdiv_bu:
6272 case Intrinsic::loongarch_lsx_vdiv_hu:
6273 case Intrinsic::loongarch_lsx_vdiv_wu:
6274 case Intrinsic::loongarch_lsx_vdiv_du:
6275 case Intrinsic::loongarch_lasx_xvdiv_bu:
6276 case Intrinsic::loongarch_lasx_xvdiv_hu:
6277 case Intrinsic::loongarch_lasx_xvdiv_wu:
6278 case Intrinsic::loongarch_lasx_xvdiv_du:
6281 case Intrinsic::loongarch_lsx_vmod_b:
6282 case Intrinsic::loongarch_lsx_vmod_h:
6283 case Intrinsic::loongarch_lsx_vmod_w:
6284 case Intrinsic::loongarch_lsx_vmod_d:
6285 case Intrinsic::loongarch_lasx_xvmod_b:
6286 case Intrinsic::loongarch_lasx_xvmod_h:
6287 case Intrinsic::loongarch_lasx_xvmod_w:
6288 case Intrinsic::loongarch_lasx_xvmod_d:
6291 case Intrinsic::loongarch_lsx_vmod_bu:
6292 case Intrinsic::loongarch_lsx_vmod_hu:
6293 case Intrinsic::loongarch_lsx_vmod_wu:
6294 case Intrinsic::loongarch_lsx_vmod_du:
6295 case Intrinsic::loongarch_lasx_xvmod_bu:
6296 case Intrinsic::loongarch_lasx_xvmod_hu:
6297 case Intrinsic::loongarch_lasx_xvmod_wu:
6298 case Intrinsic::loongarch_lasx_xvmod_du:
6301 case Intrinsic::loongarch_lsx_vand_v:
6302 case Intrinsic::loongarch_lasx_xvand_v:
6305 case Intrinsic::loongarch_lsx_vor_v:
6306 case Intrinsic::loongarch_lasx_xvor_v:
6309 case Intrinsic::loongarch_lsx_vxor_v:
6310 case Intrinsic::loongarch_lasx_xvxor_v:
6313 case Intrinsic::loongarch_lsx_vnor_v:
6314 case Intrinsic::loongarch_lasx_xvnor_v: {
6319 case Intrinsic::loongarch_lsx_vandi_b:
6320 case Intrinsic::loongarch_lasx_xvandi_b:
6323 case Intrinsic::loongarch_lsx_vori_b:
6324 case Intrinsic::loongarch_lasx_xvori_b:
6327 case Intrinsic::loongarch_lsx_vxori_b:
6328 case Intrinsic::loongarch_lasx_xvxori_b:
6331 case Intrinsic::loongarch_lsx_vsll_b:
6332 case Intrinsic::loongarch_lsx_vsll_h:
6333 case Intrinsic::loongarch_lsx_vsll_w:
6334 case Intrinsic::loongarch_lsx_vsll_d:
6335 case Intrinsic::loongarch_lasx_xvsll_b:
6336 case Intrinsic::loongarch_lasx_xvsll_h:
6337 case Intrinsic::loongarch_lasx_xvsll_w:
6338 case Intrinsic::loongarch_lasx_xvsll_d:
6341 case Intrinsic::loongarch_lsx_vslli_b:
6342 case Intrinsic::loongarch_lasx_xvslli_b:
6345 case Intrinsic::loongarch_lsx_vslli_h:
6346 case Intrinsic::loongarch_lasx_xvslli_h:
6349 case Intrinsic::loongarch_lsx_vslli_w:
6350 case Intrinsic::loongarch_lasx_xvslli_w:
6353 case Intrinsic::loongarch_lsx_vslli_d:
6354 case Intrinsic::loongarch_lasx_xvslli_d:
6357 case Intrinsic::loongarch_lsx_vsrl_b:
6358 case Intrinsic::loongarch_lsx_vsrl_h:
6359 case Intrinsic::loongarch_lsx_vsrl_w:
6360 case Intrinsic::loongarch_lsx_vsrl_d:
6361 case Intrinsic::loongarch_lasx_xvsrl_b:
6362 case Intrinsic::loongarch_lasx_xvsrl_h:
6363 case Intrinsic::loongarch_lasx_xvsrl_w:
6364 case Intrinsic::loongarch_lasx_xvsrl_d:
6367 case Intrinsic::loongarch_lsx_vsrli_b:
6368 case Intrinsic::loongarch_lasx_xvsrli_b:
6371 case Intrinsic::loongarch_lsx_vsrli_h:
6372 case Intrinsic::loongarch_lasx_xvsrli_h:
6375 case Intrinsic::loongarch_lsx_vsrli_w:
6376 case Intrinsic::loongarch_lasx_xvsrli_w:
6379 case Intrinsic::loongarch_lsx_vsrli_d:
6380 case Intrinsic::loongarch_lasx_xvsrli_d:
6383 case Intrinsic::loongarch_lsx_vsra_b:
6384 case Intrinsic::loongarch_lsx_vsra_h:
6385 case Intrinsic::loongarch_lsx_vsra_w:
6386 case Intrinsic::loongarch_lsx_vsra_d:
6387 case Intrinsic::loongarch_lasx_xvsra_b:
6388 case Intrinsic::loongarch_lasx_xvsra_h:
6389 case Intrinsic::loongarch_lasx_xvsra_w:
6390 case Intrinsic::loongarch_lasx_xvsra_d:
6393 case Intrinsic::loongarch_lsx_vsrai_b:
6394 case Intrinsic::loongarch_lasx_xvsrai_b:
6397 case Intrinsic::loongarch_lsx_vsrai_h:
6398 case Intrinsic::loongarch_lasx_xvsrai_h:
6401 case Intrinsic::loongarch_lsx_vsrai_w:
6402 case Intrinsic::loongarch_lasx_xvsrai_w:
6405 case Intrinsic::loongarch_lsx_vsrai_d:
6406 case Intrinsic::loongarch_lasx_xvsrai_d:
6409 case Intrinsic::loongarch_lsx_vclz_b:
6410 case Intrinsic::loongarch_lsx_vclz_h:
6411 case Intrinsic::loongarch_lsx_vclz_w:
6412 case Intrinsic::loongarch_lsx_vclz_d:
6413 case Intrinsic::loongarch_lasx_xvclz_b:
6414 case Intrinsic::loongarch_lasx_xvclz_h:
6415 case Intrinsic::loongarch_lasx_xvclz_w:
6416 case Intrinsic::loongarch_lasx_xvclz_d:
6418 case Intrinsic::loongarch_lsx_vpcnt_b:
6419 case Intrinsic::loongarch_lsx_vpcnt_h:
6420 case Intrinsic::loongarch_lsx_vpcnt_w:
6421 case Intrinsic::loongarch_lsx_vpcnt_d:
6422 case Intrinsic::loongarch_lasx_xvpcnt_b:
6423 case Intrinsic::loongarch_lasx_xvpcnt_h:
6424 case Intrinsic::loongarch_lasx_xvpcnt_w:
6425 case Intrinsic::loongarch_lasx_xvpcnt_d:
6427 case Intrinsic::loongarch_lsx_vbitclr_b:
6428 case Intrinsic::loongarch_lsx_vbitclr_h:
6429 case Intrinsic::loongarch_lsx_vbitclr_w:
6430 case Intrinsic::loongarch_lsx_vbitclr_d:
6431 case Intrinsic::loongarch_lasx_xvbitclr_b:
6432 case Intrinsic::loongarch_lasx_xvbitclr_h:
6433 case Intrinsic::loongarch_lasx_xvbitclr_w:
6434 case Intrinsic::loongarch_lasx_xvbitclr_d:
6436 case Intrinsic::loongarch_lsx_vbitclri_b:
6437 case Intrinsic::loongarch_lasx_xvbitclri_b:
6439 case Intrinsic::loongarch_lsx_vbitclri_h:
6440 case Intrinsic::loongarch_lasx_xvbitclri_h:
6442 case Intrinsic::loongarch_lsx_vbitclri_w:
6443 case Intrinsic::loongarch_lasx_xvbitclri_w:
6445 case Intrinsic::loongarch_lsx_vbitclri_d:
6446 case Intrinsic::loongarch_lasx_xvbitclri_d:
6448 case Intrinsic::loongarch_lsx_vbitset_b:
6449 case Intrinsic::loongarch_lsx_vbitset_h:
6450 case Intrinsic::loongarch_lsx_vbitset_w:
6451 case Intrinsic::loongarch_lsx_vbitset_d:
6452 case Intrinsic::loongarch_lasx_xvbitset_b:
6453 case Intrinsic::loongarch_lasx_xvbitset_h:
6454 case Intrinsic::loongarch_lasx_xvbitset_w:
6455 case Intrinsic::loongarch_lasx_xvbitset_d: {
6456 EVT VecTy =
N->getValueType(0);
6462 case Intrinsic::loongarch_lsx_vbitseti_b:
6463 case Intrinsic::loongarch_lasx_xvbitseti_b:
6465 case Intrinsic::loongarch_lsx_vbitseti_h:
6466 case Intrinsic::loongarch_lasx_xvbitseti_h:
6468 case Intrinsic::loongarch_lsx_vbitseti_w:
6469 case Intrinsic::loongarch_lasx_xvbitseti_w:
6471 case Intrinsic::loongarch_lsx_vbitseti_d:
6472 case Intrinsic::loongarch_lasx_xvbitseti_d:
6474 case Intrinsic::loongarch_lsx_vbitrev_b:
6475 case Intrinsic::loongarch_lsx_vbitrev_h:
6476 case Intrinsic::loongarch_lsx_vbitrev_w:
6477 case Intrinsic::loongarch_lsx_vbitrev_d:
6478 case Intrinsic::loongarch_lasx_xvbitrev_b:
6479 case Intrinsic::loongarch_lasx_xvbitrev_h:
6480 case Intrinsic::loongarch_lasx_xvbitrev_w:
6481 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6482 EVT VecTy =
N->getValueType(0);
6488 case Intrinsic::loongarch_lsx_vbitrevi_b:
6489 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6491 case Intrinsic::loongarch_lsx_vbitrevi_h:
6492 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6494 case Intrinsic::loongarch_lsx_vbitrevi_w:
6495 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6497 case Intrinsic::loongarch_lsx_vbitrevi_d:
6498 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6500 case Intrinsic::loongarch_lsx_vfadd_s:
6501 case Intrinsic::loongarch_lsx_vfadd_d:
6502 case Intrinsic::loongarch_lasx_xvfadd_s:
6503 case Intrinsic::loongarch_lasx_xvfadd_d:
6506 case Intrinsic::loongarch_lsx_vfsub_s:
6507 case Intrinsic::loongarch_lsx_vfsub_d:
6508 case Intrinsic::loongarch_lasx_xvfsub_s:
6509 case Intrinsic::loongarch_lasx_xvfsub_d:
6512 case Intrinsic::loongarch_lsx_vfmul_s:
6513 case Intrinsic::loongarch_lsx_vfmul_d:
6514 case Intrinsic::loongarch_lasx_xvfmul_s:
6515 case Intrinsic::loongarch_lasx_xvfmul_d:
6518 case Intrinsic::loongarch_lsx_vfdiv_s:
6519 case Intrinsic::loongarch_lsx_vfdiv_d:
6520 case Intrinsic::loongarch_lasx_xvfdiv_s:
6521 case Intrinsic::loongarch_lasx_xvfdiv_d:
6524 case Intrinsic::loongarch_lsx_vfmadd_s:
6525 case Intrinsic::loongarch_lsx_vfmadd_d:
6526 case Intrinsic::loongarch_lasx_xvfmadd_s:
6527 case Intrinsic::loongarch_lasx_xvfmadd_d:
6529 N->getOperand(2),
N->getOperand(3));
6530 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6532 N->getOperand(1),
N->getOperand(2),
6534 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6535 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6537 N->getOperand(1),
N->getOperand(2),
6539 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6540 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6542 N->getOperand(1),
N->getOperand(2),
6544 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6546 N->getOperand(1),
N->getOperand(2),
6548 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6549 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6550 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6551 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6552 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6553 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6554 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6555 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6559 case Intrinsic::loongarch_lsx_vreplve_b:
6560 case Intrinsic::loongarch_lsx_vreplve_h:
6561 case Intrinsic::loongarch_lsx_vreplve_w:
6562 case Intrinsic::loongarch_lsx_vreplve_d:
6563 case Intrinsic::loongarch_lasx_xvreplve_b:
6564 case Intrinsic::loongarch_lasx_xvreplve_h:
6565 case Intrinsic::loongarch_lasx_xvreplve_w:
6566 case Intrinsic::loongarch_lasx_xvreplve_d:
6571 case Intrinsic::loongarch_lsx_vpickve2gr_b:
6575 case Intrinsic::loongarch_lsx_vpickve2gr_h:
6576 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
6580 case Intrinsic::loongarch_lsx_vpickve2gr_w:
6584 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
6588 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
6589 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
6593 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
6597 case Intrinsic::loongarch_lsx_bz_b:
6598 case Intrinsic::loongarch_lsx_bz_h:
6599 case Intrinsic::loongarch_lsx_bz_w:
6600 case Intrinsic::loongarch_lsx_bz_d:
6601 case Intrinsic::loongarch_lasx_xbz_b:
6602 case Intrinsic::loongarch_lasx_xbz_h:
6603 case Intrinsic::loongarch_lasx_xbz_w:
6604 case Intrinsic::loongarch_lasx_xbz_d:
6609 case Intrinsic::loongarch_lsx_bz_v:
6610 case Intrinsic::loongarch_lasx_xbz_v:
6615 case Intrinsic::loongarch_lsx_bnz_b:
6616 case Intrinsic::loongarch_lsx_bnz_h:
6617 case Intrinsic::loongarch_lsx_bnz_w:
6618 case Intrinsic::loongarch_lsx_bnz_d:
6619 case Intrinsic::loongarch_lasx_xbnz_b:
6620 case Intrinsic::loongarch_lasx_xbnz_h:
6621 case Intrinsic::loongarch_lasx_xbnz_w:
6622 case Intrinsic::loongarch_lasx_xbnz_d:
6627 case Intrinsic::loongarch_lsx_bnz_v:
6628 case Intrinsic::loongarch_lasx_xbnz_v:
6633 case Intrinsic::loongarch_lasx_concat_128_s:
6634 case Intrinsic::loongarch_lasx_concat_128_d:
6635 case Intrinsic::loongarch_lasx_concat_128:
6637 N->getOperand(1),
N->getOperand(2));
6663 "Unexpected value type!");
6672 MVT VT =
N->getSimpleValueType(0);
6706 APInt V =
C->getValueAPF().bitcastToAPInt();
6722 MVT EltVT =
N->getSimpleValueType(0);
6754 switch (
N->getOpcode()) {
6808 MF->
insert(It, BreakMBB);
6812 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
6813 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
6825 MBB->addSuccessor(BreakMBB);
6826 MBB->addSuccessor(SinkMBB);
6832 BreakMBB->addSuccessor(SinkMBB);
6844 switch (
MI.getOpcode()) {
6847 case LoongArch::PseudoVBZ:
6848 CondOpc = LoongArch::VSETEQZ_V;
6850 case LoongArch::PseudoVBZ_B:
6851 CondOpc = LoongArch::VSETANYEQZ_B;
6853 case LoongArch::PseudoVBZ_H:
6854 CondOpc = LoongArch::VSETANYEQZ_H;
6856 case LoongArch::PseudoVBZ_W:
6857 CondOpc = LoongArch::VSETANYEQZ_W;
6859 case LoongArch::PseudoVBZ_D:
6860 CondOpc = LoongArch::VSETANYEQZ_D;
6862 case LoongArch::PseudoVBNZ:
6863 CondOpc = LoongArch::VSETNEZ_V;
6865 case LoongArch::PseudoVBNZ_B:
6866 CondOpc = LoongArch::VSETALLNEZ_B;
6868 case LoongArch::PseudoVBNZ_H:
6869 CondOpc = LoongArch::VSETALLNEZ_H;
6871 case LoongArch::PseudoVBNZ_W:
6872 CondOpc = LoongArch::VSETALLNEZ_W;
6874 case LoongArch::PseudoVBNZ_D:
6875 CondOpc = LoongArch::VSETALLNEZ_D;
6877 case LoongArch::PseudoXVBZ:
6878 CondOpc = LoongArch::XVSETEQZ_V;
6880 case LoongArch::PseudoXVBZ_B:
6881 CondOpc = LoongArch::XVSETANYEQZ_B;
6883 case LoongArch::PseudoXVBZ_H:
6884 CondOpc = LoongArch::XVSETANYEQZ_H;
6886 case LoongArch::PseudoXVBZ_W:
6887 CondOpc = LoongArch::XVSETANYEQZ_W;
6889 case LoongArch::PseudoXVBZ_D:
6890 CondOpc = LoongArch::XVSETANYEQZ_D;
6892 case LoongArch::PseudoXVBNZ:
6893 CondOpc = LoongArch::XVSETNEZ_V;
6895 case LoongArch::PseudoXVBNZ_B:
6896 CondOpc = LoongArch::XVSETALLNEZ_B;
6898 case LoongArch::PseudoXVBNZ_H:
6899 CondOpc = LoongArch::XVSETALLNEZ_H;
6901 case LoongArch::PseudoXVBNZ_W:
6902 CondOpc = LoongArch::XVSETALLNEZ_W;
6904 case LoongArch::PseudoXVBNZ_D:
6905 CondOpc = LoongArch::XVSETALLNEZ_D;
6920 F->insert(It, FalseBB);
6921 F->insert(It, TrueBB);
6922 F->insert(It, SinkBB);
6925 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
6929 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
6938 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6946 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6954 MI.getOperand(0).getReg())
6961 MI.eraseFromParent();
6969 unsigned BroadcastOp;
6971 switch (
MI.getOpcode()) {
6974 case LoongArch::PseudoXVINSGR2VR_B:
6976 BroadcastOp = LoongArch::XVREPLGR2VR_B;
6977 InsOp = LoongArch::XVEXTRINS_B;
6979 case LoongArch::PseudoXVINSGR2VR_H:
6981 BroadcastOp = LoongArch::XVREPLGR2VR_H;
6982 InsOp = LoongArch::XVEXTRINS_H;
6994 unsigned Idx =
MI.getOperand(3).getImm();
6996 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
6998 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
6999 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
7002 .
addReg(XSrc, 0, LoongArch::sub_128);
7004 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
7005 : LoongArch::VINSGR2VR_B),
7014 .
addImm(LoongArch::sub_128);
7016 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7017 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7021 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
7024 .
addImm(Idx >= HalfSize ? 48 : 18);
7029 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
7032 MI.eraseFromParent();
7039 assert(Subtarget.hasExtLSX());
7046 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
7047 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
7048 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
7052 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
7053 : LoongArch::VINSGR2VR_W),
7060 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
7064 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
7065 : LoongArch::VPICKVE2GR_W),
7070 MI.eraseFromParent();
7084 unsigned EleBits = 8;
7085 unsigned NotOpc = 0;
7088 switch (
MI.getOpcode()) {
7091 case LoongArch::PseudoVMSKLTZ_B:
7092 MskOpc = LoongArch::VMSKLTZ_B;
7094 case LoongArch::PseudoVMSKLTZ_H:
7095 MskOpc = LoongArch::VMSKLTZ_H;
7098 case LoongArch::PseudoVMSKLTZ_W:
7099 MskOpc = LoongArch::VMSKLTZ_W;
7102 case LoongArch::PseudoVMSKLTZ_D:
7103 MskOpc = LoongArch::VMSKLTZ_D;
7106 case LoongArch::PseudoVMSKGEZ_B:
7107 MskOpc = LoongArch::VMSKGEZ_B;
7109 case LoongArch::PseudoVMSKEQZ_B:
7110 MskOpc = LoongArch::VMSKNZ_B;
7111 NotOpc = LoongArch::VNOR_V;
7113 case LoongArch::PseudoVMSKNEZ_B:
7114 MskOpc = LoongArch::VMSKNZ_B;
7116 case LoongArch::PseudoXVMSKLTZ_B:
7117 MskOpc = LoongArch::XVMSKLTZ_B;
7118 RC = &LoongArch::LASX256RegClass;
7120 case LoongArch::PseudoXVMSKLTZ_H:
7121 MskOpc = LoongArch::XVMSKLTZ_H;
7122 RC = &LoongArch::LASX256RegClass;
7125 case LoongArch::PseudoXVMSKLTZ_W:
7126 MskOpc = LoongArch::XVMSKLTZ_W;
7127 RC = &LoongArch::LASX256RegClass;
7130 case LoongArch::PseudoXVMSKLTZ_D:
7131 MskOpc = LoongArch::XVMSKLTZ_D;
7132 RC = &LoongArch::LASX256RegClass;
7135 case LoongArch::PseudoXVMSKGEZ_B:
7136 MskOpc = LoongArch::XVMSKGEZ_B;
7137 RC = &LoongArch::LASX256RegClass;
7139 case LoongArch::PseudoXVMSKEQZ_B:
7140 MskOpc = LoongArch::XVMSKNZ_B;
7141 NotOpc = LoongArch::XVNOR_V;
7142 RC = &LoongArch::LASX256RegClass;
7144 case LoongArch::PseudoXVMSKNEZ_B:
7145 MskOpc = LoongArch::XVMSKNZ_B;
7146 RC = &LoongArch::LASX256RegClass;
7161 if (
TRI->getRegSizeInBits(*RC) > 128) {
7162 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7163 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
7171 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
7172 : LoongArch::BSTRINS_W),
7176 .
addImm(256 / EleBits - 1)
7184 MI.eraseFromParent();
7191 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
7192 "Unexpected instruction");
7204 MI.eraseFromParent();
7211 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
7212 "Unexpected instruction");
7218 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
7228 MI.eraseFromParent();
7233 switch (
MI.getOpcode()) {
7236 case LoongArch::Select_GPR_Using_CC_GPR:
7272 if (
MI.getOperand(2).isReg())
7273 RHS =
MI.getOperand(2).getReg();
7274 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
7278 SelectDests.
insert(
MI.getOperand(0).getReg());
7282 SequenceMBBI !=
E; ++SequenceMBBI) {
7283 if (SequenceMBBI->isDebugInstr())
7286 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
7287 !SequenceMBBI->getOperand(2).isReg() ||
7288 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
7289 SequenceMBBI->getOperand(3).getImm() != CC ||
7290 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
7291 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
7293 LastSelectPseudo = &*SequenceMBBI;
7295 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
7298 if (SequenceMBBI->hasUnmodeledSideEffects() ||
7299 SequenceMBBI->mayLoadOrStore() ||
7300 SequenceMBBI->usesCustomInsertionHook())
7303 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
7318 F->insert(
I, IfFalseMBB);
7319 F->insert(
I, TailMBB);
7322 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
7328 TailMBB->
push_back(DebugInstr->removeFromParent());
7332 TailMBB->
splice(TailMBB->
end(), HeadMBB,
7342 if (
MI.getOperand(2).isImm())
7354 auto SelectMBBI =
MI.getIterator();
7355 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
7357 while (SelectMBBI != SelectEnd) {
7358 auto Next = std::next(SelectMBBI);
7362 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
7363 .
addReg(SelectMBBI->getOperand(4).getReg())
7365 .
addReg(SelectMBBI->getOperand(5).getReg())
7372 F->getProperties().resetNoPHIs();
7378 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
7381 switch (
MI.getOpcode()) {
7384 case LoongArch::DIV_W:
7385 case LoongArch::DIV_WU:
7386 case LoongArch::MOD_W:
7387 case LoongArch::MOD_WU:
7388 case LoongArch::DIV_D:
7389 case LoongArch::DIV_DU:
7390 case LoongArch::MOD_D:
7391 case LoongArch::MOD_DU:
7394 case LoongArch::WRFCSR: {
7396 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
7397 .
addReg(
MI.getOperand(1).getReg());
7398 MI.eraseFromParent();
7401 case LoongArch::RDFCSR: {
7402 MachineInstr *ReadFCSR =
7404 MI.getOperand(0).getReg())
7405 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
7407 MI.eraseFromParent();
7410 case LoongArch::Select_GPR_Using_CC_GPR:
7412 case LoongArch::BuildPairF64Pseudo:
7414 case LoongArch::SplitPairF64Pseudo:
7416 case LoongArch::PseudoVBZ:
7417 case LoongArch::PseudoVBZ_B:
7418 case LoongArch::PseudoVBZ_H:
7419 case LoongArch::PseudoVBZ_W:
7420 case LoongArch::PseudoVBZ_D:
7421 case LoongArch::PseudoVBNZ:
7422 case LoongArch::PseudoVBNZ_B:
7423 case LoongArch::PseudoVBNZ_H:
7424 case LoongArch::PseudoVBNZ_W:
7425 case LoongArch::PseudoVBNZ_D:
7426 case LoongArch::PseudoXVBZ:
7427 case LoongArch::PseudoXVBZ_B:
7428 case LoongArch::PseudoXVBZ_H:
7429 case LoongArch::PseudoXVBZ_W:
7430 case LoongArch::PseudoXVBZ_D:
7431 case LoongArch::PseudoXVBNZ:
7432 case LoongArch::PseudoXVBNZ_B:
7433 case LoongArch::PseudoXVBNZ_H:
7434 case LoongArch::PseudoXVBNZ_W:
7435 case LoongArch::PseudoXVBNZ_D:
7437 case LoongArch::PseudoXVINSGR2VR_B:
7438 case LoongArch::PseudoXVINSGR2VR_H:
7440 case LoongArch::PseudoCTPOP:
7442 case LoongArch::PseudoVMSKLTZ_B:
7443 case LoongArch::PseudoVMSKLTZ_H:
7444 case LoongArch::PseudoVMSKLTZ_W:
7445 case LoongArch::PseudoVMSKLTZ_D:
7446 case LoongArch::PseudoVMSKGEZ_B:
7447 case LoongArch::PseudoVMSKEQZ_B:
7448 case LoongArch::PseudoVMSKNEZ_B:
7449 case LoongArch::PseudoXVMSKLTZ_B:
7450 case LoongArch::PseudoXVMSKLTZ_H:
7451 case LoongArch::PseudoXVMSKLTZ_W:
7452 case LoongArch::PseudoXVMSKLTZ_D:
7453 case LoongArch::PseudoXVMSKGEZ_B:
7454 case LoongArch::PseudoXVMSKEQZ_B:
7455 case LoongArch::PseudoXVMSKNEZ_B:
7457 case TargetOpcode::STATEPOINT:
7463 MI.addOperand(*
MI.getMF(),
7465 LoongArch::R1,
true,
7468 if (!Subtarget.is64Bit())
7476 unsigned *
Fast)
const {
7477 if (!Subtarget.hasUAL())
7491#define NODE_NAME_CASE(node) \
7492 case LoongArchISD::node: \
7493 return "LoongArchISD::" #node;
7599#undef NODE_NAME_CASE
7612 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7613 LoongArch::R10, LoongArch::R11};
7617 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7618 LoongArch::F6, LoongArch::F7};
7621 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7622 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7625 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7626 LoongArch::VR6, LoongArch::VR7};
7629 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7630 LoongArch::XR6, LoongArch::XR7};
7636 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7638 unsigned GRLenInBytes = GRLen / 8;
7649 State.AllocateStack(GRLenInBytes, StackAlign),
7652 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7663 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7671 unsigned ValNo,
MVT ValVT,
7674 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7675 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7676 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7681 if (IsRet && ValNo > 1)
7685 bool UseGPRForFloat =
true;
7695 UseGPRForFloat = ArgFlags.
isVarArg();
7708 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7711 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7712 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
7714 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7720 State.getPendingArgFlags();
7723 "PendingLocs and PendingArgFlags out of sync");
7727 UseGPRForFloat =
true;
7729 if (UseGPRForFloat && ValVT == MVT::f32) {
7732 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7735 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7738 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7780 PendingLocs.
size() <= 2) {
7781 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7786 PendingLocs.
clear();
7787 PendingArgFlags.
clear();
7794 unsigned StoreSizeBytes = GRLen / 8;
7797 if (ValVT == MVT::f32 && !UseGPRForFloat) {
7799 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
7803 UseGPRForFloat =
false;
7804 StoreSizeBytes = 16;
7805 StackAlign =
Align(16);
7808 UseGPRForFloat =
false;
7809 StoreSizeBytes = 32;
7810 StackAlign =
Align(32);
7816 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
7820 if (!PendingLocs.
empty()) {
7822 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7823 for (
auto &It : PendingLocs) {
7825 It.convertToReg(
Reg);
7830 PendingLocs.clear();
7831 PendingArgFlags.
clear();
7834 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7835 "Expected an GRLenVT at this stage");
7852void LoongArchTargetLowering::analyzeInputArgs(
7855 LoongArchCCAssignFn Fn)
const {
7857 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7858 MVT ArgVT =
Ins[i].VT;
7859 Type *ArgTy =
nullptr;
7861 ArgTy = FType->getReturnType();
7862 else if (Ins[i].isOrigArg())
7863 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7867 CCInfo, IsRet, ArgTy)) {
7868 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7875void LoongArchTargetLowering::analyzeOutputArgs(
7878 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7879 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7880 MVT ArgVT = Outs[i].VT;
7881 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7885 CCInfo, IsRet, OrigTy)) {
7886 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7927 if (In.isOrigArg()) {
7932 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
7933 (
BitWidth < 32 && In.Flags.isZExt())) {
7983 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7996 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8016 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
8026 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8030 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8031 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8032 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8039 if (LocVT == MVT::f32) {
8042 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
8043 LoongArch::F26, LoongArch::F27};
8050 if (LocVT == MVT::f64) {
8053 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
8054 LoongArch::F30_64, LoongArch::F31_64};
8084 "GHC calling convention requires the F and D extensions");
8088 MVT GRLenVT = Subtarget.getGRLenVT();
8089 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
8091 std::vector<SDValue> OutChains;
8100 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
8102 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
8119 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
8120 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
8121 assert(ArgPartOffset == 0);
8122 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
8124 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
8148 int VaArgOffset, VarArgsSaveSize;
8152 if (ArgRegs.
size() == Idx) {
8154 VarArgsSaveSize = 0;
8156 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
8157 VaArgOffset = -VarArgsSaveSize;
8163 LoongArchFI->setVarArgsFrameIndex(FI);
8171 VarArgsSaveSize += GRLenInBytes;
8176 for (
unsigned I = Idx;
I < ArgRegs.
size();
8177 ++
I, VaArgOffset += GRLenInBytes) {
8178 const Register Reg = RegInfo.createVirtualRegister(RC);
8179 RegInfo.addLiveIn(ArgRegs[
I], Reg);
8187 ->setValue((
Value *)
nullptr);
8188 OutChains.push_back(Store);
8190 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
8195 if (!OutChains.empty()) {
8196 OutChains.push_back(Chain);
8211 if (
N->getNumValues() != 1)
8213 if (!
N->hasNUsesOfValue(1, 0))
8216 SDNode *Copy = *
N->user_begin();
8222 if (Copy->getGluedNode())
8226 bool HasRet =
false;
8236 Chain = Copy->getOperand(0);
8241bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
8245 auto CalleeCC = CLI.CallConv;
8246 auto &Outs = CLI.Outs;
8248 auto CallerCC = Caller.getCallingConv();
8255 for (
auto &VA : ArgLocs)
8261 auto IsCallerStructRet = Caller.hasStructRetAttr();
8262 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
8263 if (IsCallerStructRet || IsCalleeStructRet)
8267 for (
auto &Arg : Outs)
8268 if (Arg.Flags.isByVal())
8273 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
8274 if (CalleeCC != CallerCC) {
8275 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
8276 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
8302 MVT GRLenVT = Subtarget.getGRLenVT();
8314 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
8318 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
8324 "site marked musttail");
8331 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8333 if (!Flags.isByVal())
8337 unsigned Size = Flags.getByValSize();
8338 Align Alignment = Flags.getNonZeroByValAlign();
8345 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
8347 false,
nullptr, std::nullopt,
8359 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
8362 SDValue ArgValue = OutVals[OutIdx];
8371 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
8383 if (!StackPtr.getNode())
8395 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
8410 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
8411 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
8412 assert(ArgPartOffset == 0);
8417 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
8418 SDValue PartValue = OutVals[OutIdx + 1];
8419 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
8434 for (
const auto &Part : Parts) {
8435 SDValue PartValue = Part.first;
8436 SDValue PartOffset = Part.second;
8443 ArgValue = SpillSlot;
8449 if (Flags.isByVal())
8450 ArgValue = ByValArgs[j++];
8457 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
8458 "for passing parameters");
8461 if (!StackPtr.getNode())
8474 if (!MemOpChains.
empty())
8480 for (
auto &Reg : RegsToPass) {
8481 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8503 Ops.push_back(Chain);
8504 Ops.push_back(Callee);
8508 for (
auto &Reg : RegsToPass)
8509 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8514 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8515 assert(Mask &&
"Missing call preserved mask for calling convention");
8521 Ops.push_back(Glue);
8533 assert(Subtarget.is64Bit() &&
"Medium code model requires LA64");
8537 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8560 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8563 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8564 auto &VA = RVLocs[i];
8572 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8573 assert(VA.needsCustom());
8579 RetValue, RetValue2);
8592 const Type *RetTy)
const {
8594 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8596 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8600 Outs[i].Flags, CCInfo,
true,
nullptr))
8626 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8627 SDValue Val = OutVals[OutIdx];
8636 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8640 Register RegHi = RVLocs[++i].getLocReg();
8673 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
8676 if (SplatBitSize == 16 && !(V & 0x00FF)) {
8678 RequiredImm = (0b10101 << 8) | (V >> 8);
8679 return {
true, RequiredImm};
8680 }
else if (SplatBitSize == 32) {
8682 if (!(V & 0xFFFF00FF)) {
8683 RequiredImm = (0b10001 << 8) | (V >> 8);
8684 return {
true, RequiredImm};
8687 if (!(V & 0xFF00FFFF)) {
8688 RequiredImm = (0b10010 << 8) | (V >> 16);
8689 return {
true, RequiredImm};
8692 if (!(V & 0x00FFFFFF)) {
8693 RequiredImm = (0b10011 << 8) | (V >> 24);
8694 return {
true, RequiredImm};
8697 if ((V & 0xFFFF00FF) == 0xFF) {
8698 RequiredImm = (0b10110 << 8) | (V >> 8);
8699 return {
true, RequiredImm};
8702 if ((V & 0xFF00FFFF) == 0xFFFF) {
8703 RequiredImm = (0b10111 << 8) | (V >> 16);
8704 return {
true, RequiredImm};
8707 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
8709 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8710 return {
true, RequiredImm};
8712 }
else if (SplatBitSize == 64) {
8714 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
8715 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
8717 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
8718 return {
true, RequiredImm};
8721 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
8722 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
8724 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
8725 return {
true, RequiredImm};
8728 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
8730 for (
int i = 0; i < 8; ++i) {
8732 if (
byte == 0 ||
byte == 0xFF)
8733 res |= ((
byte & 1) << i);
8740 auto [IsSame, Suffix] = sameBitsPreByte(V);
8742 RequiredImm = (0b11001 << 8) | Suffix;
8743 return {
true, RequiredImm};
8746 return {
false, RequiredImm};
8751 if (!Subtarget.hasExtLSX())
8754 if (VT == MVT::f32) {
8755 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8756 return (masked == 0x3e000000 || masked == 0x40000000);
8759 if (VT == MVT::f64) {
8760 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8761 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8767bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8768 bool ForCodeSize)
const {
8770 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8772 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8774 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8785bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8795 Type *Ty =
I->getOperand(0)->getType();
8797 unsigned Size = Ty->getIntegerBitWidth();
8813 EVT VT =
Y.getValueType();
8816 return Subtarget.hasExtLSX() && VT.
isInteger();
8828 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8829 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8830 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8831 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8833 Info.memVT = MVT::i32;
8834 Info.ptrVal =
I.getArgOperand(0);
8836 Info.align =
Align(4);
8853 "Unable to expand");
8854 unsigned MinWordSize = 4;
8866 Value *AlignedAddr = Builder.CreateIntrinsic(
8867 Intrinsic::ptrmask, {PtrTy, IntTy},
8868 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8871 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
8872 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8873 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
8874 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8875 Value *Mask = Builder.CreateShl(
8876 ConstantInt::get(WordType,
8879 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
8880 Value *ValOperand_Shifted =
8881 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
8882 ShiftAmt,
"ValOperand_Shifted");
8885 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8887 NewOperand = ValOperand_Shifted;
8890 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
8893 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
8894 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
8913 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
8921 if (Subtarget.hasLAMCAS()) {
8943 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
8945 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
8947 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
8949 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
8951 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
8953 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
8955 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
8957 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
8967 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
8969 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
8971 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
8973 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
8975 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
8977 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
8979 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
8981 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
8993 if (Subtarget.hasLAMCAS())
9005 unsigned GRLen = Subtarget.getGRLen();
9007 Value *FailureOrdering =
9008 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9009 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9011 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9012 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9013 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9014 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9017 Value *Result = Builder.CreateIntrinsic(
9018 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
9020 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9036 Builder.CreateNot(Mask,
"Inv_Mask"),
9043 unsigned GRLen = Subtarget.getGRLen();
9052 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
9053 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9054 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
9070 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
9071 Result = Builder.CreateCall(LlwOpScwLoop,
9072 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
9075 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
9079 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
9102 const Constant *PersonalityFn)
const {
9103 return LoongArch::R4;
9107 const Constant *PersonalityFn)
const {
9108 return LoongArch::R5;
9119 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
9120 return RefinementSteps;
9125 int &RefinementSteps,
9126 bool &UseOneConstNR,
9127 bool Reciprocal)
const {
9128 if (Subtarget.hasFrecipe()) {
9132 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9133 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9134 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9135 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9136 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9155 int &RefinementSteps)
const {
9156 if (Subtarget.hasFrecipe()) {
9160 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
9161 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
9162 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
9163 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
9164 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
9181LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
9201 if (Constraint.
size() == 1) {
9202 switch (Constraint[0]) {
9218 if (Constraint ==
"ZC" || Constraint ==
"ZB")
9227 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
9234std::pair<unsigned, const TargetRegisterClass *>
9235LoongArchTargetLowering::getRegForInlineAsmConstraint(
9239 if (Constraint.
size() == 1) {
9240 switch (Constraint[0]) {
9245 return std::make_pair(0U, &LoongArch::GPRRegClass);
9247 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
9249 if (Subtarget.hasBasicF() && VT == MVT::f32)
9250 return std::make_pair(0U, &LoongArch::FPR32RegClass);
9251 if (Subtarget.hasBasicD() && VT == MVT::f64)
9252 return std::make_pair(0U, &LoongArch::FPR64RegClass);
9253 if (Subtarget.hasExtLSX() &&
9254 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
9255 return std::make_pair(0U, &LoongArch::LSX128RegClass);
9256 if (Subtarget.hasExtLASX() &&
9257 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
9258 return std::make_pair(0U, &LoongArch::LASX256RegClass);
9278 bool IsFP = Constraint[2] ==
'f';
9279 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
9280 std::pair<unsigned, const TargetRegisterClass *>
R;
9285 unsigned RegNo =
R.first;
9286 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
9287 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
9288 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
9289 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
9299void LoongArchTargetLowering::LowerAsmOperandForConstraint(
9303 if (Constraint.
size() == 1) {
9304 switch (Constraint[0]) {
9308 uint64_t CVal =
C->getSExtValue();
9311 Subtarget.getGRLenVT()));
9317 uint64_t CVal =
C->getSExtValue();
9320 Subtarget.getGRLenVT()));
9326 if (
C->getZExtValue() == 0)
9333 uint64_t CVal =
C->getZExtValue();
9346#define GET_REGISTER_MATCHER
9347#include "LoongArchGenAsmMatcher.inc"
9353 std::string NewRegName = Name.second.str();
9359 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
9360 if (!ReservedRegs.
test(Reg))
9377 const APInt &Imm = ConstNode->getAPIntValue();
9379 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
9380 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
9383 if (ConstNode->hasOneUse() &&
9384 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
9385 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
9391 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
9392 unsigned Shifts = Imm.countr_zero();
9398 APInt ImmPop = Imm.ashr(Shifts);
9399 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
9403 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
9404 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
9405 (ImmSmall - Imm).isPowerOf2())
9415 Type *Ty,
unsigned AS,
9470 EVT MemVT = LD->getMemoryVT();
9471 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
9482 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
9491 if (
Y.getValueType().isVector())
9503 Type *Ty,
bool IsSigned)
const {
9504 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
9513 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
9514 Type.getSizeInBits() < Subtarget.getGRLen()))
9524 Align &PrefAlign)
const {
9528 if (Subtarget.is64Bit()) {
9530 PrefAlign =
Align(8);
9533 PrefAlign =
Align(4);
9548bool LoongArchTargetLowering::splitValueIntoRegisterParts(
9550 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
9551 bool IsABIRegCopy = CC.has_value();
9554 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9555 PartVT == MVT::f32) {
9558 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
9562 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f32, Val);
9570SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
9572 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
9573 bool IsABIRegCopy = CC.has_value();
9575 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9576 PartVT == MVT::f32) {
9580 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
9582 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
9593 if (VT == MVT::f16 && Subtarget.hasBasicF())
9599unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
9602 if (VT == MVT::f16 && Subtarget.hasBasicF())
9611 unsigned Depth)
const {
9612 EVT VT =
Op.getValueType();
9614 unsigned Opc =
Op.getOpcode();
9621 MVT SrcVT = Src.getSimpleValueType();
9626 if (OriginalDemandedBits.
countr_zero() >= NumElts)
9630 APInt KnownUndef, KnownZero;
9646 if (KnownSrc.
One[SrcBits - 1])
9648 else if (KnownSrc.
Zero[SrcBits - 1])
9653 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
9660 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
9683 unsigned Index)
const {
9692 unsigned Index)
const {
9696 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
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)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
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_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static 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 lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
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 SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
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_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue 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 bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static 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 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,...
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
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.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
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.
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
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.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
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...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
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 isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
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 shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
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.
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
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
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
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.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ 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)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
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
bool isInteger() const
Return true if this is an integer or a vector integer type.
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)