30#include "llvm/IR/IntrinsicsLoongArch.h"
40#define DEBUG_TYPE "loongarch-isel-lowering"
45 cl::desc(
"Trap on integer division by zero."),
52 MVT GRLenVT = Subtarget.getGRLenVT();
57 if (Subtarget.hasBasicF())
59 if (Subtarget.hasBasicD())
63 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
65 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
67 if (Subtarget.hasExtLSX())
71 if (Subtarget.hasExtLASX())
72 for (
MVT VT : LASXVTs)
140 if (Subtarget.is64Bit()) {
168 if (!Subtarget.is64Bit()) {
174 if (Subtarget.hasBasicD())
186 if (Subtarget.hasBasicF()) {
217 if (Subtarget.is64Bit())
220 if (!Subtarget.hasBasicD()) {
222 if (Subtarget.is64Bit()) {
231 if (Subtarget.hasBasicD()) {
263 if (Subtarget.is64Bit())
269 if (Subtarget.hasExtLSX()) {
284 for (
MVT VT : LSXVTs) {
298 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
315 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
317 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
319 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
323 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
341 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
342 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
357 if (Subtarget.hasExtLASX()) {
358 for (
MVT VT : LASXVTs) {
373 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
391 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
393 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
395 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
399 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
421 if (Subtarget.hasExtLSX()) {
428 if (Subtarget.hasExtLASX())
451 if (Subtarget.hasLAMCAS())
454 if (Subtarget.hasSCQ()) {
471 switch (
Op.getOpcode()) {
472 case ISD::ATOMIC_FENCE:
473 return lowerATOMIC_FENCE(
Op, DAG);
475 return lowerEH_DWARF_CFA(
Op, DAG);
477 return lowerGlobalAddress(
Op, DAG);
479 return lowerGlobalTLSAddress(
Op, DAG);
481 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
483 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
485 return lowerINTRINSIC_VOID(
Op, DAG);
487 return lowerBlockAddress(
Op, DAG);
489 return lowerJumpTable(
Op, DAG);
491 return lowerShiftLeftParts(
Op, DAG);
493 return lowerShiftRightParts(
Op, DAG,
true);
495 return lowerShiftRightParts(
Op, DAG,
false);
497 return lowerConstantPool(
Op, DAG);
499 return lowerFP_TO_SINT(
Op, DAG);
501 return lowerBITCAST(
Op, DAG);
503 return lowerUINT_TO_FP(
Op, DAG);
505 return lowerSINT_TO_FP(
Op, DAG);
507 return lowerVASTART(
Op, DAG);
509 return lowerFRAMEADDR(
Op, DAG);
511 return lowerRETURNADDR(
Op, DAG);
513 return lowerWRITE_REGISTER(
Op, DAG);
515 return lowerINSERT_VECTOR_ELT(
Op, DAG);
517 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
519 return lowerBUILD_VECTOR(
Op, DAG);
521 return lowerCONCAT_VECTORS(
Op, DAG);
523 return lowerVECTOR_SHUFFLE(
Op, DAG);
525 return lowerBITREVERSE(
Op, DAG);
527 return lowerSCALAR_TO_VECTOR(
Op, DAG);
529 return lowerPREFETCH(
Op, DAG);
531 return lowerSELECT(
Op, DAG);
533 return lowerBRCOND(
Op, DAG);
534 case ISD::FP_TO_FP16:
535 return lowerFP_TO_FP16(
Op, DAG);
536 case ISD::FP16_TO_FP:
537 return lowerFP16_TO_FP(
Op, DAG);
538 case ISD::FP_TO_BF16:
539 return lowerFP_TO_BF16(
Op, DAG);
540 case ISD::BF16_TO_FP:
541 return lowerBF16_TO_FP(
Op, DAG);
542 case ISD::VECREDUCE_ADD:
543 return lowerVECREDUCE_ADD(
Op, DAG);
544 case ISD::VECREDUCE_AND:
545 case ISD::VECREDUCE_OR:
546 case ISD::VECREDUCE_XOR:
547 case ISD::VECREDUCE_SMAX:
548 case ISD::VECREDUCE_SMIN:
549 case ISD::VECREDUCE_UMAX:
550 case ISD::VECREDUCE_UMIN:
551 return lowerVECREDUCE(
Op, DAG);
568 MVT OpVT =
Op.getSimpleValueType();
574 unsigned LegalVecSize = 128;
575 bool isLASX256Vector =
585 if (isLASX256Vector) {
590 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
596 if (isLASX256Vector) {
621 MVT OpVT =
Op.getSimpleValueType();
635 for (
int i = NumEles; i > 1; i /= 2) {
638 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
647 unsigned IsData =
Op.getConstantOperandVal(4);
652 return Op.getOperand(0);
667 if (
LHS == LHS2 &&
RHS == RHS2) {
672 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
688 MVT VT =
N->getSimpleValueType(0);
719 if (~TrueVal == FalseVal) {
759 unsigned SelOpNo = 0;
769 unsigned ConstSelOpNo = 1;
770 unsigned OtherSelOpNo = 2;
777 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
782 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
788 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
790 std::swap(NewConstOps[0], NewConstOps[1]);
802 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
804 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
807 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
808 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
828 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
842 int64_t
C = RHSC->getSExtValue();
885 MVT VT =
Op.getSimpleValueType();
886 MVT GRLenVT = Subtarget.getGRLenVT();
891 if (
Op.hasOneUse()) {
892 unsigned UseOpc =
Op->user_begin()->getOpcode();
894 SDNode *BinOp = *
Op->user_begin();
901 return lowerSELECT(NewSel, DAG);
941 if (TrueVal - 1 == FalseVal)
943 if (TrueVal + 1 == FalseVal)
950 RHS == TrueV &&
LHS == FalseV) {
982 MVT GRLenVT = Subtarget.getGRLenVT();
994 Op.getOperand(0),
LHS,
RHS, TargetCC,
998 Op.getOperand(0), CondV,
Op.getOperand(2));
1008LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1011 MVT OpVT =
Op.getSimpleValueType();
1022 EVT ResTy =
Op->getValueType(0);
1033 for (
unsigned int i = 0; i < NewEltNum; i++) {
1036 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1055 for (
unsigned int i = 0; i < NewEltNum; i++)
1056 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1057 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1075 if (EltBits > 32 || EltBits == 1)
1103 int MaskOffset,
const APInt &Zeroable) {
1104 int Size = Mask.size();
1105 unsigned SizeInBits =
Size * ScalarSizeInBits;
1107 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1108 for (
int i = 0; i <
Size; i += Scale)
1109 for (
int j = 0; j < Shift; ++j)
1110 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1118 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1119 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1124 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1125 for (
int i = 0; i !=
Size; i += Scale) {
1126 unsigned Pos =
Left ? i + Shift : i;
1127 unsigned Low =
Left ? i : i + Shift;
1128 unsigned Len = Scale - Shift;
1133 int ShiftEltBits = ScalarSizeInBits * Scale;
1134 bool ByteShift = ShiftEltBits > 64;
1137 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1141 Scale = ByteShift ? Scale / 2 : Scale;
1147 return (
int)ShiftAmt;
1150 unsigned MaxWidth = 128;
1151 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1152 for (
int Shift = 1; Shift != Scale; ++Shift)
1153 for (
bool Left : {
true,
false})
1154 if (CheckZeros(Shift, Scale,
Left)) {
1155 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1180 const APInt &Zeroable) {
1181 int Size = Mask.size();
1195 Mask,
Size, Zeroable);
1203 "Illegal integer vector type");
1212template <
typename ValType>
1215 unsigned CheckStride,
1217 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1221 if (*
I != -1 && *
I != ExpectedIndex)
1223 ExpectedIndex += ExpectedIndexStride;
1227 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1239 int Size = Mask.size();
1249 int ScalarSizeInBits = VectorSizeInBits /
Size;
1250 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1251 (void)ScalarSizeInBits;
1253 for (
int i = 0; i <
Size; ++i) {
1259 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1276 RepeatedMask.
assign(LaneSize, -1);
1277 int Size = Mask.size();
1278 for (
int i = 0; i <
Size; ++i) {
1279 assert(Mask[i] == -1 || Mask[i] >= 0);
1282 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1289 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1290 if (RepeatedMask[i % LaneSize] < 0)
1292 RepeatedMask[i % LaneSize] = LocalM;
1293 else if (RepeatedMask[i % LaneSize] != LocalM)
1310 int NumElts = RepeatedMask.
size();
1312 int Scale = 16 / NumElts;
1314 for (
int i = 0; i < NumElts; ++i) {
1315 int M = RepeatedMask[i];
1316 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1317 "Unexpected mask index.");
1322 int StartIdx = i - (M % NumElts);
1329 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1332 Rotation = CandidateRotation;
1333 else if (Rotation != CandidateRotation)
1337 SDValue MaskV = M < NumElts ? V1 : V2;
1348 else if (TargetV != MaskV)
1353 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1354 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1363 return Rotation * Scale;
1382 if (ByteRotation <= 0)
1389 int LoByteShift = 16 - ByteRotation;
1390 int HiByteShift = ByteRotation;
1413 const APInt &Zeroable) {
1427 for (
int i = 0; i < NumElements; i++) {
1431 if (i % Scale != 0) {
1442 SDValue V = M < NumElements ? V1 : V2;
1443 M = M % NumElements;
1446 Offset = M - (i / Scale);
1449 if (
Offset % (NumElements / Scale))
1451 }
else if (InputV != V)
1454 if (M != (
Offset + (i / Scale)))
1465 if (
Offset >= (NumElements / 2)) {
1467 Offset -= (NumElements / 2);
1474 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1478 }
while (Scale > 1);
1484 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1485 NumExtElements *= 2) {
1505 int SplatIndex = -1;
1506 for (
const auto &M : Mask) {
1513 if (SplatIndex == -1)
1516 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1518 APInt Imm(64, SplatIndex);
1549 unsigned SubVecSize = 4;
1550 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1553 int SubMask[4] = {-1, -1, -1, -1};
1554 for (
unsigned i = 0; i < SubVecSize; ++i) {
1555 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
1561 M -= 4 * (j / SubVecSize);
1562 if (M < 0 || M >= 4)
1568 if (SubMask[i] == -1)
1572 else if (M != -1 && M != SubMask[i])
1579 for (
int i = SubVecSize - 1; i >= 0; --i) {
1592 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1619 const auto &Begin = Mask.begin();
1620 const auto &End = Mask.end();
1621 SDValue OriV1 = V1, OriV2 = V2;
1659 const auto &Begin = Mask.begin();
1660 const auto &End = Mask.end();
1661 SDValue OriV1 = V1, OriV2 = V2;
1700 const auto &Begin = Mask.begin();
1701 const auto &End = Mask.end();
1702 unsigned HalfSize = Mask.size() / 2;
1703 SDValue OriV1 = V1, OriV2 = V2;
1743 const auto &Begin = Mask.begin();
1744 const auto &End = Mask.end();
1745 SDValue OriV1 = V1, OriV2 = V2;
1783 const auto &Begin = Mask.begin();
1784 const auto &Mid = Mask.begin() + Mask.size() / 2;
1785 const auto &End = Mask.end();
1786 SDValue OriV1 = V1, OriV2 = V2;
1825 const auto &Begin = Mask.begin();
1826 const auto &Mid = Mask.begin() + Mask.size() / 2;
1827 const auto &End = Mask.end();
1828 SDValue OriV1 = V1, OriV2 = V2;
1882 "Vector type is unsupported for lsx!");
1884 "Two operands have different types!");
1886 "Unexpected mask size for shuffle!");
1887 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
1889 APInt KnownUndef, KnownZero;
1891 APInt Zeroable = KnownUndef | KnownZero;
1954 int SplatIndex = -1;
1955 for (
const auto &M : Mask) {
1962 if (SplatIndex == -1)
1965 const auto &Begin = Mask.begin();
1966 const auto &End = Mask.end();
1967 unsigned HalfSize = Mask.size() / 2;
1969 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1973 APInt Imm(64, SplatIndex);
1988 if (Mask.size() <= 4)
1998 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2002 unsigned HalfSize = NumElts / 2;
2003 bool FrontLo =
true, FrontHi =
true;
2004 bool BackLo =
true, BackHi =
true;
2006 auto inRange = [](
int val,
int low,
int high) {
2007 return (val == -1) || (val >= low && val < high);
2010 for (
unsigned i = 0; i < HalfSize; ++i) {
2011 int Fronti = Mask[i];
2012 int Backi = Mask[i + HalfSize];
2014 FrontLo &=
inRange(Fronti, 0, HalfSize);
2015 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2016 BackLo &=
inRange(Backi, 0, HalfSize);
2017 BackHi &=
inRange(Backi, HalfSize, NumElts);
2023 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2027 for (
unsigned i = 0; i < NumElts; ++i)
2054 const auto &Begin = Mask.begin();
2055 const auto &End = Mask.end();
2056 unsigned HalfSize = Mask.size() / 2;
2057 unsigned LeftSize = HalfSize / 2;
2058 SDValue OriV1 = V1, OriV2 = V2;
2065 Mask.size() + HalfSize - LeftSize, 1) &&
2067 Mask.size() + HalfSize + LeftSize, 1))
2078 Mask.size() + HalfSize - LeftSize, 1) &&
2080 Mask.size() + HalfSize + LeftSize, 1))
2093 const auto &Begin = Mask.begin();
2094 const auto &End = Mask.end();
2095 unsigned HalfSize = Mask.size() / 2;
2096 SDValue OriV1 = V1, OriV2 = V2;
2103 Mask.size() + HalfSize, 1))
2114 Mask.size() + HalfSize, 1))
2127 const auto &Begin = Mask.begin();
2128 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2129 const auto &Mid = Mask.begin() + Mask.size() / 2;
2130 const auto &RightMid = Mask.end() - Mask.size() / 4;
2131 const auto &End = Mask.end();
2132 unsigned HalfSize = Mask.size() / 2;
2133 SDValue OriV1 = V1, OriV2 = V2;
2162 const auto &Begin = Mask.begin();
2163 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2164 const auto &Mid = Mask.begin() + Mask.size() / 2;
2165 const auto &RightMid = Mask.end() - Mask.size() / 4;
2166 const auto &End = Mask.end();
2167 unsigned HalfSize = Mask.size() / 2;
2168 SDValue OriV1 = V1, OriV2 = V2;
2198 int MaskSize = Mask.size();
2199 int HalfSize = Mask.size() / 2;
2200 const auto &Begin = Mask.begin();
2201 const auto &Mid = Mask.begin() + HalfSize;
2202 const auto &End = Mask.end();
2214 for (
auto it = Begin; it < Mid; it++) {
2217 else if ((*it >= 0 && *it < HalfSize) ||
2218 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2219 int M = *it < HalfSize ? *it : *it - HalfSize;
2224 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2226 for (
auto it = Mid; it < End; it++) {
2229 else if ((*it >= HalfSize && *it < MaskSize) ||
2230 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2231 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2236 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2266 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
2268 int MaskSize = Mask.size();
2269 int HalfSize = Mask.size() / 2;
2272 HalfMaskType preMask =
None, postMask =
None;
2274 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2275 return M < 0 || (M >= 0 && M < HalfSize) ||
2276 (M >= MaskSize && M < MaskSize + HalfSize);
2278 preMask = HighLaneTy;
2279 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
2280 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2281 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2283 preMask = LowLaneTy;
2285 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2286 return M < 0 || (M >= 0 && M < HalfSize) ||
2287 (M >= MaskSize && M < MaskSize + HalfSize);
2289 postMask = HighLaneTy;
2290 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
2291 return M < 0 || (M >= HalfSize && M < MaskSize) ||
2292 (M >= MaskSize + HalfSize && M < MaskSize * 2);
2294 postMask = LowLaneTy;
2302 if (preMask == HighLaneTy && postMask == LowLaneTy) {
2305 if (preMask == LowLaneTy && postMask == HighLaneTy) {
2318 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2319 *it = *it < 0 ? *it : *it - HalfSize;
2321 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2322 *it = *it < 0 ? *it : *it + HalfSize;
2324 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
2337 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
2338 *it = *it < 0 ? *it : *it - HalfSize;
2340 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
2353 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
2354 *it = *it < 0 ? *it : *it + HalfSize;
2377 int Size = Mask.size();
2378 int LaneSize =
Size / 2;
2380 bool LaneCrossing[2] = {
false,
false};
2381 for (
int i = 0; i <
Size; ++i)
2382 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
2383 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
2386 if (!LaneCrossing[0] && !LaneCrossing[1])
2390 InLaneMask.
assign(Mask.begin(), Mask.end());
2391 for (
int i = 0; i <
Size; ++i) {
2392 int &M = InLaneMask[i];
2395 if (((M %
Size) / LaneSize) != (i / LaneSize))
2396 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
2401 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
2416 "Vector type is unsupported for lasx!");
2418 "Two operands have different types!");
2420 "Unexpected mask size for shuffle!");
2421 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2422 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
2428 APInt KnownUndef, KnownZero;
2430 APInt Zeroable = KnownUndef | KnownZero;
2467 Subtarget, Zeroable)))
2483 ArrayRef<int> OrigMask = SVOp->
getMask();
2486 MVT VT =
Op.getSimpleValueType();
2490 bool V1IsUndef = V1.
isUndef();
2491 bool V2IsUndef = V2.
isUndef();
2492 if (V1IsUndef && V2IsUndef)
2505 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
2506 SmallVector<int, 8> NewMask(OrigMask);
2507 for (
int &M : NewMask)
2508 if (M >= NumElements)
2514 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
2515 (void)MaskUpperLimit;
2517 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
2518 "Out of bounds shuffle index");
2540 std::tie(Res, Chain) =
2541 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
2542 if (Subtarget.is64Bit())
2559 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
2560 CallOptions,
DL, Chain);
2566 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2572 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
2573 if (Subtarget.is64Bit())
2580 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
2581 MVT VT =
Op.getSimpleValueType();
2590 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
2607 "Unsupported vector type for broadcast.");
2610 bool IsIdeneity =
true;
2612 for (
int i = 0; i !=
NumOps; i++) {
2614 if (
Op.getOpcode() != ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
2626 auto ExtType = LN->getExtensionType();
2632 ? DAG.
getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other)
2634 SDValue Ops[] = {LN->getChain(), LN->getBasePtr(), LN->getOffset()};
2645 EVT ResTy =
Op->getValueType(0);
2648 APInt SplatValue, SplatUndef;
2649 unsigned SplatBitSize;
2652 bool UseSameConstant =
true;
2657 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
2658 (!Subtarget.hasExtLASX() || !Is256Vec))
2664 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
2666 SplatBitSize <= 64) {
2668 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2672 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
2677 if ((Is128Vec && ResTy == MVT::v4i32) ||
2678 (Is256Vec && ResTy == MVT::v8i32))
2684 switch (SplatBitSize) {
2688 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
2691 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
2694 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
2697 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
2705 if (ViaVecTy != ResTy)
2706 Result = DAG.
getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
2714 for (
unsigned i = 0; i < NumElts; ++i) {
2719 ConstantValue = Opi;
2720 else if (ConstantValue != Opi)
2721 UseSameConstant =
false;
2726 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
2728 for (
unsigned i = 0; i < NumElts; ++i) {
2748 for (
unsigned i = 1; i < NumElts; ++i) {
2764 MVT ResVT =
Op.getSimpleValueType();
2768 unsigned NumFreezeUndef = 0;
2769 unsigned NumZero = 0;
2770 unsigned NumNonZero = 0;
2771 unsigned NonZeros = 0;
2772 SmallSet<SDValue, 4> Undefs;
2773 for (
unsigned i = 0; i != NumOperands; ++i) {
2788 assert(i <
sizeof(NonZeros) * CHAR_BIT);
2795 if (NumNonZero > 2) {
2799 Ops.slice(0, NumOperands / 2));
2801 Ops.slice(NumOperands / 2));
2814 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
2816 for (
unsigned i = 0; i != NumOperands; ++i) {
2817 if ((NonZeros & (1 << i)) == 0)
2828LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
2830 MVT EltVT =
Op.getSimpleValueType();
2835 MVT GRLenVT = Subtarget.getGRLenVT();
2865 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
2885LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
2887 MVT VT =
Op.getSimpleValueType();
2909 for (
unsigned i = 0; i < NumElts; ++i)
2932 return DAG.
getNode(ISD::MEMBARRIER,
DL, MVT::Other,
Op.getOperand(0));
2940 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
2942 "On LA64, only 64-bit registers can be written.");
2943 return Op.getOperand(0);
2946 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
2948 "On LA32, only 32-bit registers can be written.");
2949 return Op.getOperand(0);
2959 "be a constant integer");
2965 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
2966 EVT VT =
Op.getValueType();
2969 unsigned Depth =
Op.getConstantOperandVal(0);
2970 int GRLenInBytes = Subtarget.getGRLen() / 8;
2973 int Offset = -(GRLenInBytes * 2);
2985 if (
Op.getConstantOperandVal(0) != 0) {
2987 "return address can only be determined for the current frame");
2993 MVT GRLenVT = Subtarget.getGRLenVT();
3005 auto Size = Subtarget.getGRLen() / 8;
3013 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3023 MachinePointerInfo(SV));
3028 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3029 !Subtarget.hasBasicD() &&
"unexpected target features");
3035 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3049 EVT RetVT =
Op.getValueType();
3055 std::tie(Result, Chain) =
3062 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3063 !Subtarget.hasBasicD() &&
"unexpected target features");
3074 EVT RetVT =
Op.getValueType();
3080 std::tie(Result, Chain) =
3089 EVT VT =
Op.getValueType();
3093 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3094 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3098 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3113 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
3115 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
3116 !Subtarget.hasBasicD()) {
3123 return DAG.
getNode(ISD::BITCAST,
DL,
Op.getValueType(), Trunc);
3140 N->getOffset(), Flags);
3148template <
class NodeTy>
3151 bool IsLocal)
const {
3162 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
3233 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3235 const GlobalValue *GV =
N->getGlobal();
3247 unsigned Opc,
bool UseGOT,
3251 MVT GRLenVT = Subtarget.getGRLenVT();
3265 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
3303 Args.emplace_back(Load, CallTy);
3306 TargetLowering::CallLoweringInfo CLI(DAG);
3321 const GlobalValue *GV =
N->getGlobal();
3335LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
3342 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
3345 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
3358 return getDynamicTLSAddr(
N, DAG,
3359 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
3360 : LoongArch::PseudoLA_TLS_GD,
3367 return getDynamicTLSAddr(
N, DAG,
3368 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
3369 : LoongArch::PseudoLA_TLS_LD,
3374 return getStaticTLSAddr(
N, DAG,
3375 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
3376 : LoongArch::PseudoLA_TLS_IE,
3383 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
3387 return getTLSDescAddr(
N, DAG,
3388 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
3389 : LoongArch::PseudoLA_TLS_DESC,
3393template <
unsigned N>
3398 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
3399 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
3401 ": argument out of range.");
3408LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
3410 switch (
Op.getConstantOperandVal(0)) {
3413 case Intrinsic::thread_pointer: {
3417 case Intrinsic::loongarch_lsx_vpickve2gr_d:
3418 case Intrinsic::loongarch_lsx_vpickve2gr_du:
3419 case Intrinsic::loongarch_lsx_vreplvei_d:
3420 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
3422 case Intrinsic::loongarch_lsx_vreplvei_w:
3423 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
3424 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
3425 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
3426 case Intrinsic::loongarch_lasx_xvpickve_d:
3427 case Intrinsic::loongarch_lasx_xvpickve_d_f:
3429 case Intrinsic::loongarch_lasx_xvinsve0_d:
3431 case Intrinsic::loongarch_lsx_vsat_b:
3432 case Intrinsic::loongarch_lsx_vsat_bu:
3433 case Intrinsic::loongarch_lsx_vrotri_b:
3434 case Intrinsic::loongarch_lsx_vsllwil_h_b:
3435 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
3436 case Intrinsic::loongarch_lsx_vsrlri_b:
3437 case Intrinsic::loongarch_lsx_vsrari_b:
3438 case Intrinsic::loongarch_lsx_vreplvei_h:
3439 case Intrinsic::loongarch_lasx_xvsat_b:
3440 case Intrinsic::loongarch_lasx_xvsat_bu:
3441 case Intrinsic::loongarch_lasx_xvrotri_b:
3442 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
3443 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
3444 case Intrinsic::loongarch_lasx_xvsrlri_b:
3445 case Intrinsic::loongarch_lasx_xvsrari_b:
3446 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
3447 case Intrinsic::loongarch_lasx_xvpickve_w:
3448 case Intrinsic::loongarch_lasx_xvpickve_w_f:
3450 case Intrinsic::loongarch_lasx_xvinsve0_w:
3452 case Intrinsic::loongarch_lsx_vsat_h:
3453 case Intrinsic::loongarch_lsx_vsat_hu:
3454 case Intrinsic::loongarch_lsx_vrotri_h:
3455 case Intrinsic::loongarch_lsx_vsllwil_w_h:
3456 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
3457 case Intrinsic::loongarch_lsx_vsrlri_h:
3458 case Intrinsic::loongarch_lsx_vsrari_h:
3459 case Intrinsic::loongarch_lsx_vreplvei_b:
3460 case Intrinsic::loongarch_lasx_xvsat_h:
3461 case Intrinsic::loongarch_lasx_xvsat_hu:
3462 case Intrinsic::loongarch_lasx_xvrotri_h:
3463 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
3464 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
3465 case Intrinsic::loongarch_lasx_xvsrlri_h:
3466 case Intrinsic::loongarch_lasx_xvsrari_h:
3467 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
3469 case Intrinsic::loongarch_lsx_vsrlni_b_h:
3470 case Intrinsic::loongarch_lsx_vsrani_b_h:
3471 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
3472 case Intrinsic::loongarch_lsx_vsrarni_b_h:
3473 case Intrinsic::loongarch_lsx_vssrlni_b_h:
3474 case Intrinsic::loongarch_lsx_vssrani_b_h:
3475 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
3476 case Intrinsic::loongarch_lsx_vssrani_bu_h:
3477 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
3478 case Intrinsic::loongarch_lsx_vssrarni_b_h:
3479 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
3480 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
3481 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
3482 case Intrinsic::loongarch_lasx_xvsrani_b_h:
3483 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
3484 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
3485 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
3486 case Intrinsic::loongarch_lasx_xvssrani_b_h:
3487 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
3488 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
3489 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
3490 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
3491 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
3492 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
3494 case Intrinsic::loongarch_lsx_vsat_w:
3495 case Intrinsic::loongarch_lsx_vsat_wu:
3496 case Intrinsic::loongarch_lsx_vrotri_w:
3497 case Intrinsic::loongarch_lsx_vsllwil_d_w:
3498 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
3499 case Intrinsic::loongarch_lsx_vsrlri_w:
3500 case Intrinsic::loongarch_lsx_vsrari_w:
3501 case Intrinsic::loongarch_lsx_vslei_bu:
3502 case Intrinsic::loongarch_lsx_vslei_hu:
3503 case Intrinsic::loongarch_lsx_vslei_wu:
3504 case Intrinsic::loongarch_lsx_vslei_du:
3505 case Intrinsic::loongarch_lsx_vslti_bu:
3506 case Intrinsic::loongarch_lsx_vslti_hu:
3507 case Intrinsic::loongarch_lsx_vslti_wu:
3508 case Intrinsic::loongarch_lsx_vslti_du:
3509 case Intrinsic::loongarch_lsx_vbsll_v:
3510 case Intrinsic::loongarch_lsx_vbsrl_v:
3511 case Intrinsic::loongarch_lasx_xvsat_w:
3512 case Intrinsic::loongarch_lasx_xvsat_wu:
3513 case Intrinsic::loongarch_lasx_xvrotri_w:
3514 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
3515 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
3516 case Intrinsic::loongarch_lasx_xvsrlri_w:
3517 case Intrinsic::loongarch_lasx_xvsrari_w:
3518 case Intrinsic::loongarch_lasx_xvslei_bu:
3519 case Intrinsic::loongarch_lasx_xvslei_hu:
3520 case Intrinsic::loongarch_lasx_xvslei_wu:
3521 case Intrinsic::loongarch_lasx_xvslei_du:
3522 case Intrinsic::loongarch_lasx_xvslti_bu:
3523 case Intrinsic::loongarch_lasx_xvslti_hu:
3524 case Intrinsic::loongarch_lasx_xvslti_wu:
3525 case Intrinsic::loongarch_lasx_xvslti_du:
3526 case Intrinsic::loongarch_lasx_xvbsll_v:
3527 case Intrinsic::loongarch_lasx_xvbsrl_v:
3529 case Intrinsic::loongarch_lsx_vseqi_b:
3530 case Intrinsic::loongarch_lsx_vseqi_h:
3531 case Intrinsic::loongarch_lsx_vseqi_w:
3532 case Intrinsic::loongarch_lsx_vseqi_d:
3533 case Intrinsic::loongarch_lsx_vslei_b:
3534 case Intrinsic::loongarch_lsx_vslei_h:
3535 case Intrinsic::loongarch_lsx_vslei_w:
3536 case Intrinsic::loongarch_lsx_vslei_d:
3537 case Intrinsic::loongarch_lsx_vslti_b:
3538 case Intrinsic::loongarch_lsx_vslti_h:
3539 case Intrinsic::loongarch_lsx_vslti_w:
3540 case Intrinsic::loongarch_lsx_vslti_d:
3541 case Intrinsic::loongarch_lasx_xvseqi_b:
3542 case Intrinsic::loongarch_lasx_xvseqi_h:
3543 case Intrinsic::loongarch_lasx_xvseqi_w:
3544 case Intrinsic::loongarch_lasx_xvseqi_d:
3545 case Intrinsic::loongarch_lasx_xvslei_b:
3546 case Intrinsic::loongarch_lasx_xvslei_h:
3547 case Intrinsic::loongarch_lasx_xvslei_w:
3548 case Intrinsic::loongarch_lasx_xvslei_d:
3549 case Intrinsic::loongarch_lasx_xvslti_b:
3550 case Intrinsic::loongarch_lasx_xvslti_h:
3551 case Intrinsic::loongarch_lasx_xvslti_w:
3552 case Intrinsic::loongarch_lasx_xvslti_d:
3554 case Intrinsic::loongarch_lsx_vsrlni_h_w:
3555 case Intrinsic::loongarch_lsx_vsrani_h_w:
3556 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
3557 case Intrinsic::loongarch_lsx_vsrarni_h_w:
3558 case Intrinsic::loongarch_lsx_vssrlni_h_w:
3559 case Intrinsic::loongarch_lsx_vssrani_h_w:
3560 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
3561 case Intrinsic::loongarch_lsx_vssrani_hu_w:
3562 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
3563 case Intrinsic::loongarch_lsx_vssrarni_h_w:
3564 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
3565 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
3566 case Intrinsic::loongarch_lsx_vfrstpi_b:
3567 case Intrinsic::loongarch_lsx_vfrstpi_h:
3568 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
3569 case Intrinsic::loongarch_lasx_xvsrani_h_w:
3570 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
3571 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
3572 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
3573 case Intrinsic::loongarch_lasx_xvssrani_h_w:
3574 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
3575 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
3576 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
3577 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
3578 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
3579 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
3580 case Intrinsic::loongarch_lasx_xvfrstpi_b:
3581 case Intrinsic::loongarch_lasx_xvfrstpi_h:
3583 case Intrinsic::loongarch_lsx_vsat_d:
3584 case Intrinsic::loongarch_lsx_vsat_du:
3585 case Intrinsic::loongarch_lsx_vrotri_d:
3586 case Intrinsic::loongarch_lsx_vsrlri_d:
3587 case Intrinsic::loongarch_lsx_vsrari_d:
3588 case Intrinsic::loongarch_lasx_xvsat_d:
3589 case Intrinsic::loongarch_lasx_xvsat_du:
3590 case Intrinsic::loongarch_lasx_xvrotri_d:
3591 case Intrinsic::loongarch_lasx_xvsrlri_d:
3592 case Intrinsic::loongarch_lasx_xvsrari_d:
3594 case Intrinsic::loongarch_lsx_vsrlni_w_d:
3595 case Intrinsic::loongarch_lsx_vsrani_w_d:
3596 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
3597 case Intrinsic::loongarch_lsx_vsrarni_w_d:
3598 case Intrinsic::loongarch_lsx_vssrlni_w_d:
3599 case Intrinsic::loongarch_lsx_vssrani_w_d:
3600 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
3601 case Intrinsic::loongarch_lsx_vssrani_wu_d:
3602 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
3603 case Intrinsic::loongarch_lsx_vssrarni_w_d:
3604 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
3605 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
3606 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
3607 case Intrinsic::loongarch_lasx_xvsrani_w_d:
3608 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
3609 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
3610 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
3611 case Intrinsic::loongarch_lasx_xvssrani_w_d:
3612 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
3613 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
3614 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
3615 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
3616 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
3617 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
3619 case Intrinsic::loongarch_lsx_vsrlni_d_q:
3620 case Intrinsic::loongarch_lsx_vsrani_d_q:
3621 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
3622 case Intrinsic::loongarch_lsx_vsrarni_d_q:
3623 case Intrinsic::loongarch_lsx_vssrlni_d_q:
3624 case Intrinsic::loongarch_lsx_vssrani_d_q:
3625 case Intrinsic::loongarch_lsx_vssrlni_du_q:
3626 case Intrinsic::loongarch_lsx_vssrani_du_q:
3627 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
3628 case Intrinsic::loongarch_lsx_vssrarni_d_q:
3629 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
3630 case Intrinsic::loongarch_lsx_vssrarni_du_q:
3631 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
3632 case Intrinsic::loongarch_lasx_xvsrani_d_q:
3633 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
3634 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
3635 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
3636 case Intrinsic::loongarch_lasx_xvssrani_d_q:
3637 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
3638 case Intrinsic::loongarch_lasx_xvssrani_du_q:
3639 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
3640 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
3641 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
3642 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
3644 case Intrinsic::loongarch_lsx_vnori_b:
3645 case Intrinsic::loongarch_lsx_vshuf4i_b:
3646 case Intrinsic::loongarch_lsx_vshuf4i_h:
3647 case Intrinsic::loongarch_lsx_vshuf4i_w:
3648 case Intrinsic::loongarch_lasx_xvnori_b:
3649 case Intrinsic::loongarch_lasx_xvshuf4i_b:
3650 case Intrinsic::loongarch_lasx_xvshuf4i_h:
3651 case Intrinsic::loongarch_lasx_xvshuf4i_w:
3652 case Intrinsic::loongarch_lasx_xvpermi_d:
3654 case Intrinsic::loongarch_lsx_vshuf4i_d:
3655 case Intrinsic::loongarch_lsx_vpermi_w:
3656 case Intrinsic::loongarch_lsx_vbitseli_b:
3657 case Intrinsic::loongarch_lsx_vextrins_b:
3658 case Intrinsic::loongarch_lsx_vextrins_h:
3659 case Intrinsic::loongarch_lsx_vextrins_w:
3660 case Intrinsic::loongarch_lsx_vextrins_d:
3661 case Intrinsic::loongarch_lasx_xvshuf4i_d:
3662 case Intrinsic::loongarch_lasx_xvpermi_w:
3663 case Intrinsic::loongarch_lasx_xvpermi_q:
3664 case Intrinsic::loongarch_lasx_xvbitseli_b:
3665 case Intrinsic::loongarch_lasx_xvextrins_b:
3666 case Intrinsic::loongarch_lasx_xvextrins_h:
3667 case Intrinsic::loongarch_lasx_xvextrins_w:
3668 case Intrinsic::loongarch_lasx_xvextrins_d:
3670 case Intrinsic::loongarch_lsx_vrepli_b:
3671 case Intrinsic::loongarch_lsx_vrepli_h:
3672 case Intrinsic::loongarch_lsx_vrepli_w:
3673 case Intrinsic::loongarch_lsx_vrepli_d:
3674 case Intrinsic::loongarch_lasx_xvrepli_b:
3675 case Intrinsic::loongarch_lasx_xvrepli_h:
3676 case Intrinsic::loongarch_lasx_xvrepli_w:
3677 case Intrinsic::loongarch_lasx_xvrepli_d:
3679 case Intrinsic::loongarch_lsx_vldi:
3680 case Intrinsic::loongarch_lasx_xvldi:
3696LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
3699 MVT GRLenVT = Subtarget.getGRLenVT();
3700 EVT VT =
Op.getValueType();
3702 const StringRef ErrorMsgOOR =
"argument out of range";
3703 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3704 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3706 switch (
Op.getConstantOperandVal(1)) {
3709 case Intrinsic::loongarch_crc_w_b_w:
3710 case Intrinsic::loongarch_crc_w_h_w:
3711 case Intrinsic::loongarch_crc_w_w_w:
3712 case Intrinsic::loongarch_crc_w_d_w:
3713 case Intrinsic::loongarch_crcc_w_b_w:
3714 case Intrinsic::loongarch_crcc_w_h_w:
3715 case Intrinsic::loongarch_crcc_w_w_w:
3716 case Intrinsic::loongarch_crcc_w_d_w:
3718 case Intrinsic::loongarch_csrrd_w:
3719 case Intrinsic::loongarch_csrrd_d: {
3720 unsigned Imm =
Op.getConstantOperandVal(2);
3726 case Intrinsic::loongarch_csrwr_w:
3727 case Intrinsic::loongarch_csrwr_d: {
3728 unsigned Imm =
Op.getConstantOperandVal(3);
3732 {Chain,
Op.getOperand(2),
3735 case Intrinsic::loongarch_csrxchg_w:
3736 case Intrinsic::loongarch_csrxchg_d: {
3737 unsigned Imm =
Op.getConstantOperandVal(4);
3741 {Chain,
Op.getOperand(2),
Op.getOperand(3),
3744 case Intrinsic::loongarch_iocsrrd_d: {
3749#define IOCSRRD_CASE(NAME, NODE) \
3750 case Intrinsic::loongarch_##NAME: { \
3751 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
3752 {Chain, Op.getOperand(2)}); \
3758 case Intrinsic::loongarch_cpucfg: {
3760 {Chain,
Op.getOperand(2)});
3762 case Intrinsic::loongarch_lddir_d: {
3763 unsigned Imm =
Op.getConstantOperandVal(3);
3768 case Intrinsic::loongarch_movfcsr2gr: {
3769 if (!Subtarget.hasBasicF())
3771 unsigned Imm =
Op.getConstantOperandVal(2);
3777 case Intrinsic::loongarch_lsx_vld:
3778 case Intrinsic::loongarch_lsx_vldrepl_b:
3779 case Intrinsic::loongarch_lasx_xvld:
3780 case Intrinsic::loongarch_lasx_xvldrepl_b:
3784 case Intrinsic::loongarch_lsx_vldrepl_h:
3785 case Intrinsic::loongarch_lasx_xvldrepl_h:
3789 Op,
"argument out of range or not a multiple of 2", DAG)
3791 case Intrinsic::loongarch_lsx_vldrepl_w:
3792 case Intrinsic::loongarch_lasx_xvldrepl_w:
3796 Op,
"argument out of range or not a multiple of 4", DAG)
3798 case Intrinsic::loongarch_lsx_vldrepl_d:
3799 case Intrinsic::loongarch_lasx_xvldrepl_d:
3803 Op,
"argument out of range or not a multiple of 8", DAG)
3814 return Op.getOperand(0);
3820 MVT GRLenVT = Subtarget.getGRLenVT();
3822 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
3824 const StringRef ErrorMsgOOR =
"argument out of range";
3825 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3826 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
3827 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3829 switch (IntrinsicEnum) {
3833 case Intrinsic::loongarch_cacop_d:
3834 case Intrinsic::loongarch_cacop_w: {
3835 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
3837 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
3846 case Intrinsic::loongarch_dbar: {
3853 case Intrinsic::loongarch_ibar: {
3860 case Intrinsic::loongarch_break: {
3867 case Intrinsic::loongarch_movgr2fcsr: {
3868 if (!Subtarget.hasBasicF())
3878 case Intrinsic::loongarch_syscall: {
3885#define IOCSRWR_CASE(NAME, NODE) \
3886 case Intrinsic::loongarch_##NAME: { \
3887 SDValue Op3 = Op.getOperand(3); \
3888 return Subtarget.is64Bit() \
3889 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
3890 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
3891 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
3892 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
3899 case Intrinsic::loongarch_iocsrwr_d: {
3900 return !Subtarget.is64Bit()
3907#define ASRT_LE_GT_CASE(NAME) \
3908 case Intrinsic::loongarch_##NAME: { \
3909 return !Subtarget.is64Bit() \
3910 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
3915#undef ASRT_LE_GT_CASE
3916 case Intrinsic::loongarch_ldpte_d: {
3917 unsigned Imm =
Op.getConstantOperandVal(3);
3918 return !Subtarget.is64Bit()
3923 case Intrinsic::loongarch_lsx_vst:
3924 case Intrinsic::loongarch_lasx_xvst:
3928 case Intrinsic::loongarch_lasx_xvstelm_b:
3933 case Intrinsic::loongarch_lsx_vstelm_b:
3938 case Intrinsic::loongarch_lasx_xvstelm_h:
3943 Op,
"argument out of range or not a multiple of 2", DAG)
3945 case Intrinsic::loongarch_lsx_vstelm_h:
3950 Op,
"argument out of range or not a multiple of 2", DAG)
3952 case Intrinsic::loongarch_lasx_xvstelm_w:
3957 Op,
"argument out of range or not a multiple of 4", DAG)
3959 case Intrinsic::loongarch_lsx_vstelm_w:
3964 Op,
"argument out of range or not a multiple of 4", DAG)
3966 case Intrinsic::loongarch_lasx_xvstelm_d:
3971 Op,
"argument out of range or not a multiple of 8", DAG)
3973 case Intrinsic::loongarch_lsx_vstelm_d:
3978 Op,
"argument out of range or not a multiple of 8", DAG)
3989 EVT VT =
Lo.getValueType();
4030 EVT VT =
Lo.getValueType();
4122 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4123 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
4127 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
4133 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
4160 StringRef ErrorMsg,
bool WithChain =
true) {
4165 Results.push_back(
N->getOperand(0));
4168template <
unsigned N>
4173 const StringRef ErrorMsgOOR =
"argument out of range";
4174 unsigned Imm =
Node->getConstantOperandVal(2);
4208 switch (
N->getConstantOperandVal(0)) {
4211 case Intrinsic::loongarch_lsx_vpickve2gr_b:
4215 case Intrinsic::loongarch_lsx_vpickve2gr_h:
4216 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
4220 case Intrinsic::loongarch_lsx_vpickve2gr_w:
4224 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
4228 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
4229 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
4233 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
4237 case Intrinsic::loongarch_lsx_bz_b:
4238 case Intrinsic::loongarch_lsx_bz_h:
4239 case Intrinsic::loongarch_lsx_bz_w:
4240 case Intrinsic::loongarch_lsx_bz_d:
4241 case Intrinsic::loongarch_lasx_xbz_b:
4242 case Intrinsic::loongarch_lasx_xbz_h:
4243 case Intrinsic::loongarch_lasx_xbz_w:
4244 case Intrinsic::loongarch_lasx_xbz_d:
4248 case Intrinsic::loongarch_lsx_bz_v:
4249 case Intrinsic::loongarch_lasx_xbz_v:
4253 case Intrinsic::loongarch_lsx_bnz_b:
4254 case Intrinsic::loongarch_lsx_bnz_h:
4255 case Intrinsic::loongarch_lsx_bnz_w:
4256 case Intrinsic::loongarch_lsx_bnz_d:
4257 case Intrinsic::loongarch_lasx_xbnz_b:
4258 case Intrinsic::loongarch_lasx_xbnz_h:
4259 case Intrinsic::loongarch_lasx_xbnz_w:
4260 case Intrinsic::loongarch_lasx_xbnz_d:
4264 case Intrinsic::loongarch_lsx_bnz_v:
4265 case Intrinsic::loongarch_lasx_xbnz_v:
4275 assert(
N->getValueType(0) == MVT::i128 &&
4276 "AtomicCmpSwap on types less than 128 should be legal");
4280 switch (
MemOp->getMergedOrdering()) {
4284 Opcode = LoongArch::PseudoCmpXchg128Acquire;
4288 Opcode = LoongArch::PseudoCmpXchg128;
4295 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
4296 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
4297 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
4298 NewVal.first, NewVal.second,
N->getOperand(0)};
4301 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
4312 EVT VT =
N->getValueType(0);
4313 switch (
N->getOpcode()) {
4318 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
4319 "Unexpected custom legalisation");
4326 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4327 "Unexpected custom legalisation");
4329 Subtarget.hasDiv32() && VT == MVT::i32
4336 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4337 "Unexpected custom legalisation");
4345 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4346 "Unexpected custom legalisation");
4350 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4351 "Unexpected custom legalisation");
4358 if (Src.getValueType() == MVT::f16)
4359 Src = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Src);
4369 EVT OpVT = Src.getValueType();
4373 std::tie(Result, Chain) =
4378 case ISD::BITCAST: {
4380 EVT SrcVT = Src.getValueType();
4381 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
4382 Subtarget.hasBasicF()) {
4386 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
4388 DAG.
getVTList(MVT::i32, MVT::i32), Src);
4396 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4397 "Unexpected custom legalisation");
4400 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
4406 assert((VT == MVT::i16 || VT == MVT::i32) &&
4407 "Unexpected custom legalization");
4408 MVT GRLenVT = Subtarget.getGRLenVT();
4428 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
4429 "Unexpected custom legalization");
4430 MVT GRLenVT = Subtarget.getGRLenVT();
4448 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
4449 "Unexpected custom legalisation");
4456 MVT GRLenVT = Subtarget.getGRLenVT();
4457 const StringRef ErrorMsgOOR =
"argument out of range";
4458 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4459 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4461 switch (
N->getConstantOperandVal(1)) {
4464 case Intrinsic::loongarch_movfcsr2gr: {
4465 if (!Subtarget.hasBasicF()) {
4482#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
4483 case Intrinsic::loongarch_##NAME: { \
4484 SDValue NODE = DAG.getNode( \
4485 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4486 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4487 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4488 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4489 Results.push_back(NODE.getValue(1)); \
4498#undef CRC_CASE_EXT_BINARYOP
4500#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
4501 case Intrinsic::loongarch_##NAME: { \
4502 SDValue NODE = DAG.getNode( \
4503 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4505 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
4506 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
4507 Results.push_back(NODE.getValue(1)); \
4512#undef CRC_CASE_EXT_UNARYOP
4513#define CSR_CASE(ID) \
4514 case Intrinsic::loongarch_##ID: { \
4515 if (!Subtarget.is64Bit()) \
4516 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
4524 case Intrinsic::loongarch_csrrd_w: {
4538 case Intrinsic::loongarch_csrwr_w: {
4539 unsigned Imm =
N->getConstantOperandVal(3);
4553 case Intrinsic::loongarch_csrxchg_w: {
4554 unsigned Imm =
N->getConstantOperandVal(4);
4569#define IOCSRRD_CASE(NAME, NODE) \
4570 case Intrinsic::loongarch_##NAME: { \
4571 SDValue IOCSRRDResults = \
4572 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
4573 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
4574 Results.push_back( \
4575 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
4576 Results.push_back(IOCSRRDResults.getValue(1)); \
4583 case Intrinsic::loongarch_cpucfg: {
4592 case Intrinsic::loongarch_lddir_d: {
4593 if (!Subtarget.is64Bit()) {
4603 if (Subtarget.is64Bit())
4605 "On LA64, only 64-bit registers can be read.");
4608 "On LA32, only 32-bit registers can be read.");
4610 Results.push_back(
N->getOperand(0));
4621 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
4629 case ISD::ATOMIC_CMP_SWAP: {
4634 MVT VT =
N->getSimpleValueType(0);
4640 EVT InVT = In.getValueType();
4651 for (
unsigned I = 0;
I < MinElts; ++
I)
4652 TruncMask[
I] = Scale *
I;
4654 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
4655 MVT SVT = In.getSimpleValueType().getScalarType();
4661 "Illegal vector type in truncation");
4680 SDValue FirstOperand =
N->getOperand(0);
4681 SDValue SecondOperand =
N->getOperand(1);
4682 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
4683 EVT ValTy =
N->getValueType(0);
4686 unsigned SMIdx, SMLen;
4692 if (!Subtarget.has32S())
4714 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
4729 if (SMIdx + SMLen > ValTy.getSizeInBits())
4748 NewOperand = FirstOperand;
4751 msb = lsb + SMLen - 1;
4755 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
4768 if (!Subtarget.has32S())
4780 SDValue FirstOperand =
N->getOperand(0);
4782 EVT ValTy =
N->getValueType(0);
4785 unsigned MaskIdx, MaskLen;
4800 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
4816 switch (Src.getOpcode()) {
4819 return Src.getOperand(0).getValueSizeInBits() ==
Size;
4829 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
4842 switch (Src.getOpcode()) {
4852 Src.getOpcode(),
DL, SExtVT,
4858 DL, SExtVT, Src.getOperand(0),
4870 EVT VT =
N->getValueType(0);
4872 EVT SrcVT = Src.getValueType();
4874 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
4879 EVT CmpVT = Src.getOperand(0).getValueType();
4884 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
4912 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4919 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
4943 EVT VT =
N->getValueType(0);
4945 EVT SrcVT = Src.getValueType();
4961 bool UseLASX =
false;
4962 bool PropagateSExt =
false;
4964 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
4965 EVT CmpVT = Src.getOperand(0).getValueType();
4974 SExtVT = MVT::v2i64;
4977 SExtVT = MVT::v4i32;
4979 SExtVT = MVT::v4i64;
4981 PropagateSExt =
true;
4985 SExtVT = MVT::v8i16;
4987 SExtVT = MVT::v8i32;
4989 PropagateSExt =
true;
4993 SExtVT = MVT::v16i8;
4995 SExtVT = MVT::v16i16;
4997 PropagateSExt =
true;
5001 SExtVT = MVT::v32i8;
5009 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
5010 if (Src.getSimpleValueType() == MVT::v32i8) {
5018 }
else if (UseLASX) {
5037 EVT ValTy =
N->getValueType(0);
5038 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5041 unsigned ValBits = ValTy.getSizeInBits();
5042 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
5044 bool SwapAndRetried =
false;
5047 if (!Subtarget.has32S())
5053 if (ValBits != 32 && ValBits != 64)
5068 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
5071 (MaskIdx0 + MaskLen0 <= ValBits)) {
5092 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
5093 (MaskIdx0 + MaskLen0 <= ValBits)) {
5110 (MaskIdx0 + MaskLen0 <= 64) &&
5118 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5119 : (MaskIdx0 + MaskLen0 - 1),
5135 (MaskIdx0 + MaskLen0 <= ValBits)) {
5158 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
5159 : (MaskIdx0 + MaskLen0 - 1),
5174 unsigned MaskIdx, MaskLen;
5175 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
5202 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
5216 if (!SwapAndRetried) {
5218 SwapAndRetried =
true;
5222 SwapAndRetried =
false;
5248 if (!SwapAndRetried) {
5250 SwapAndRetried =
true;
5260 switch (V.getNode()->getOpcode()) {
5272 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5280 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
5357 SDNode *AndNode =
N->getOperand(0).getNode();
5365 SDValue CmpInputValue =
N->getOperand(1);
5376 AndInputValue1 = AndInputValue1.
getOperand(0);
5380 if (AndInputValue2 != CmpInputValue)
5413 TruncInputValue1, TruncInputValue2);
5415 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
5456 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
5484 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
5518 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
5534 EVT VT =
N->getValueType(0);
5537 if (TrueV == FalseV)
5569 {LHS, RHS, CC, TrueV, FalseV});
5574template <
unsigned N>
5578 bool IsSigned =
false) {
5582 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5583 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5585 ": argument out of range.");
5591template <
unsigned N>
5595 EVT ResTy =
Node->getValueType(0);
5599 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
5600 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
5602 ": argument out of range.");
5607 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
5613 EVT ResTy =
Node->getValueType(0);
5621 EVT ResTy =
Node->getValueType(0);
5630template <
unsigned N>
5633 EVT ResTy =
Node->getValueType(0);
5638 ": argument out of range.");
5648template <
unsigned N>
5651 EVT ResTy =
Node->getValueType(0);
5656 ": argument out of range.");
5665template <
unsigned N>
5668 EVT ResTy =
Node->getValueType(0);
5673 ": argument out of range.");
5687 switch (
N->getConstantOperandVal(0)) {
5690 case Intrinsic::loongarch_lsx_vadd_b:
5691 case Intrinsic::loongarch_lsx_vadd_h:
5692 case Intrinsic::loongarch_lsx_vadd_w:
5693 case Intrinsic::loongarch_lsx_vadd_d:
5694 case Intrinsic::loongarch_lasx_xvadd_b:
5695 case Intrinsic::loongarch_lasx_xvadd_h:
5696 case Intrinsic::loongarch_lasx_xvadd_w:
5697 case Intrinsic::loongarch_lasx_xvadd_d:
5700 case Intrinsic::loongarch_lsx_vaddi_bu:
5701 case Intrinsic::loongarch_lsx_vaddi_hu:
5702 case Intrinsic::loongarch_lsx_vaddi_wu:
5703 case Intrinsic::loongarch_lsx_vaddi_du:
5704 case Intrinsic::loongarch_lasx_xvaddi_bu:
5705 case Intrinsic::loongarch_lasx_xvaddi_hu:
5706 case Intrinsic::loongarch_lasx_xvaddi_wu:
5707 case Intrinsic::loongarch_lasx_xvaddi_du:
5710 case Intrinsic::loongarch_lsx_vsub_b:
5711 case Intrinsic::loongarch_lsx_vsub_h:
5712 case Intrinsic::loongarch_lsx_vsub_w:
5713 case Intrinsic::loongarch_lsx_vsub_d:
5714 case Intrinsic::loongarch_lasx_xvsub_b:
5715 case Intrinsic::loongarch_lasx_xvsub_h:
5716 case Intrinsic::loongarch_lasx_xvsub_w:
5717 case Intrinsic::loongarch_lasx_xvsub_d:
5720 case Intrinsic::loongarch_lsx_vsubi_bu:
5721 case Intrinsic::loongarch_lsx_vsubi_hu:
5722 case Intrinsic::loongarch_lsx_vsubi_wu:
5723 case Intrinsic::loongarch_lsx_vsubi_du:
5724 case Intrinsic::loongarch_lasx_xvsubi_bu:
5725 case Intrinsic::loongarch_lasx_xvsubi_hu:
5726 case Intrinsic::loongarch_lasx_xvsubi_wu:
5727 case Intrinsic::loongarch_lasx_xvsubi_du:
5730 case Intrinsic::loongarch_lsx_vneg_b:
5731 case Intrinsic::loongarch_lsx_vneg_h:
5732 case Intrinsic::loongarch_lsx_vneg_w:
5733 case Intrinsic::loongarch_lsx_vneg_d:
5734 case Intrinsic::loongarch_lasx_xvneg_b:
5735 case Intrinsic::loongarch_lasx_xvneg_h:
5736 case Intrinsic::loongarch_lasx_xvneg_w:
5737 case Intrinsic::loongarch_lasx_xvneg_d:
5741 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
5743 SDLoc(
N),
N->getValueType(0)),
5745 case Intrinsic::loongarch_lsx_vmax_b:
5746 case Intrinsic::loongarch_lsx_vmax_h:
5747 case Intrinsic::loongarch_lsx_vmax_w:
5748 case Intrinsic::loongarch_lsx_vmax_d:
5749 case Intrinsic::loongarch_lasx_xvmax_b:
5750 case Intrinsic::loongarch_lasx_xvmax_h:
5751 case Intrinsic::loongarch_lasx_xvmax_w:
5752 case Intrinsic::loongarch_lasx_xvmax_d:
5755 case Intrinsic::loongarch_lsx_vmax_bu:
5756 case Intrinsic::loongarch_lsx_vmax_hu:
5757 case Intrinsic::loongarch_lsx_vmax_wu:
5758 case Intrinsic::loongarch_lsx_vmax_du:
5759 case Intrinsic::loongarch_lasx_xvmax_bu:
5760 case Intrinsic::loongarch_lasx_xvmax_hu:
5761 case Intrinsic::loongarch_lasx_xvmax_wu:
5762 case Intrinsic::loongarch_lasx_xvmax_du:
5765 case Intrinsic::loongarch_lsx_vmaxi_b:
5766 case Intrinsic::loongarch_lsx_vmaxi_h:
5767 case Intrinsic::loongarch_lsx_vmaxi_w:
5768 case Intrinsic::loongarch_lsx_vmaxi_d:
5769 case Intrinsic::loongarch_lasx_xvmaxi_b:
5770 case Intrinsic::loongarch_lasx_xvmaxi_h:
5771 case Intrinsic::loongarch_lasx_xvmaxi_w:
5772 case Intrinsic::loongarch_lasx_xvmaxi_d:
5775 case Intrinsic::loongarch_lsx_vmaxi_bu:
5776 case Intrinsic::loongarch_lsx_vmaxi_hu:
5777 case Intrinsic::loongarch_lsx_vmaxi_wu:
5778 case Intrinsic::loongarch_lsx_vmaxi_du:
5779 case Intrinsic::loongarch_lasx_xvmaxi_bu:
5780 case Intrinsic::loongarch_lasx_xvmaxi_hu:
5781 case Intrinsic::loongarch_lasx_xvmaxi_wu:
5782 case Intrinsic::loongarch_lasx_xvmaxi_du:
5785 case Intrinsic::loongarch_lsx_vmin_b:
5786 case Intrinsic::loongarch_lsx_vmin_h:
5787 case Intrinsic::loongarch_lsx_vmin_w:
5788 case Intrinsic::loongarch_lsx_vmin_d:
5789 case Intrinsic::loongarch_lasx_xvmin_b:
5790 case Intrinsic::loongarch_lasx_xvmin_h:
5791 case Intrinsic::loongarch_lasx_xvmin_w:
5792 case Intrinsic::loongarch_lasx_xvmin_d:
5795 case Intrinsic::loongarch_lsx_vmin_bu:
5796 case Intrinsic::loongarch_lsx_vmin_hu:
5797 case Intrinsic::loongarch_lsx_vmin_wu:
5798 case Intrinsic::loongarch_lsx_vmin_du:
5799 case Intrinsic::loongarch_lasx_xvmin_bu:
5800 case Intrinsic::loongarch_lasx_xvmin_hu:
5801 case Intrinsic::loongarch_lasx_xvmin_wu:
5802 case Intrinsic::loongarch_lasx_xvmin_du:
5805 case Intrinsic::loongarch_lsx_vmini_b:
5806 case Intrinsic::loongarch_lsx_vmini_h:
5807 case Intrinsic::loongarch_lsx_vmini_w:
5808 case Intrinsic::loongarch_lsx_vmini_d:
5809 case Intrinsic::loongarch_lasx_xvmini_b:
5810 case Intrinsic::loongarch_lasx_xvmini_h:
5811 case Intrinsic::loongarch_lasx_xvmini_w:
5812 case Intrinsic::loongarch_lasx_xvmini_d:
5815 case Intrinsic::loongarch_lsx_vmini_bu:
5816 case Intrinsic::loongarch_lsx_vmini_hu:
5817 case Intrinsic::loongarch_lsx_vmini_wu:
5818 case Intrinsic::loongarch_lsx_vmini_du:
5819 case Intrinsic::loongarch_lasx_xvmini_bu:
5820 case Intrinsic::loongarch_lasx_xvmini_hu:
5821 case Intrinsic::loongarch_lasx_xvmini_wu:
5822 case Intrinsic::loongarch_lasx_xvmini_du:
5825 case Intrinsic::loongarch_lsx_vmul_b:
5826 case Intrinsic::loongarch_lsx_vmul_h:
5827 case Intrinsic::loongarch_lsx_vmul_w:
5828 case Intrinsic::loongarch_lsx_vmul_d:
5829 case Intrinsic::loongarch_lasx_xvmul_b:
5830 case Intrinsic::loongarch_lasx_xvmul_h:
5831 case Intrinsic::loongarch_lasx_xvmul_w:
5832 case Intrinsic::loongarch_lasx_xvmul_d:
5835 case Intrinsic::loongarch_lsx_vmadd_b:
5836 case Intrinsic::loongarch_lsx_vmadd_h:
5837 case Intrinsic::loongarch_lsx_vmadd_w:
5838 case Intrinsic::loongarch_lsx_vmadd_d:
5839 case Intrinsic::loongarch_lasx_xvmadd_b:
5840 case Intrinsic::loongarch_lasx_xvmadd_h:
5841 case Intrinsic::loongarch_lasx_xvmadd_w:
5842 case Intrinsic::loongarch_lasx_xvmadd_d: {
5843 EVT ResTy =
N->getValueType(0);
5848 case Intrinsic::loongarch_lsx_vmsub_b:
5849 case Intrinsic::loongarch_lsx_vmsub_h:
5850 case Intrinsic::loongarch_lsx_vmsub_w:
5851 case Intrinsic::loongarch_lsx_vmsub_d:
5852 case Intrinsic::loongarch_lasx_xvmsub_b:
5853 case Intrinsic::loongarch_lasx_xvmsub_h:
5854 case Intrinsic::loongarch_lasx_xvmsub_w:
5855 case Intrinsic::loongarch_lasx_xvmsub_d: {
5856 EVT ResTy =
N->getValueType(0);
5861 case Intrinsic::loongarch_lsx_vdiv_b:
5862 case Intrinsic::loongarch_lsx_vdiv_h:
5863 case Intrinsic::loongarch_lsx_vdiv_w:
5864 case Intrinsic::loongarch_lsx_vdiv_d:
5865 case Intrinsic::loongarch_lasx_xvdiv_b:
5866 case Intrinsic::loongarch_lasx_xvdiv_h:
5867 case Intrinsic::loongarch_lasx_xvdiv_w:
5868 case Intrinsic::loongarch_lasx_xvdiv_d:
5871 case Intrinsic::loongarch_lsx_vdiv_bu:
5872 case Intrinsic::loongarch_lsx_vdiv_hu:
5873 case Intrinsic::loongarch_lsx_vdiv_wu:
5874 case Intrinsic::loongarch_lsx_vdiv_du:
5875 case Intrinsic::loongarch_lasx_xvdiv_bu:
5876 case Intrinsic::loongarch_lasx_xvdiv_hu:
5877 case Intrinsic::loongarch_lasx_xvdiv_wu:
5878 case Intrinsic::loongarch_lasx_xvdiv_du:
5881 case Intrinsic::loongarch_lsx_vmod_b:
5882 case Intrinsic::loongarch_lsx_vmod_h:
5883 case Intrinsic::loongarch_lsx_vmod_w:
5884 case Intrinsic::loongarch_lsx_vmod_d:
5885 case Intrinsic::loongarch_lasx_xvmod_b:
5886 case Intrinsic::loongarch_lasx_xvmod_h:
5887 case Intrinsic::loongarch_lasx_xvmod_w:
5888 case Intrinsic::loongarch_lasx_xvmod_d:
5891 case Intrinsic::loongarch_lsx_vmod_bu:
5892 case Intrinsic::loongarch_lsx_vmod_hu:
5893 case Intrinsic::loongarch_lsx_vmod_wu:
5894 case Intrinsic::loongarch_lsx_vmod_du:
5895 case Intrinsic::loongarch_lasx_xvmod_bu:
5896 case Intrinsic::loongarch_lasx_xvmod_hu:
5897 case Intrinsic::loongarch_lasx_xvmod_wu:
5898 case Intrinsic::loongarch_lasx_xvmod_du:
5901 case Intrinsic::loongarch_lsx_vand_v:
5902 case Intrinsic::loongarch_lasx_xvand_v:
5905 case Intrinsic::loongarch_lsx_vor_v:
5906 case Intrinsic::loongarch_lasx_xvor_v:
5909 case Intrinsic::loongarch_lsx_vxor_v:
5910 case Intrinsic::loongarch_lasx_xvxor_v:
5913 case Intrinsic::loongarch_lsx_vnor_v:
5914 case Intrinsic::loongarch_lasx_xvnor_v: {
5919 case Intrinsic::loongarch_lsx_vandi_b:
5920 case Intrinsic::loongarch_lasx_xvandi_b:
5923 case Intrinsic::loongarch_lsx_vori_b:
5924 case Intrinsic::loongarch_lasx_xvori_b:
5927 case Intrinsic::loongarch_lsx_vxori_b:
5928 case Intrinsic::loongarch_lasx_xvxori_b:
5931 case Intrinsic::loongarch_lsx_vsll_b:
5932 case Intrinsic::loongarch_lsx_vsll_h:
5933 case Intrinsic::loongarch_lsx_vsll_w:
5934 case Intrinsic::loongarch_lsx_vsll_d:
5935 case Intrinsic::loongarch_lasx_xvsll_b:
5936 case Intrinsic::loongarch_lasx_xvsll_h:
5937 case Intrinsic::loongarch_lasx_xvsll_w:
5938 case Intrinsic::loongarch_lasx_xvsll_d:
5941 case Intrinsic::loongarch_lsx_vslli_b:
5942 case Intrinsic::loongarch_lasx_xvslli_b:
5945 case Intrinsic::loongarch_lsx_vslli_h:
5946 case Intrinsic::loongarch_lasx_xvslli_h:
5949 case Intrinsic::loongarch_lsx_vslli_w:
5950 case Intrinsic::loongarch_lasx_xvslli_w:
5953 case Intrinsic::loongarch_lsx_vslli_d:
5954 case Intrinsic::loongarch_lasx_xvslli_d:
5957 case Intrinsic::loongarch_lsx_vsrl_b:
5958 case Intrinsic::loongarch_lsx_vsrl_h:
5959 case Intrinsic::loongarch_lsx_vsrl_w:
5960 case Intrinsic::loongarch_lsx_vsrl_d:
5961 case Intrinsic::loongarch_lasx_xvsrl_b:
5962 case Intrinsic::loongarch_lasx_xvsrl_h:
5963 case Intrinsic::loongarch_lasx_xvsrl_w:
5964 case Intrinsic::loongarch_lasx_xvsrl_d:
5967 case Intrinsic::loongarch_lsx_vsrli_b:
5968 case Intrinsic::loongarch_lasx_xvsrli_b:
5971 case Intrinsic::loongarch_lsx_vsrli_h:
5972 case Intrinsic::loongarch_lasx_xvsrli_h:
5975 case Intrinsic::loongarch_lsx_vsrli_w:
5976 case Intrinsic::loongarch_lasx_xvsrli_w:
5979 case Intrinsic::loongarch_lsx_vsrli_d:
5980 case Intrinsic::loongarch_lasx_xvsrli_d:
5983 case Intrinsic::loongarch_lsx_vsra_b:
5984 case Intrinsic::loongarch_lsx_vsra_h:
5985 case Intrinsic::loongarch_lsx_vsra_w:
5986 case Intrinsic::loongarch_lsx_vsra_d:
5987 case Intrinsic::loongarch_lasx_xvsra_b:
5988 case Intrinsic::loongarch_lasx_xvsra_h:
5989 case Intrinsic::loongarch_lasx_xvsra_w:
5990 case Intrinsic::loongarch_lasx_xvsra_d:
5993 case Intrinsic::loongarch_lsx_vsrai_b:
5994 case Intrinsic::loongarch_lasx_xvsrai_b:
5997 case Intrinsic::loongarch_lsx_vsrai_h:
5998 case Intrinsic::loongarch_lasx_xvsrai_h:
6001 case Intrinsic::loongarch_lsx_vsrai_w:
6002 case Intrinsic::loongarch_lasx_xvsrai_w:
6005 case Intrinsic::loongarch_lsx_vsrai_d:
6006 case Intrinsic::loongarch_lasx_xvsrai_d:
6009 case Intrinsic::loongarch_lsx_vclz_b:
6010 case Intrinsic::loongarch_lsx_vclz_h:
6011 case Intrinsic::loongarch_lsx_vclz_w:
6012 case Intrinsic::loongarch_lsx_vclz_d:
6013 case Intrinsic::loongarch_lasx_xvclz_b:
6014 case Intrinsic::loongarch_lasx_xvclz_h:
6015 case Intrinsic::loongarch_lasx_xvclz_w:
6016 case Intrinsic::loongarch_lasx_xvclz_d:
6018 case Intrinsic::loongarch_lsx_vpcnt_b:
6019 case Intrinsic::loongarch_lsx_vpcnt_h:
6020 case Intrinsic::loongarch_lsx_vpcnt_w:
6021 case Intrinsic::loongarch_lsx_vpcnt_d:
6022 case Intrinsic::loongarch_lasx_xvpcnt_b:
6023 case Intrinsic::loongarch_lasx_xvpcnt_h:
6024 case Intrinsic::loongarch_lasx_xvpcnt_w:
6025 case Intrinsic::loongarch_lasx_xvpcnt_d:
6027 case Intrinsic::loongarch_lsx_vbitclr_b:
6028 case Intrinsic::loongarch_lsx_vbitclr_h:
6029 case Intrinsic::loongarch_lsx_vbitclr_w:
6030 case Intrinsic::loongarch_lsx_vbitclr_d:
6031 case Intrinsic::loongarch_lasx_xvbitclr_b:
6032 case Intrinsic::loongarch_lasx_xvbitclr_h:
6033 case Intrinsic::loongarch_lasx_xvbitclr_w:
6034 case Intrinsic::loongarch_lasx_xvbitclr_d:
6036 case Intrinsic::loongarch_lsx_vbitclri_b:
6037 case Intrinsic::loongarch_lasx_xvbitclri_b:
6039 case Intrinsic::loongarch_lsx_vbitclri_h:
6040 case Intrinsic::loongarch_lasx_xvbitclri_h:
6042 case Intrinsic::loongarch_lsx_vbitclri_w:
6043 case Intrinsic::loongarch_lasx_xvbitclri_w:
6045 case Intrinsic::loongarch_lsx_vbitclri_d:
6046 case Intrinsic::loongarch_lasx_xvbitclri_d:
6048 case Intrinsic::loongarch_lsx_vbitset_b:
6049 case Intrinsic::loongarch_lsx_vbitset_h:
6050 case Intrinsic::loongarch_lsx_vbitset_w:
6051 case Intrinsic::loongarch_lsx_vbitset_d:
6052 case Intrinsic::loongarch_lasx_xvbitset_b:
6053 case Intrinsic::loongarch_lasx_xvbitset_h:
6054 case Intrinsic::loongarch_lasx_xvbitset_w:
6055 case Intrinsic::loongarch_lasx_xvbitset_d: {
6056 EVT VecTy =
N->getValueType(0);
6062 case Intrinsic::loongarch_lsx_vbitseti_b:
6063 case Intrinsic::loongarch_lasx_xvbitseti_b:
6065 case Intrinsic::loongarch_lsx_vbitseti_h:
6066 case Intrinsic::loongarch_lasx_xvbitseti_h:
6068 case Intrinsic::loongarch_lsx_vbitseti_w:
6069 case Intrinsic::loongarch_lasx_xvbitseti_w:
6071 case Intrinsic::loongarch_lsx_vbitseti_d:
6072 case Intrinsic::loongarch_lasx_xvbitseti_d:
6074 case Intrinsic::loongarch_lsx_vbitrev_b:
6075 case Intrinsic::loongarch_lsx_vbitrev_h:
6076 case Intrinsic::loongarch_lsx_vbitrev_w:
6077 case Intrinsic::loongarch_lsx_vbitrev_d:
6078 case Intrinsic::loongarch_lasx_xvbitrev_b:
6079 case Intrinsic::loongarch_lasx_xvbitrev_h:
6080 case Intrinsic::loongarch_lasx_xvbitrev_w:
6081 case Intrinsic::loongarch_lasx_xvbitrev_d: {
6082 EVT VecTy =
N->getValueType(0);
6088 case Intrinsic::loongarch_lsx_vbitrevi_b:
6089 case Intrinsic::loongarch_lasx_xvbitrevi_b:
6091 case Intrinsic::loongarch_lsx_vbitrevi_h:
6092 case Intrinsic::loongarch_lasx_xvbitrevi_h:
6094 case Intrinsic::loongarch_lsx_vbitrevi_w:
6095 case Intrinsic::loongarch_lasx_xvbitrevi_w:
6097 case Intrinsic::loongarch_lsx_vbitrevi_d:
6098 case Intrinsic::loongarch_lasx_xvbitrevi_d:
6100 case Intrinsic::loongarch_lsx_vfadd_s:
6101 case Intrinsic::loongarch_lsx_vfadd_d:
6102 case Intrinsic::loongarch_lasx_xvfadd_s:
6103 case Intrinsic::loongarch_lasx_xvfadd_d:
6106 case Intrinsic::loongarch_lsx_vfsub_s:
6107 case Intrinsic::loongarch_lsx_vfsub_d:
6108 case Intrinsic::loongarch_lasx_xvfsub_s:
6109 case Intrinsic::loongarch_lasx_xvfsub_d:
6112 case Intrinsic::loongarch_lsx_vfmul_s:
6113 case Intrinsic::loongarch_lsx_vfmul_d:
6114 case Intrinsic::loongarch_lasx_xvfmul_s:
6115 case Intrinsic::loongarch_lasx_xvfmul_d:
6118 case Intrinsic::loongarch_lsx_vfdiv_s:
6119 case Intrinsic::loongarch_lsx_vfdiv_d:
6120 case Intrinsic::loongarch_lasx_xvfdiv_s:
6121 case Intrinsic::loongarch_lasx_xvfdiv_d:
6124 case Intrinsic::loongarch_lsx_vfmadd_s:
6125 case Intrinsic::loongarch_lsx_vfmadd_d:
6126 case Intrinsic::loongarch_lasx_xvfmadd_s:
6127 case Intrinsic::loongarch_lasx_xvfmadd_d:
6129 N->getOperand(2),
N->getOperand(3));
6130 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
6132 N->getOperand(1),
N->getOperand(2),
6134 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
6135 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
6137 N->getOperand(1),
N->getOperand(2),
6139 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
6140 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
6142 N->getOperand(1),
N->getOperand(2),
6144 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
6146 N->getOperand(1),
N->getOperand(2),
6148 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
6149 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
6150 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
6151 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
6152 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
6153 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
6154 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
6155 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
6159 case Intrinsic::loongarch_lsx_vreplve_b:
6160 case Intrinsic::loongarch_lsx_vreplve_h:
6161 case Intrinsic::loongarch_lsx_vreplve_w:
6162 case Intrinsic::loongarch_lsx_vreplve_d:
6163 case Intrinsic::loongarch_lasx_xvreplve_b:
6164 case Intrinsic::loongarch_lasx_xvreplve_h:
6165 case Intrinsic::loongarch_lasx_xvreplve_w:
6166 case Intrinsic::loongarch_lasx_xvreplve_d:
6196 "Unexpected value type!");
6205 MVT VT =
N->getSimpleValueType(0);
6239 APInt V =
C->getValueAPF().bitcastToAPInt();
6255 MVT EltVT =
N->getSimpleValueType(0);
6287 switch (
N->getOpcode()) {
6341 MF->
insert(It, BreakMBB);
6345 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
6346 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
6358 MBB->addSuccessor(BreakMBB);
6359 MBB->addSuccessor(SinkMBB);
6365 BreakMBB->addSuccessor(SinkMBB);
6377 switch (
MI.getOpcode()) {
6380 case LoongArch::PseudoVBZ:
6381 CondOpc = LoongArch::VSETEQZ_V;
6383 case LoongArch::PseudoVBZ_B:
6384 CondOpc = LoongArch::VSETANYEQZ_B;
6386 case LoongArch::PseudoVBZ_H:
6387 CondOpc = LoongArch::VSETANYEQZ_H;
6389 case LoongArch::PseudoVBZ_W:
6390 CondOpc = LoongArch::VSETANYEQZ_W;
6392 case LoongArch::PseudoVBZ_D:
6393 CondOpc = LoongArch::VSETANYEQZ_D;
6395 case LoongArch::PseudoVBNZ:
6396 CondOpc = LoongArch::VSETNEZ_V;
6398 case LoongArch::PseudoVBNZ_B:
6399 CondOpc = LoongArch::VSETALLNEZ_B;
6401 case LoongArch::PseudoVBNZ_H:
6402 CondOpc = LoongArch::VSETALLNEZ_H;
6404 case LoongArch::PseudoVBNZ_W:
6405 CondOpc = LoongArch::VSETALLNEZ_W;
6407 case LoongArch::PseudoVBNZ_D:
6408 CondOpc = LoongArch::VSETALLNEZ_D;
6410 case LoongArch::PseudoXVBZ:
6411 CondOpc = LoongArch::XVSETEQZ_V;
6413 case LoongArch::PseudoXVBZ_B:
6414 CondOpc = LoongArch::XVSETANYEQZ_B;
6416 case LoongArch::PseudoXVBZ_H:
6417 CondOpc = LoongArch::XVSETANYEQZ_H;
6419 case LoongArch::PseudoXVBZ_W:
6420 CondOpc = LoongArch::XVSETANYEQZ_W;
6422 case LoongArch::PseudoXVBZ_D:
6423 CondOpc = LoongArch::XVSETANYEQZ_D;
6425 case LoongArch::PseudoXVBNZ:
6426 CondOpc = LoongArch::XVSETNEZ_V;
6428 case LoongArch::PseudoXVBNZ_B:
6429 CondOpc = LoongArch::XVSETALLNEZ_B;
6431 case LoongArch::PseudoXVBNZ_H:
6432 CondOpc = LoongArch::XVSETALLNEZ_H;
6434 case LoongArch::PseudoXVBNZ_W:
6435 CondOpc = LoongArch::XVSETALLNEZ_W;
6437 case LoongArch::PseudoXVBNZ_D:
6438 CondOpc = LoongArch::XVSETALLNEZ_D;
6453 F->insert(It, FalseBB);
6454 F->insert(It, TrueBB);
6455 F->insert(It, SinkBB);
6458 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
6462 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
6471 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6479 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6487 MI.getOperand(0).getReg())
6494 MI.eraseFromParent();
6502 unsigned BroadcastOp;
6504 switch (
MI.getOpcode()) {
6507 case LoongArch::PseudoXVINSGR2VR_B:
6509 BroadcastOp = LoongArch::XVREPLGR2VR_B;
6510 InsOp = LoongArch::XVEXTRINS_B;
6512 case LoongArch::PseudoXVINSGR2VR_H:
6514 BroadcastOp = LoongArch::XVREPLGR2VR_H;
6515 InsOp = LoongArch::XVEXTRINS_H;
6527 unsigned Idx =
MI.getOperand(3).getImm();
6529 if (XSrc.
isVirtual() &&
MRI.getVRegDef(XSrc)->isImplicitDef() &&
6531 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
6532 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
6535 .
addReg(XSrc, 0, LoongArch::sub_128);
6537 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
6538 : LoongArch::VINSGR2VR_B),
6547 .
addImm(LoongArch::sub_128);
6549 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6550 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6554 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
6557 .
addImm(Idx >= HalfSize ? 48 : 18);
6562 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
6565 MI.eraseFromParent();
6572 assert(Subtarget.hasExtLSX());
6579 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
6580 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
6581 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
6585 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
6586 : LoongArch::VINSGR2VR_W),
6593 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
6597 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
6598 : LoongArch::VPICKVE2GR_W),
6603 MI.eraseFromParent();
6617 unsigned EleBits = 8;
6618 unsigned NotOpc = 0;
6621 switch (
MI.getOpcode()) {
6624 case LoongArch::PseudoVMSKLTZ_B:
6625 MskOpc = LoongArch::VMSKLTZ_B;
6627 case LoongArch::PseudoVMSKLTZ_H:
6628 MskOpc = LoongArch::VMSKLTZ_H;
6631 case LoongArch::PseudoVMSKLTZ_W:
6632 MskOpc = LoongArch::VMSKLTZ_W;
6635 case LoongArch::PseudoVMSKLTZ_D:
6636 MskOpc = LoongArch::VMSKLTZ_D;
6639 case LoongArch::PseudoVMSKGEZ_B:
6640 MskOpc = LoongArch::VMSKGEZ_B;
6642 case LoongArch::PseudoVMSKEQZ_B:
6643 MskOpc = LoongArch::VMSKNZ_B;
6644 NotOpc = LoongArch::VNOR_V;
6646 case LoongArch::PseudoVMSKNEZ_B:
6647 MskOpc = LoongArch::VMSKNZ_B;
6649 case LoongArch::PseudoXVMSKLTZ_B:
6650 MskOpc = LoongArch::XVMSKLTZ_B;
6651 RC = &LoongArch::LASX256RegClass;
6653 case LoongArch::PseudoXVMSKLTZ_H:
6654 MskOpc = LoongArch::XVMSKLTZ_H;
6655 RC = &LoongArch::LASX256RegClass;
6658 case LoongArch::PseudoXVMSKLTZ_W:
6659 MskOpc = LoongArch::XVMSKLTZ_W;
6660 RC = &LoongArch::LASX256RegClass;
6663 case LoongArch::PseudoXVMSKLTZ_D:
6664 MskOpc = LoongArch::XVMSKLTZ_D;
6665 RC = &LoongArch::LASX256RegClass;
6668 case LoongArch::PseudoXVMSKGEZ_B:
6669 MskOpc = LoongArch::XVMSKGEZ_B;
6670 RC = &LoongArch::LASX256RegClass;
6672 case LoongArch::PseudoXVMSKEQZ_B:
6673 MskOpc = LoongArch::XVMSKNZ_B;
6674 NotOpc = LoongArch::XVNOR_V;
6675 RC = &LoongArch::LASX256RegClass;
6677 case LoongArch::PseudoXVMSKNEZ_B:
6678 MskOpc = LoongArch::XVMSKNZ_B;
6679 RC = &LoongArch::LASX256RegClass;
6694 if (
TRI->getRegSizeInBits(*RC) > 128) {
6695 Register Lo =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6696 Register Hi =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
6704 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
6705 : LoongArch::BSTRINS_W),
6709 .
addImm(256 / EleBits - 1)
6717 MI.eraseFromParent();
6724 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
6725 "Unexpected instruction");
6737 MI.eraseFromParent();
6744 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
6745 "Unexpected instruction");
6751 Register TmpReg =
MRI.createVirtualRegister(&LoongArch::FPR64RegClass);
6761 MI.eraseFromParent();
6766 switch (
MI.getOpcode()) {
6769 case LoongArch::Select_GPR_Using_CC_GPR:
6805 if (
MI.getOperand(2).isReg())
6806 RHS =
MI.getOperand(2).getReg();
6807 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
6811 SelectDests.
insert(
MI.getOperand(0).getReg());
6815 SequenceMBBI !=
E; ++SequenceMBBI) {
6816 if (SequenceMBBI->isDebugInstr())
6819 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
6820 !SequenceMBBI->getOperand(2).isReg() ||
6821 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
6822 SequenceMBBI->getOperand(3).getImm() != CC ||
6823 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
6824 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
6826 LastSelectPseudo = &*SequenceMBBI;
6828 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
6831 if (SequenceMBBI->hasUnmodeledSideEffects() ||
6832 SequenceMBBI->mayLoadOrStore() ||
6833 SequenceMBBI->usesCustomInsertionHook())
6836 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
6851 F->insert(
I, IfFalseMBB);
6852 F->insert(
I, TailMBB);
6855 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
6861 TailMBB->
push_back(DebugInstr->removeFromParent());
6865 TailMBB->
splice(TailMBB->
end(), HeadMBB,
6875 if (
MI.getOperand(2).isImm())
6887 auto SelectMBBI =
MI.getIterator();
6888 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
6890 while (SelectMBBI != SelectEnd) {
6891 auto Next = std::next(SelectMBBI);
6895 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
6896 .
addReg(SelectMBBI->getOperand(4).getReg())
6898 .
addReg(SelectMBBI->getOperand(5).getReg())
6905 F->getProperties().resetNoPHIs();
6911 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
6914 switch (
MI.getOpcode()) {
6917 case LoongArch::DIV_W:
6918 case LoongArch::DIV_WU:
6919 case LoongArch::MOD_W:
6920 case LoongArch::MOD_WU:
6921 case LoongArch::DIV_D:
6922 case LoongArch::DIV_DU:
6923 case LoongArch::MOD_D:
6924 case LoongArch::MOD_DU:
6927 case LoongArch::WRFCSR: {
6929 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
6930 .
addReg(
MI.getOperand(1).getReg());
6931 MI.eraseFromParent();
6934 case LoongArch::RDFCSR: {
6935 MachineInstr *ReadFCSR =
6937 MI.getOperand(0).getReg())
6938 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
6940 MI.eraseFromParent();
6943 case LoongArch::Select_GPR_Using_CC_GPR:
6945 case LoongArch::BuildPairF64Pseudo:
6947 case LoongArch::SplitPairF64Pseudo:
6949 case LoongArch::PseudoVBZ:
6950 case LoongArch::PseudoVBZ_B:
6951 case LoongArch::PseudoVBZ_H:
6952 case LoongArch::PseudoVBZ_W:
6953 case LoongArch::PseudoVBZ_D:
6954 case LoongArch::PseudoVBNZ:
6955 case LoongArch::PseudoVBNZ_B:
6956 case LoongArch::PseudoVBNZ_H:
6957 case LoongArch::PseudoVBNZ_W:
6958 case LoongArch::PseudoVBNZ_D:
6959 case LoongArch::PseudoXVBZ:
6960 case LoongArch::PseudoXVBZ_B:
6961 case LoongArch::PseudoXVBZ_H:
6962 case LoongArch::PseudoXVBZ_W:
6963 case LoongArch::PseudoXVBZ_D:
6964 case LoongArch::PseudoXVBNZ:
6965 case LoongArch::PseudoXVBNZ_B:
6966 case LoongArch::PseudoXVBNZ_H:
6967 case LoongArch::PseudoXVBNZ_W:
6968 case LoongArch::PseudoXVBNZ_D:
6970 case LoongArch::PseudoXVINSGR2VR_B:
6971 case LoongArch::PseudoXVINSGR2VR_H:
6973 case LoongArch::PseudoCTPOP:
6975 case LoongArch::PseudoVMSKLTZ_B:
6976 case LoongArch::PseudoVMSKLTZ_H:
6977 case LoongArch::PseudoVMSKLTZ_W:
6978 case LoongArch::PseudoVMSKLTZ_D:
6979 case LoongArch::PseudoVMSKGEZ_B:
6980 case LoongArch::PseudoVMSKEQZ_B:
6981 case LoongArch::PseudoVMSKNEZ_B:
6982 case LoongArch::PseudoXVMSKLTZ_B:
6983 case LoongArch::PseudoXVMSKLTZ_H:
6984 case LoongArch::PseudoXVMSKLTZ_W:
6985 case LoongArch::PseudoXVMSKLTZ_D:
6986 case LoongArch::PseudoXVMSKGEZ_B:
6987 case LoongArch::PseudoXVMSKEQZ_B:
6988 case LoongArch::PseudoXVMSKNEZ_B:
6990 case TargetOpcode::STATEPOINT:
6996 MI.addOperand(*
MI.getMF(),
6998 LoongArch::R1,
true,
7001 if (!Subtarget.is64Bit())
7009 unsigned *
Fast)
const {
7010 if (!Subtarget.hasUAL())
7024#define NODE_NAME_CASE(node) \
7025 case LoongArchISD::node: \
7026 return "LoongArchISD::" #node;
7126#undef NODE_NAME_CASE
7139 LoongArch::R7, LoongArch::R8, LoongArch::R9,
7140 LoongArch::R10, LoongArch::R11};
7144 LoongArch::F3, LoongArch::F4, LoongArch::F5,
7145 LoongArch::F6, LoongArch::F7};
7148 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
7149 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7152 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
7153 LoongArch::VR6, LoongArch::VR7};
7156 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
7157 LoongArch::XR6, LoongArch::XR7};
7163 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
7165 unsigned GRLenInBytes = GRLen / 8;
7176 State.AllocateStack(GRLenInBytes, StackAlign),
7179 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7190 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
7198 unsigned ValNo,
MVT ValVT,
7201 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
7202 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
7203 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
7208 if (IsRet && ValNo > 1)
7212 bool UseGPRForFloat =
true;
7222 UseGPRForFloat = ArgFlags.
isVarArg();
7235 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
7238 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
7239 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
7241 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
7247 State.getPendingArgFlags();
7250 "PendingLocs and PendingArgFlags out of sync");
7254 UseGPRForFloat =
true;
7256 if (UseGPRForFloat && ValVT == MVT::f32) {
7259 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
7262 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
7265 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
7307 PendingLocs.
size() <= 2) {
7308 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
7313 PendingLocs.
clear();
7314 PendingArgFlags.
clear();
7321 unsigned StoreSizeBytes = GRLen / 8;
7324 if (ValVT == MVT::f32 && !UseGPRForFloat)
7326 else if (ValVT == MVT::f64 && !UseGPRForFloat)
7336 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
7340 if (!PendingLocs.
empty()) {
7342 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
7343 for (
auto &It : PendingLocs) {
7345 It.convertToReg(
Reg);
7350 PendingLocs.clear();
7351 PendingArgFlags.
clear();
7354 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
7355 "Expected an GRLenVT at this stage");
7372void LoongArchTargetLowering::analyzeInputArgs(
7375 LoongArchCCAssignFn Fn)
const {
7377 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
7378 MVT ArgVT =
Ins[i].VT;
7379 Type *ArgTy =
nullptr;
7381 ArgTy = FType->getReturnType();
7382 else if (Ins[i].isOrigArg())
7383 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
7387 CCInfo, IsRet, ArgTy)) {
7388 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
7395void LoongArchTargetLowering::analyzeOutputArgs(
7398 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
7399 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7400 MVT ArgVT = Outs[i].VT;
7401 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
7405 CCInfo, IsRet, OrigTy)) {
7406 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
7447 if (In.isOrigArg()) {
7452 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
7453 (
BitWidth < 32 && In.Flags.isZExt())) {
7503 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7516 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
7536 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
7546 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
7550 LoongArch::R23, LoongArch::R24, LoongArch::R25,
7551 LoongArch::R26, LoongArch::R27, LoongArch::R28,
7552 LoongArch::R29, LoongArch::R30, LoongArch::R31};
7559 if (LocVT == MVT::f32) {
7562 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
7563 LoongArch::F26, LoongArch::F27};
7570 if (LocVT == MVT::f64) {
7573 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
7574 LoongArch::F30_64, LoongArch::F31_64};
7604 "GHC calling convention requires the F and D extensions");
7608 MVT GRLenVT = Subtarget.getGRLenVT();
7609 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
7611 std::vector<SDValue> OutChains;
7620 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
7622 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
7639 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
7640 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
7641 assert(ArgPartOffset == 0);
7642 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
7644 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
7668 int VaArgOffset, VarArgsSaveSize;
7672 if (ArgRegs.
size() == Idx) {
7674 VarArgsSaveSize = 0;
7676 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
7677 VaArgOffset = -VarArgsSaveSize;
7683 LoongArchFI->setVarArgsFrameIndex(FI);
7691 VarArgsSaveSize += GRLenInBytes;
7696 for (
unsigned I = Idx;
I < ArgRegs.
size();
7697 ++
I, VaArgOffset += GRLenInBytes) {
7698 const Register Reg = RegInfo.createVirtualRegister(RC);
7699 RegInfo.addLiveIn(ArgRegs[
I], Reg);
7707 ->setValue((
Value *)
nullptr);
7708 OutChains.push_back(Store);
7710 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
7715 if (!OutChains.empty()) {
7716 OutChains.push_back(Chain);
7731 if (
N->getNumValues() != 1)
7733 if (!
N->hasNUsesOfValue(1, 0))
7736 SDNode *Copy = *
N->user_begin();
7742 if (Copy->getGluedNode())
7746 bool HasRet =
false;
7756 Chain = Copy->getOperand(0);
7761bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
7765 auto CalleeCC = CLI.CallConv;
7766 auto &Outs = CLI.Outs;
7768 auto CallerCC = Caller.getCallingConv();
7775 for (
auto &VA : ArgLocs)
7781 auto IsCallerStructRet = Caller.hasStructRetAttr();
7782 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
7783 if (IsCallerStructRet || IsCalleeStructRet)
7787 for (
auto &Arg : Outs)
7788 if (Arg.Flags.isByVal())
7793 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
7794 if (CalleeCC != CallerCC) {
7795 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
7796 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
7822 MVT GRLenVT = Subtarget.getGRLenVT();
7834 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
7838 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
7844 "site marked musttail");
7851 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
7853 if (!Flags.isByVal())
7857 unsigned Size = Flags.getByValSize();
7858 Align Alignment = Flags.getNonZeroByValAlign();
7865 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
7867 false,
nullptr, std::nullopt,
7879 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
7882 SDValue ArgValue = OutVals[OutIdx];
7891 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
7903 if (!StackPtr.getNode())
7915 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
7930 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
7931 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
7932 assert(ArgPartOffset == 0);
7937 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
7938 SDValue PartValue = OutVals[OutIdx + 1];
7939 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
7954 for (
const auto &Part : Parts) {
7955 SDValue PartValue = Part.first;
7956 SDValue PartOffset = Part.second;
7963 ArgValue = SpillSlot;
7969 if (Flags.isByVal())
7970 ArgValue = ByValArgs[j++];
7977 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
7978 "for passing parameters");
7981 if (!StackPtr.getNode())
7994 if (!MemOpChains.
empty())
8000 for (
auto &Reg : RegsToPass) {
8001 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
8023 Ops.push_back(Chain);
8024 Ops.push_back(Callee);
8028 for (
auto &Reg : RegsToPass)
8029 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
8034 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
8035 assert(Mask &&
"Missing call preserved mask for calling convention");
8041 Ops.push_back(Glue);
8053 assert(Subtarget.is64Bit() &&
"Medium code model requires LA64");
8057 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
8080 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
8083 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
8084 auto &VA = RVLocs[i];
8092 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
8093 assert(VA.needsCustom());
8099 RetValue, RetValue2);
8112 const Type *RetTy)
const {
8114 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
8116 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8120 Outs[i].Flags, CCInfo,
true,
nullptr))
8146 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
8147 SDValue Val = OutVals[OutIdx];
8156 DAG.
getVTList(MVT::i32, MVT::i32), Val);
8160 Register RegHi = RVLocs[++i].getLocReg();
8190 if (!Subtarget.hasExtLSX())
8193 if (VT == MVT::f32) {
8194 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
8195 return (masked == 0x3e000000 || masked == 0x40000000);
8198 if (VT == MVT::f64) {
8199 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
8200 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
8206bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
8207 bool ForCodeSize)
const {
8209 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8211 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8213 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
8224bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
8234 Type *Ty =
I->getOperand(0)->getType();
8236 unsigned Size = Ty->getIntegerBitWidth();
8263 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
8264 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
8265 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
8266 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
8268 Info.memVT = MVT::i32;
8269 Info.ptrVal =
I.getArgOperand(0);
8271 Info.align =
Align(4);
8288 "Unable to expand");
8289 unsigned MinWordSize = 4;
8301 Value *AlignedAddr = Builder.CreateIntrinsic(
8302 Intrinsic::ptrmask, {PtrTy, IntTy},
8303 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
8306 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
8307 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
8308 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
8309 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
8310 Value *Mask = Builder.CreateShl(
8311 ConstantInt::get(WordType,
8314 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
8315 Value *ValOperand_Shifted =
8316 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
8317 ShiftAmt,
"ValOperand_Shifted");
8320 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
8322 NewOperand = ValOperand_Shifted;
8325 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
8328 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
8329 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
8348 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
8356 if (Subtarget.hasLAMCAS()) {
8378 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
8380 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
8382 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
8384 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
8386 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
8388 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
8390 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
8392 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
8402 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
8404 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
8406 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
8408 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
8410 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
8412 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
8414 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
8416 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
8428 if (Subtarget.hasLAMCAS())
8440 unsigned GRLen = Subtarget.getGRLen();
8442 Value *FailureOrdering =
8443 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
8444 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
8446 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
8447 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
8448 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
8449 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
8452 Value *Result = Builder.CreateIntrinsic(
8453 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
8455 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
8471 Builder.CreateNot(Mask,
"Inv_Mask"),
8478 unsigned GRLen = Subtarget.getGRLen();
8487 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
8488 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
8489 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
8505 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
8506 Result = Builder.CreateCall(LlwOpScwLoop,
8507 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
8510 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
8514 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
8537 const Constant *PersonalityFn)
const {
8538 return LoongArch::R4;
8542 const Constant *PersonalityFn)
const {
8543 return LoongArch::R5;
8554 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
8555 return RefinementSteps;
8560 int &RefinementSteps,
8561 bool &UseOneConstNR,
8562 bool Reciprocal)
const {
8563 if (Subtarget.hasFrecipe()) {
8567 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8568 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8569 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8570 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8571 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8590 int &RefinementSteps)
const {
8591 if (Subtarget.hasFrecipe()) {
8595 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
8596 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
8597 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
8598 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
8599 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
8616LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
8636 if (Constraint.
size() == 1) {
8637 switch (Constraint[0]) {
8653 if (Constraint ==
"ZC" || Constraint ==
"ZB")
8662 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
8669std::pair<unsigned, const TargetRegisterClass *>
8670LoongArchTargetLowering::getRegForInlineAsmConstraint(
8674 if (Constraint.
size() == 1) {
8675 switch (Constraint[0]) {
8680 return std::make_pair(0U, &LoongArch::GPRRegClass);
8682 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
8684 if (Subtarget.hasBasicF() && VT == MVT::f32)
8685 return std::make_pair(0U, &LoongArch::FPR32RegClass);
8686 if (Subtarget.hasBasicD() && VT == MVT::f64)
8687 return std::make_pair(0U, &LoongArch::FPR64RegClass);
8688 if (Subtarget.hasExtLSX() &&
8689 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
8690 return std::make_pair(0U, &LoongArch::LSX128RegClass);
8691 if (Subtarget.hasExtLASX() &&
8692 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
8693 return std::make_pair(0U, &LoongArch::LASX256RegClass);
8713 bool IsFP = Constraint[2] ==
'f';
8714 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
8715 std::pair<unsigned, const TargetRegisterClass *>
R;
8720 unsigned RegNo =
R.first;
8721 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
8722 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
8723 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
8724 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
8734void LoongArchTargetLowering::LowerAsmOperandForConstraint(
8738 if (Constraint.
size() == 1) {
8739 switch (Constraint[0]) {
8743 uint64_t CVal =
C->getSExtValue();
8746 Subtarget.getGRLenVT()));
8752 uint64_t CVal =
C->getSExtValue();
8755 Subtarget.getGRLenVT()));
8761 if (
C->getZExtValue() == 0)
8768 uint64_t CVal =
C->getZExtValue();
8781#define GET_REGISTER_MATCHER
8782#include "LoongArchGenAsmMatcher.inc"
8788 std::string NewRegName = Name.second.str();
8794 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
8795 if (!ReservedRegs.
test(Reg))
8812 const APInt &Imm = ConstNode->getAPIntValue();
8814 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
8815 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
8818 if (ConstNode->hasOneUse() &&
8819 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
8820 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
8826 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
8827 unsigned Shifts = Imm.countr_zero();
8833 APInt ImmPop = Imm.ashr(Shifts);
8834 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
8838 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
8839 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
8840 (ImmSmall - Imm).isPowerOf2())
8850 Type *Ty,
unsigned AS,
8905 EVT MemVT = LD->getMemoryVT();
8906 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
8917 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
8926 if (
Y.getValueType().isVector())
8938 Type *Ty,
bool IsSigned)
const {
8939 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
8948 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
8949 Type.getSizeInBits() < Subtarget.getGRLen()))
8959 Align &PrefAlign)
const {
8963 if (Subtarget.is64Bit()) {
8965 PrefAlign =
Align(8);
8968 PrefAlign =
Align(4);
8983bool LoongArchTargetLowering::splitValueIntoRegisterParts(
8985 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
8986 bool IsABIRegCopy = CC.has_value();
8989 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
8990 PartVT == MVT::f32) {
8993 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
8997 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f32, Val);
9005SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
9007 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
9008 bool IsABIRegCopy = CC.has_value();
9010 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
9011 PartVT == MVT::f32) {
9015 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
9017 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
9028 if (VT == MVT::f16 && Subtarget.hasBasicF())
9034unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
9037 if (VT == MVT::f16 && Subtarget.hasBasicF())
9046 unsigned Depth)
const {
9047 EVT VT =
Op.getValueType();
9049 unsigned Opc =
Op.getOpcode();
9056 MVT SrcVT = Src.getSimpleValueType();
9061 if (OriginalDemandedBits.
countr_zero() >= NumElts)
9065 APInt KnownUndef, KnownZero;
9081 if (KnownSrc.
One[SrcBits - 1])
9083 else if (KnownSrc.
Zero[SrcBits - 1])
9088 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
9095 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
#define NODE_NAME_CASE(node)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performEXTRACT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VSHUF.
static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
A "pseudo-class" with methods for operating on BUILD_VECTORs.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Argument * getArg(unsigned i) const
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
This class is used to represent ISD::LOAD nodes.
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void addSExt32Register(Register Reg)
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
EVT getMemoryVT() const
Return the type of the in-memory value.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
ArrayRef< int > getMask() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ 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...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Align getNonZeroOrigAlign() const
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)