28#include "llvm/IR/IntrinsicsLoongArch.h"
37#define DEBUG_TYPE "loongarch-isel-lowering"
42 cl::desc(
"Trap on integer division by zero."),
54 if (Subtarget.hasBasicF())
56 if (Subtarget.hasBasicD())
60 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
62 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
64 if (Subtarget.hasExtLSX())
68 if (Subtarget.hasExtLASX())
69 for (
MVT VT : LASXVTs)
169 if (Subtarget.hasBasicF()) {
193 if (!Subtarget.hasBasicD()) {
204 if (Subtarget.hasBasicD()) {
233 if (Subtarget.hasExtLSX()) {
248 for (
MVT VT : LSXVTs) {
261 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
276 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
278 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
280 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
284 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
304 if (Subtarget.hasExtLASX()) {
305 for (
MVT VT : LASXVTs) {
319 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
334 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
336 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
338 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
342 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
364 if (Subtarget.hasExtLSX())
387 if (Subtarget.hasLAMCAS())
390 if (Subtarget.hasSCQ()) {
407 switch (
Op.getOpcode()) {
409 return lowerATOMIC_FENCE(
Op, DAG);
411 return lowerEH_DWARF_CFA(
Op, DAG);
413 return lowerGlobalAddress(
Op, DAG);
415 return lowerGlobalTLSAddress(
Op, DAG);
417 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
419 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
421 return lowerINTRINSIC_VOID(
Op, DAG);
423 return lowerBlockAddress(
Op, DAG);
425 return lowerJumpTable(
Op, DAG);
427 return lowerShiftLeftParts(
Op, DAG);
429 return lowerShiftRightParts(
Op, DAG,
true);
431 return lowerShiftRightParts(
Op, DAG,
false);
433 return lowerConstantPool(
Op, DAG);
435 return lowerFP_TO_SINT(
Op, DAG);
437 return lowerBITCAST(
Op, DAG);
439 return lowerUINT_TO_FP(
Op, DAG);
441 return lowerSINT_TO_FP(
Op, DAG);
443 return lowerVASTART(
Op, DAG);
445 return lowerFRAMEADDR(
Op, DAG);
447 return lowerRETURNADDR(
Op, DAG);
449 return lowerWRITE_REGISTER(
Op, DAG);
451 return lowerINSERT_VECTOR_ELT(
Op, DAG);
453 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
455 return lowerBUILD_VECTOR(
Op, DAG);
457 return lowerVECTOR_SHUFFLE(
Op, DAG);
459 return lowerBITREVERSE(
Op, DAG);
461 return lowerSCALAR_TO_VECTOR(
Op, DAG);
467LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
470 MVT OpVT =
Op.getSimpleValueType();
481 EVT ResTy =
Op->getValueType(0);
492 for (
unsigned int i = 0; i < NewEltNum; i++) {
495 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
514 for (
unsigned int i = 0; i < NewEltNum; i++)
515 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
516 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
524template <
typename ValType>
527 unsigned CheckStride,
529 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
533 if (*
I != -1 && *
I != ExpectedIndex)
535 ExpectedIndex += ExpectedIndexStride;
539 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
558 for (
const auto &M : Mask) {
565 if (SplatIndex == -1)
568 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
569 if (fitsRegularPattern<int>(Mask.begin(), 1, Mask.end(), SplatIndex, 0)) {
570 APInt Imm(64, SplatIndex);
604 int SubMask[4] = {-1, -1, -1, -1};
605 for (
unsigned i = 0; i < 4; ++i) {
606 for (
unsigned j = i; j < Mask.size(); j += 4) {
613 if (Idx < 0 || Idx >= 4)
619 if (SubMask[i] == -1)
623 else if (
Idx != -1 &&
Idx != SubMask[i])
630 for (
int i = 3; i >= 0; --i) {
631 int Idx = SubMask[i];
663 const auto &Begin = Mask.begin();
664 const auto &
End = Mask.end();
665 SDValue OriV1 = V1, OriV2 = V2;
667 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 2))
669 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 2))
674 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 2))
676 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 2))
703 const auto &Begin = Mask.begin();
704 const auto &
End = Mask.end();
705 SDValue OriV1 = V1, OriV2 = V2;
707 if (fitsRegularPattern<int>(Begin, 2,
End, 1, 2))
709 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + 1, 2))
714 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 1, 2))
716 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + 1, 2))
744 const auto &Begin = Mask.begin();
745 const auto &
End = Mask.end();
746 unsigned HalfSize = Mask.size() / 2;
747 SDValue OriV1 = V1, OriV2 = V2;
749 if (fitsRegularPattern<int>(Begin, 2,
End, HalfSize, 1))
751 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size() + HalfSize, 1))
756 if (fitsRegularPattern<int>(Begin + 1, 2,
End, HalfSize, 1))
758 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size() + HalfSize,
787 const auto &Begin = Mask.begin();
788 const auto &
End = Mask.end();
789 SDValue OriV1 = V1, OriV2 = V2;
791 if (fitsRegularPattern<int>(Begin, 2,
End, 0, 1))
793 else if (fitsRegularPattern<int>(Begin, 2,
End, Mask.size(), 1))
798 if (fitsRegularPattern<int>(Begin + 1, 2,
End, 0, 1))
800 else if (fitsRegularPattern<int>(Begin + 1, 2,
End, Mask.size(), 1))
827 const auto &Begin = Mask.begin();
828 const auto &Mid = Mask.begin() + Mask.size() / 2;
829 const auto &
End = Mask.end();
830 SDValue OriV1 = V1, OriV2 = V2;
832 if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
834 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size(), 2))
839 if (fitsRegularPattern<int>(Mid, 1,
End, 0, 2))
841 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size(), 2))
869 const auto &Begin = Mask.begin();
870 const auto &Mid = Mask.begin() + Mask.size() / 2;
871 const auto &
End = Mask.end();
872 SDValue OriV1 = V1, OriV2 = V2;
874 if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
876 else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size() + 1, 2))
881 if (fitsRegularPattern<int>(Mid, 1,
End, 1, 2))
883 else if (fitsRegularPattern<int>(Mid, 1,
End, Mask.size() + 1, 2))
925 "Vector type is unsupported for lsx!");
927 "Two operands have different types!");
929 "Unexpected mask size for shuffle!");
930 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
978 for (
const auto &M : Mask) {
985 if (SplatIndex == -1)
988 const auto &Begin = Mask.begin();
989 const auto &
End = Mask.end();
990 unsigned HalfSize = Mask.size() / 2;
992 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
993 if (fitsRegularPattern<int>(Begin, 1,
End - HalfSize, SplatIndex, 0) &&
994 fitsRegularPattern<int>(Begin + HalfSize, 1,
End, SplatIndex + HalfSize,
996 APInt Imm(64, SplatIndex);
1010 if (Mask.size() <= 4)
1034 const auto &Begin = Mask.begin();
1035 const auto &
End = Mask.end();
1036 unsigned HalfSize = Mask.size() / 2;
1037 unsigned LeftSize = HalfSize / 2;
1038 SDValue OriV1 = V1, OriV2 = V2;
1040 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, HalfSize - LeftSize,
1042 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize + LeftSize, 1))
1044 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize,
1045 Mask.size() + HalfSize - LeftSize, 1) &&
1046 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
1047 Mask.size() + HalfSize + LeftSize, 1))
1052 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, HalfSize - LeftSize,
1054 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize + LeftSize,
1057 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize,
1058 Mask.size() + HalfSize - LeftSize, 1) &&
1059 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
1060 Mask.size() + HalfSize + LeftSize, 1))
1073 const auto &Begin = Mask.begin();
1074 const auto &
End = Mask.end();
1075 unsigned HalfSize = Mask.size() / 2;
1076 SDValue OriV1 = V1, OriV2 = V2;
1078 if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, 0, 1) &&
1079 fitsRegularPattern<int>(Begin + HalfSize, 2,
End, HalfSize, 1))
1081 else if (fitsRegularPattern<int>(Begin, 2,
End - HalfSize, Mask.size(), 1) &&
1082 fitsRegularPattern<int>(Begin + HalfSize, 2,
End,
1083 Mask.size() + HalfSize, 1))
1088 if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, 0, 1) &&
1089 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End, HalfSize, 1))
1091 else if (fitsRegularPattern<int>(Begin + 1, 2,
End - HalfSize, Mask.size(),
1093 fitsRegularPattern<int>(Begin + 1 + HalfSize, 2,
End,
1094 Mask.size() + HalfSize, 1))
1107 const auto &Begin = Mask.begin();
1108 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
1109 const auto &Mid = Mask.begin() + Mask.size() / 2;
1110 const auto &RightMid = Mask.end() - Mask.size() / 4;
1111 const auto &
End = Mask.end();
1112 unsigned HalfSize = Mask.size() / 2;
1113 SDValue OriV1 = V1, OriV2 = V2;
1115 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 0, 2) &&
1116 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize, 2))
1118 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size(), 2) &&
1119 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize, 2))
1124 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 0, 2) &&
1125 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize, 2))
1127 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size(), 2) &&
1128 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize, 2))
1142 const auto &Begin = Mask.begin();
1143 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
1144 const auto &Mid = Mask.begin() + Mask.size() / 2;
1145 const auto &RightMid = Mask.end() - Mask.size() / 4;
1146 const auto &
End = Mask.end();
1147 unsigned HalfSize = Mask.size() / 2;
1148 SDValue OriV1 = V1, OriV2 = V2;
1150 if (fitsRegularPattern<int>(Begin, 1, LeftMid, 1, 2) &&
1151 fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize + 1, 2))
1153 else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size() + 1, 2) &&
1154 fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize + 1,
1160 if (fitsRegularPattern<int>(LeftMid, 1, Mid, 1, 2) &&
1161 fitsRegularPattern<int>(RightMid, 1,
End, HalfSize + 1, 2))
1163 else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size() + 1, 2) &&
1164 fitsRegularPattern<int>(RightMid, 1,
End, Mask.size() + HalfSize + 1,
1178 int MaskSize = Mask.size();
1179 int HalfSize = Mask.size() / 2;
1180 const auto &Begin = Mask.begin();
1181 const auto &Mid = Mask.begin() + HalfSize;
1182 const auto &
End = Mask.end();
1194 for (
auto it = Begin; it < Mid; it++) {
1197 else if ((*it >= 0 && *it < HalfSize) ||
1198 (*it >= MaskSize && *it <= MaskSize + HalfSize)) {
1199 int M = *it < HalfSize ? *it : *it - HalfSize;
1204 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
1206 for (
auto it = Mid; it <
End; it++) {
1209 else if ((*it >= HalfSize && *it < MaskSize) ||
1210 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
1211 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
1216 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
1247 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
1249 int MaskSize = Mask.size();
1250 int HalfSize = Mask.size() / 2;
1252 HalfMaskType preMask =
None, postMask =
None;
1254 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
1255 return M < 0 || (M >= 0 && M < HalfSize) ||
1256 (M >= MaskSize && M < MaskSize + HalfSize);
1258 preMask = HighLaneTy;
1259 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
1260 return M < 0 || (M >= HalfSize && M < MaskSize) ||
1261 (M >= MaskSize + HalfSize && M < MaskSize * 2);
1263 preMask = LowLaneTy;
1265 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
1266 return M < 0 || (M >= 0 && M < HalfSize) ||
1267 (M >= MaskSize && M < MaskSize + HalfSize);
1269 postMask = HighLaneTy;
1270 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
1271 return M < 0 || (M >= HalfSize && M < MaskSize) ||
1272 (M >= MaskSize + HalfSize && M < MaskSize * 2);
1274 postMask = LowLaneTy;
1282 if (preMask == HighLaneTy && postMask == LowLaneTy) {
1285 if (preMask == LowLaneTy && postMask == HighLaneTy) {
1291 if (!V2.isUndef()) {
1298 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
1299 *it = *it < 0 ? *it : *it - HalfSize;
1301 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
1302 *it = *it < 0 ? *it : *it + HalfSize;
1304 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
1310 if (!V2.isUndef()) {
1317 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
1318 *it = *it < 0 ? *it : *it - HalfSize;
1320 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
1326 if (!V2.isUndef()) {
1333 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
1334 *it = *it < 0 ? *it : *it + HalfSize;
1350 "Vector type is unsupported for lasx!");
1352 "Two operands have different types!");
1354 "Unexpected mask size for shuffle!");
1355 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
1356 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
1401 MVT VT =
Op.getSimpleValueType();
1405 bool V1IsUndef = V1.
isUndef();
1406 bool V2IsUndef =
V2.isUndef();
1407 if (V1IsUndef && V2IsUndef)
1420 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
1422 for (
int &M : NewMask)
1423 if (M >= NumElements)
1429 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
1430 (void)MaskUpperLimit;
1432 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
1433 "Out of bounds shuffle index");
1448 if (isa<ConstantSDNode>(
Op))
1450 if (isa<ConstantFPSDNode>(
Op))
1465 EVT ResTy =
Op->getValueType(0);
1467 APInt SplatValue, SplatUndef;
1468 unsigned SplatBitSize;
1473 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
1474 (!Subtarget.hasExtLASX() || !Is256Vec))
1477 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
1479 SplatBitSize <= 64) {
1481 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
1487 switch (SplatBitSize) {
1491 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
1494 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
1497 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
1500 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
1508 if (ViaVecTy != ResTy)
1521 EVT ResTy =
Node->getValueType(0);
1527 for (
unsigned i = 0; i < NumElts; ++i) {
1529 Node->getOperand(i),
1539LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
1541 EVT VecTy =
Op->getOperand(0)->getValueType(0);
1546 if (isa<ConstantSDNode>(
Idx) &&
1547 (EltTy == MVT::i32 || EltTy == MVT::i64 || EltTy == MVT::f32 ||
1548 EltTy == MVT::f64 ||
Idx->getAsZExtVal() < NumElts / 2))
1555LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
1557 if (isa<ConstantSDNode>(
Op->getOperand(2)))
1581 if (Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
1583 "On LA64, only 64-bit registers can be written.");
1584 return Op.getOperand(0);
1587 if (!Subtarget.
is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
1589 "On LA32, only 32-bit registers can be written.");
1590 return Op.getOperand(0);
1598 if (!isa<ConstantSDNode>(
Op.getOperand(0))) {
1600 "be a constant integer");
1607 EVT VT =
Op.getValueType();
1610 unsigned Depth =
Op.getConstantOperandVal(0);
1611 int GRLenInBytes = Subtarget.
getGRLen() / 8;
1614 int Offset = -(GRLenInBytes * 2);
1629 if (
Op.getConstantOperandVal(0) != 0) {
1631 "return address can only be determined for the current frame");
1665 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
1673 !Subtarget.hasBasicD() &&
"unexpected target features");
1678 auto *
C = dyn_cast<ConstantSDNode>(Op0.
getOperand(1));
1679 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
1689 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLT(MVT::i32))
1693 EVT RetVT =
Op.getValueType();
1695 MakeLibCallOptions CallOptions;
1696 CallOptions.setTypeListBeforeSoften(OpVT, RetVT,
true);
1699 std::tie(Result, Chain) =
1707 !Subtarget.hasBasicD() &&
"unexpected target features");
1714 dyn_cast<VTSDNode>(Op0.
getOperand(1))->getVT().bitsLE(MVT::i32))
1718 EVT RetVT =
Op.getValueType();
1720 MakeLibCallOptions CallOptions;
1721 CallOptions.setTypeListBeforeSoften(OpVT, RetVT,
true);
1724 std::tie(Result, Chain) =
1735 if (
Op.getValueType() == MVT::f32 && Op0.
getValueType() == MVT::i32 &&
1736 Subtarget.
is64Bit() && Subtarget.hasBasicF()) {
1752 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
1753 !Subtarget.hasBasicD()) {
1777 N->getOffset(), Flags);
1785template <
class NodeTy>
1788 bool IsLocal)
const {
1799 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
1851 return getAddr(cast<BlockAddressSDNode>(
Op), DAG,
1857 return getAddr(cast<JumpTableSDNode>(
Op), DAG,
1863 return getAddr(cast<ConstantPoolSDNode>(
Op), DAG,
1870 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
1874 if (GV->
isDSOLocal() && isa<GlobalVariable>(GV)) {
1875 if (
auto GCM = dyn_cast<GlobalVariable>(GV)->
getCodeModel())
1884 unsigned Opc,
bool UseGOT,
1902 if (Opc == LoongArch::PseudoLA_TLS_LE && !Large)
1943 Args.push_back(Entry);
1975LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
1982 assert((!Large || Subtarget.
is64Bit()) &&
"Large code model requires LA64");
1985 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
1999 return getDynamicTLSAddr(
N, DAG,
2000 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
2001 : LoongArch::PseudoLA_TLS_GD,
2008 return getDynamicTLSAddr(
N, DAG,
2009 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
2010 : LoongArch::PseudoLA_TLS_LD,
2015 return getStaticTLSAddr(
N, DAG,
2016 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
2017 : LoongArch::PseudoLA_TLS_IE,
2024 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
2028 return getTLSDescAddr(
N, DAG,
2029 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
2030 : LoongArch::PseudoLA_TLS_DESC,
2034template <
unsigned N>
2037 auto *CImm = cast<ConstantSDNode>(
Op->getOperand(ImmOp));
2039 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
2040 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
2042 ": argument out of range.");
2049LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
2052 switch (
Op.getConstantOperandVal(0)) {
2055 case Intrinsic::thread_pointer: {
2059 case Intrinsic::loongarch_lsx_vpickve2gr_d:
2060 case Intrinsic::loongarch_lsx_vpickve2gr_du:
2061 case Intrinsic::loongarch_lsx_vreplvei_d:
2062 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
2063 return checkIntrinsicImmArg<1>(
Op, 2, DAG);
2064 case Intrinsic::loongarch_lsx_vreplvei_w:
2065 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
2066 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
2067 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
2068 case Intrinsic::loongarch_lasx_xvpickve_d:
2069 case Intrinsic::loongarch_lasx_xvpickve_d_f:
2070 return checkIntrinsicImmArg<2>(
Op, 2, DAG);
2071 case Intrinsic::loongarch_lasx_xvinsve0_d:
2072 return checkIntrinsicImmArg<2>(
Op, 3, DAG);
2073 case Intrinsic::loongarch_lsx_vsat_b:
2074 case Intrinsic::loongarch_lsx_vsat_bu:
2075 case Intrinsic::loongarch_lsx_vrotri_b:
2076 case Intrinsic::loongarch_lsx_vsllwil_h_b:
2077 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
2078 case Intrinsic::loongarch_lsx_vsrlri_b:
2079 case Intrinsic::loongarch_lsx_vsrari_b:
2080 case Intrinsic::loongarch_lsx_vreplvei_h:
2081 case Intrinsic::loongarch_lasx_xvsat_b:
2082 case Intrinsic::loongarch_lasx_xvsat_bu:
2083 case Intrinsic::loongarch_lasx_xvrotri_b:
2084 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
2085 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
2086 case Intrinsic::loongarch_lasx_xvsrlri_b:
2087 case Intrinsic::loongarch_lasx_xvsrari_b:
2088 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
2089 case Intrinsic::loongarch_lasx_xvpickve_w:
2090 case Intrinsic::loongarch_lasx_xvpickve_w_f:
2091 return checkIntrinsicImmArg<3>(
Op, 2, DAG);
2092 case Intrinsic::loongarch_lasx_xvinsve0_w:
2093 return checkIntrinsicImmArg<3>(
Op, 3, DAG);
2094 case Intrinsic::loongarch_lsx_vsat_h:
2095 case Intrinsic::loongarch_lsx_vsat_hu:
2096 case Intrinsic::loongarch_lsx_vrotri_h:
2097 case Intrinsic::loongarch_lsx_vsllwil_w_h:
2098 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
2099 case Intrinsic::loongarch_lsx_vsrlri_h:
2100 case Intrinsic::loongarch_lsx_vsrari_h:
2101 case Intrinsic::loongarch_lsx_vreplvei_b:
2102 case Intrinsic::loongarch_lasx_xvsat_h:
2103 case Intrinsic::loongarch_lasx_xvsat_hu:
2104 case Intrinsic::loongarch_lasx_xvrotri_h:
2105 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
2106 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
2107 case Intrinsic::loongarch_lasx_xvsrlri_h:
2108 case Intrinsic::loongarch_lasx_xvsrari_h:
2109 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
2110 return checkIntrinsicImmArg<4>(
Op, 2, DAG);
2111 case Intrinsic::loongarch_lsx_vsrlni_b_h:
2112 case Intrinsic::loongarch_lsx_vsrani_b_h:
2113 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
2114 case Intrinsic::loongarch_lsx_vsrarni_b_h:
2115 case Intrinsic::loongarch_lsx_vssrlni_b_h:
2116 case Intrinsic::loongarch_lsx_vssrani_b_h:
2117 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
2118 case Intrinsic::loongarch_lsx_vssrani_bu_h:
2119 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
2120 case Intrinsic::loongarch_lsx_vssrarni_b_h:
2121 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
2122 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
2123 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
2124 case Intrinsic::loongarch_lasx_xvsrani_b_h:
2125 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
2126 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
2127 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
2128 case Intrinsic::loongarch_lasx_xvssrani_b_h:
2129 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
2130 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
2131 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
2132 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
2133 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
2134 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
2135 return checkIntrinsicImmArg<4>(
Op, 3, DAG);
2136 case Intrinsic::loongarch_lsx_vsat_w:
2137 case Intrinsic::loongarch_lsx_vsat_wu:
2138 case Intrinsic::loongarch_lsx_vrotri_w:
2139 case Intrinsic::loongarch_lsx_vsllwil_d_w:
2140 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
2141 case Intrinsic::loongarch_lsx_vsrlri_w:
2142 case Intrinsic::loongarch_lsx_vsrari_w:
2143 case Intrinsic::loongarch_lsx_vslei_bu:
2144 case Intrinsic::loongarch_lsx_vslei_hu:
2145 case Intrinsic::loongarch_lsx_vslei_wu:
2146 case Intrinsic::loongarch_lsx_vslei_du:
2147 case Intrinsic::loongarch_lsx_vslti_bu:
2148 case Intrinsic::loongarch_lsx_vslti_hu:
2149 case Intrinsic::loongarch_lsx_vslti_wu:
2150 case Intrinsic::loongarch_lsx_vslti_du:
2151 case Intrinsic::loongarch_lsx_vbsll_v:
2152 case Intrinsic::loongarch_lsx_vbsrl_v:
2153 case Intrinsic::loongarch_lasx_xvsat_w:
2154 case Intrinsic::loongarch_lasx_xvsat_wu:
2155 case Intrinsic::loongarch_lasx_xvrotri_w:
2156 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
2157 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
2158 case Intrinsic::loongarch_lasx_xvsrlri_w:
2159 case Intrinsic::loongarch_lasx_xvsrari_w:
2160 case Intrinsic::loongarch_lasx_xvslei_bu:
2161 case Intrinsic::loongarch_lasx_xvslei_hu:
2162 case Intrinsic::loongarch_lasx_xvslei_wu:
2163 case Intrinsic::loongarch_lasx_xvslei_du:
2164 case Intrinsic::loongarch_lasx_xvslti_bu:
2165 case Intrinsic::loongarch_lasx_xvslti_hu:
2166 case Intrinsic::loongarch_lasx_xvslti_wu:
2167 case Intrinsic::loongarch_lasx_xvslti_du:
2168 case Intrinsic::loongarch_lasx_xvbsll_v:
2169 case Intrinsic::loongarch_lasx_xvbsrl_v:
2170 return checkIntrinsicImmArg<5>(
Op, 2, DAG);
2171 case Intrinsic::loongarch_lsx_vseqi_b:
2172 case Intrinsic::loongarch_lsx_vseqi_h:
2173 case Intrinsic::loongarch_lsx_vseqi_w:
2174 case Intrinsic::loongarch_lsx_vseqi_d:
2175 case Intrinsic::loongarch_lsx_vslei_b:
2176 case Intrinsic::loongarch_lsx_vslei_h:
2177 case Intrinsic::loongarch_lsx_vslei_w:
2178 case Intrinsic::loongarch_lsx_vslei_d:
2179 case Intrinsic::loongarch_lsx_vslti_b:
2180 case Intrinsic::loongarch_lsx_vslti_h:
2181 case Intrinsic::loongarch_lsx_vslti_w:
2182 case Intrinsic::loongarch_lsx_vslti_d:
2183 case Intrinsic::loongarch_lasx_xvseqi_b:
2184 case Intrinsic::loongarch_lasx_xvseqi_h:
2185 case Intrinsic::loongarch_lasx_xvseqi_w:
2186 case Intrinsic::loongarch_lasx_xvseqi_d:
2187 case Intrinsic::loongarch_lasx_xvslei_b:
2188 case Intrinsic::loongarch_lasx_xvslei_h:
2189 case Intrinsic::loongarch_lasx_xvslei_w:
2190 case Intrinsic::loongarch_lasx_xvslei_d:
2191 case Intrinsic::loongarch_lasx_xvslti_b:
2192 case Intrinsic::loongarch_lasx_xvslti_h:
2193 case Intrinsic::loongarch_lasx_xvslti_w:
2194 case Intrinsic::loongarch_lasx_xvslti_d:
2195 return checkIntrinsicImmArg<5>(
Op, 2, DAG,
true);
2196 case Intrinsic::loongarch_lsx_vsrlni_h_w:
2197 case Intrinsic::loongarch_lsx_vsrani_h_w:
2198 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
2199 case Intrinsic::loongarch_lsx_vsrarni_h_w:
2200 case Intrinsic::loongarch_lsx_vssrlni_h_w:
2201 case Intrinsic::loongarch_lsx_vssrani_h_w:
2202 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
2203 case Intrinsic::loongarch_lsx_vssrani_hu_w:
2204 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
2205 case Intrinsic::loongarch_lsx_vssrarni_h_w:
2206 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
2207 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
2208 case Intrinsic::loongarch_lsx_vfrstpi_b:
2209 case Intrinsic::loongarch_lsx_vfrstpi_h:
2210 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
2211 case Intrinsic::loongarch_lasx_xvsrani_h_w:
2212 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
2213 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
2214 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
2215 case Intrinsic::loongarch_lasx_xvssrani_h_w:
2216 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
2217 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
2218 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
2219 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
2220 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
2221 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
2222 case Intrinsic::loongarch_lasx_xvfrstpi_b:
2223 case Intrinsic::loongarch_lasx_xvfrstpi_h:
2224 return checkIntrinsicImmArg<5>(
Op, 3, DAG);
2225 case Intrinsic::loongarch_lsx_vsat_d:
2226 case Intrinsic::loongarch_lsx_vsat_du:
2227 case Intrinsic::loongarch_lsx_vrotri_d:
2228 case Intrinsic::loongarch_lsx_vsrlri_d:
2229 case Intrinsic::loongarch_lsx_vsrari_d:
2230 case Intrinsic::loongarch_lasx_xvsat_d:
2231 case Intrinsic::loongarch_lasx_xvsat_du:
2232 case Intrinsic::loongarch_lasx_xvrotri_d:
2233 case Intrinsic::loongarch_lasx_xvsrlri_d:
2234 case Intrinsic::loongarch_lasx_xvsrari_d:
2235 return checkIntrinsicImmArg<6>(
Op, 2, DAG);
2236 case Intrinsic::loongarch_lsx_vsrlni_w_d:
2237 case Intrinsic::loongarch_lsx_vsrani_w_d:
2238 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
2239 case Intrinsic::loongarch_lsx_vsrarni_w_d:
2240 case Intrinsic::loongarch_lsx_vssrlni_w_d:
2241 case Intrinsic::loongarch_lsx_vssrani_w_d:
2242 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
2243 case Intrinsic::loongarch_lsx_vssrani_wu_d:
2244 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
2245 case Intrinsic::loongarch_lsx_vssrarni_w_d:
2246 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
2247 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
2248 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
2249 case Intrinsic::loongarch_lasx_xvsrani_w_d:
2250 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
2251 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
2252 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
2253 case Intrinsic::loongarch_lasx_xvssrani_w_d:
2254 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
2255 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
2256 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
2257 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
2258 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
2259 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
2260 return checkIntrinsicImmArg<6>(
Op, 3, DAG);
2261 case Intrinsic::loongarch_lsx_vsrlni_d_q:
2262 case Intrinsic::loongarch_lsx_vsrani_d_q:
2263 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
2264 case Intrinsic::loongarch_lsx_vsrarni_d_q:
2265 case Intrinsic::loongarch_lsx_vssrlni_d_q:
2266 case Intrinsic::loongarch_lsx_vssrani_d_q:
2267 case Intrinsic::loongarch_lsx_vssrlni_du_q:
2268 case Intrinsic::loongarch_lsx_vssrani_du_q:
2269 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
2270 case Intrinsic::loongarch_lsx_vssrarni_d_q:
2271 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
2272 case Intrinsic::loongarch_lsx_vssrarni_du_q:
2273 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
2274 case Intrinsic::loongarch_lasx_xvsrani_d_q:
2275 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
2276 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
2277 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
2278 case Intrinsic::loongarch_lasx_xvssrani_d_q:
2279 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
2280 case Intrinsic::loongarch_lasx_xvssrani_du_q:
2281 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
2282 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
2283 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
2284 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
2285 return checkIntrinsicImmArg<7>(
Op, 3, DAG);
2286 case Intrinsic::loongarch_lsx_vnori_b:
2287 case Intrinsic::loongarch_lsx_vshuf4i_b:
2288 case Intrinsic::loongarch_lsx_vshuf4i_h:
2289 case Intrinsic::loongarch_lsx_vshuf4i_w:
2290 case Intrinsic::loongarch_lasx_xvnori_b:
2291 case Intrinsic::loongarch_lasx_xvshuf4i_b:
2292 case Intrinsic::loongarch_lasx_xvshuf4i_h:
2293 case Intrinsic::loongarch_lasx_xvshuf4i_w:
2294 case Intrinsic::loongarch_lasx_xvpermi_d:
2295 return checkIntrinsicImmArg<8>(
Op, 2, DAG);
2296 case Intrinsic::loongarch_lsx_vshuf4i_d:
2297 case Intrinsic::loongarch_lsx_vpermi_w:
2298 case Intrinsic::loongarch_lsx_vbitseli_b:
2299 case Intrinsic::loongarch_lsx_vextrins_b:
2300 case Intrinsic::loongarch_lsx_vextrins_h:
2301 case Intrinsic::loongarch_lsx_vextrins_w:
2302 case Intrinsic::loongarch_lsx_vextrins_d:
2303 case Intrinsic::loongarch_lasx_xvshuf4i_d:
2304 case Intrinsic::loongarch_lasx_xvpermi_w:
2305 case Intrinsic::loongarch_lasx_xvpermi_q:
2306 case Intrinsic::loongarch_lasx_xvbitseli_b:
2307 case Intrinsic::loongarch_lasx_xvextrins_b:
2308 case Intrinsic::loongarch_lasx_xvextrins_h:
2309 case Intrinsic::loongarch_lasx_xvextrins_w:
2310 case Intrinsic::loongarch_lasx_xvextrins_d:
2311 return checkIntrinsicImmArg<8>(
Op, 3, DAG);
2312 case Intrinsic::loongarch_lsx_vrepli_b:
2313 case Intrinsic::loongarch_lsx_vrepli_h:
2314 case Intrinsic::loongarch_lsx_vrepli_w:
2315 case Intrinsic::loongarch_lsx_vrepli_d:
2316 case Intrinsic::loongarch_lasx_xvrepli_b:
2317 case Intrinsic::loongarch_lasx_xvrepli_h:
2318 case Intrinsic::loongarch_lasx_xvrepli_w:
2319 case Intrinsic::loongarch_lasx_xvrepli_d:
2320 return checkIntrinsicImmArg<10>(
Op, 1, DAG,
true);
2321 case Intrinsic::loongarch_lsx_vldi:
2322 case Intrinsic::loongarch_lasx_xvldi:
2323 return checkIntrinsicImmArg<13>(
Op, 1, DAG,
true);
2338LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
2342 EVT VT =
Op.getValueType();
2344 const StringRef ErrorMsgOOR =
"argument out of range";
2345 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
2346 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
2348 switch (
Op.getConstantOperandVal(1)) {
2351 case Intrinsic::loongarch_crc_w_b_w:
2352 case Intrinsic::loongarch_crc_w_h_w:
2353 case Intrinsic::loongarch_crc_w_w_w:
2354 case Intrinsic::loongarch_crc_w_d_w:
2355 case Intrinsic::loongarch_crcc_w_b_w:
2356 case Intrinsic::loongarch_crcc_w_h_w:
2357 case Intrinsic::loongarch_crcc_w_w_w:
2358 case Intrinsic::loongarch_crcc_w_d_w:
2360 case Intrinsic::loongarch_csrrd_w:
2361 case Intrinsic::loongarch_csrrd_d: {
2362 unsigned Imm =
Op.getConstantOperandVal(2);
2363 return !isUInt<14>(Imm)
2368 case Intrinsic::loongarch_csrwr_w:
2369 case Intrinsic::loongarch_csrwr_d: {
2370 unsigned Imm =
Op.getConstantOperandVal(3);
2371 return !isUInt<14>(Imm)
2374 {Chain,
Op.getOperand(2),
2377 case Intrinsic::loongarch_csrxchg_w:
2378 case Intrinsic::loongarch_csrxchg_d: {
2379 unsigned Imm =
Op.getConstantOperandVal(4);
2380 return !isUInt<14>(Imm)
2383 {Chain,
Op.getOperand(2),
Op.getOperand(3),
2386 case Intrinsic::loongarch_iocsrrd_d: {
2391#define IOCSRRD_CASE(NAME, NODE) \
2392 case Intrinsic::loongarch_##NAME: { \
2393 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
2394 {Chain, Op.getOperand(2)}); \
2400 case Intrinsic::loongarch_cpucfg: {
2402 {Chain,
Op.getOperand(2)});
2404 case Intrinsic::loongarch_lddir_d: {
2405 unsigned Imm =
Op.getConstantOperandVal(3);
2406 return !isUInt<8>(Imm)
2410 case Intrinsic::loongarch_movfcsr2gr: {
2411 if (!Subtarget.hasBasicF())
2413 unsigned Imm =
Op.getConstantOperandVal(2);
2414 return !isUInt<2>(Imm)
2419 case Intrinsic::loongarch_lsx_vld:
2420 case Intrinsic::loongarch_lsx_vldrepl_b:
2421 case Intrinsic::loongarch_lasx_xvld:
2422 case Intrinsic::loongarch_lasx_xvldrepl_b:
2423 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
2426 case Intrinsic::loongarch_lsx_vldrepl_h:
2427 case Intrinsic::loongarch_lasx_xvldrepl_h:
2428 return !isShiftedInt<11, 1>(
2429 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
2431 Op,
"argument out of range or not a multiple of 2", DAG)
2433 case Intrinsic::loongarch_lsx_vldrepl_w:
2434 case Intrinsic::loongarch_lasx_xvldrepl_w:
2435 return !isShiftedInt<10, 2>(
2436 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
2438 Op,
"argument out of range or not a multiple of 4", DAG)
2440 case Intrinsic::loongarch_lsx_vldrepl_d:
2441 case Intrinsic::loongarch_lasx_xvldrepl_d:
2442 return !isShiftedInt<9, 3>(
2443 cast<ConstantSDNode>(
Op.getOperand(3))->getSExtValue())
2445 Op,
"argument out of range or not a multiple of 8", DAG)
2456 return Op.getOperand(0);
2464 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
2466 const StringRef ErrorMsgOOR =
"argument out of range";
2467 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
2468 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
2469 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
2471 switch (IntrinsicEnum) {
2475 case Intrinsic::loongarch_cacop_d:
2476 case Intrinsic::loongarch_cacop_w: {
2477 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.
is64Bit())
2479 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.
is64Bit())
2483 int Imm2 = cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue();
2484 if (!isUInt<5>(Imm1) || !isInt<12>(Imm2))
2488 case Intrinsic::loongarch_dbar: {
2490 return !isUInt<15>(Imm)
2495 case Intrinsic::loongarch_ibar: {
2497 return !isUInt<15>(Imm)
2502 case Intrinsic::loongarch_break: {
2504 return !isUInt<15>(Imm)
2509 case Intrinsic::loongarch_movgr2fcsr: {
2510 if (!Subtarget.hasBasicF())
2513 return !isUInt<2>(Imm)
2520 case Intrinsic::loongarch_syscall: {
2522 return !isUInt<15>(Imm)
2527#define IOCSRWR_CASE(NAME, NODE) \
2528 case Intrinsic::loongarch_##NAME: { \
2529 SDValue Op3 = Op.getOperand(3); \
2530 return Subtarget.is64Bit() \
2531 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
2532 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
2533 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
2534 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
2541 case Intrinsic::loongarch_iocsrwr_d: {
2549#define ASRT_LE_GT_CASE(NAME) \
2550 case Intrinsic::loongarch_##NAME: { \
2551 return !Subtarget.is64Bit() \
2552 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
2557#undef ASRT_LE_GT_CASE
2558 case Intrinsic::loongarch_ldpte_d: {
2559 unsigned Imm =
Op.getConstantOperandVal(3);
2565 case Intrinsic::loongarch_lsx_vst:
2566 case Intrinsic::loongarch_lasx_xvst:
2567 return !isInt<12>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue())
2570 case Intrinsic::loongarch_lasx_xvstelm_b:
2571 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2572 !isUInt<5>(
Op.getConstantOperandVal(5)))
2575 case Intrinsic::loongarch_lsx_vstelm_b:
2576 return (!isInt<8>(cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2577 !isUInt<4>(
Op.getConstantOperandVal(5)))
2580 case Intrinsic::loongarch_lasx_xvstelm_h:
2581 return (!isShiftedInt<8, 1>(
2582 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2583 !isUInt<4>(
Op.getConstantOperandVal(5)))
2585 Op,
"argument out of range or not a multiple of 2", DAG)
2587 case Intrinsic::loongarch_lsx_vstelm_h:
2588 return (!isShiftedInt<8, 1>(
2589 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2590 !isUInt<3>(
Op.getConstantOperandVal(5)))
2592 Op,
"argument out of range or not a multiple of 2", DAG)
2594 case Intrinsic::loongarch_lasx_xvstelm_w:
2595 return (!isShiftedInt<8, 2>(
2596 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2597 !isUInt<3>(
Op.getConstantOperandVal(5)))
2599 Op,
"argument out of range or not a multiple of 4", DAG)
2601 case Intrinsic::loongarch_lsx_vstelm_w:
2602 return (!isShiftedInt<8, 2>(
2603 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2604 !isUInt<2>(
Op.getConstantOperandVal(5)))
2606 Op,
"argument out of range or not a multiple of 4", DAG)
2608 case Intrinsic::loongarch_lasx_xvstelm_d:
2609 return (!isShiftedInt<8, 3>(
2610 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2611 !isUInt<2>(
Op.getConstantOperandVal(5)))
2613 Op,
"argument out of range or not a multiple of 8", DAG)
2615 case Intrinsic::loongarch_lsx_vstelm_d:
2616 return (!isShiftedInt<8, 3>(
2617 cast<ConstantSDNode>(
Op.getOperand(4))->getSExtValue()) ||
2618 !isUInt<1>(
Op.getConstantOperandVal(5)))
2620 Op,
"argument out of range or not a multiple of 8", DAG)
2631 EVT VT =
Lo.getValueType();
2672 EVT VT =
Lo.getValueType();
2764 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
2765 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
2769 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
2775 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
2802 StringRef ErrorMsg,
bool WithChain =
true) {
2807 Results.push_back(
N->getOperand(0));
2810template <
unsigned N>
2815 const StringRef ErrorMsgOOR =
"argument out of range";
2816 unsigned Imm =
Node->getConstantOperandVal(2);
2817 if (!isUInt<N>(Imm)) {
2850 switch (
N->getConstantOperandVal(0)) {
2853 case Intrinsic::loongarch_lsx_vpickve2gr_b:
2854 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
2857 case Intrinsic::loongarch_lsx_vpickve2gr_h:
2858 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
2859 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
2862 case Intrinsic::loongarch_lsx_vpickve2gr_w:
2863 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
2866 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
2867 replaceVPICKVE2GRResults<4>(
N,
Results, DAG, Subtarget,
2870 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
2871 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
2872 replaceVPICKVE2GRResults<3>(
N,
Results, DAG, Subtarget,
2875 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
2876 replaceVPICKVE2GRResults<2>(
N,
Results, DAG, Subtarget,
2879 case Intrinsic::loongarch_lsx_bz_b:
2880 case Intrinsic::loongarch_lsx_bz_h:
2881 case Intrinsic::loongarch_lsx_bz_w:
2882 case Intrinsic::loongarch_lsx_bz_d:
2883 case Intrinsic::loongarch_lasx_xbz_b:
2884 case Intrinsic::loongarch_lasx_xbz_h:
2885 case Intrinsic::loongarch_lasx_xbz_w:
2886 case Intrinsic::loongarch_lasx_xbz_d:
2890 case Intrinsic::loongarch_lsx_bz_v:
2891 case Intrinsic::loongarch_lasx_xbz_v:
2895 case Intrinsic::loongarch_lsx_bnz_b:
2896 case Intrinsic::loongarch_lsx_bnz_h:
2897 case Intrinsic::loongarch_lsx_bnz_w:
2898 case Intrinsic::loongarch_lsx_bnz_d:
2899 case Intrinsic::loongarch_lasx_xbnz_b:
2900 case Intrinsic::loongarch_lasx_xbnz_h:
2901 case Intrinsic::loongarch_lasx_xbnz_w:
2902 case Intrinsic::loongarch_lasx_xbnz_d:
2906 case Intrinsic::loongarch_lsx_bnz_v:
2907 case Intrinsic::loongarch_lasx_xbnz_v:
2917 assert(
N->getValueType(0) == MVT::i128 &&
2918 "AtomicCmpSwap on types less than 128 should be legal");
2922 switch (
MemOp->getMergedOrdering()) {
2926 Opcode = LoongArch::PseudoCmpXchg128Acquire;
2930 Opcode = LoongArch::PseudoCmpXchg128;
2937 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
2938 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
2939 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
2940 NewVal.first, NewVal.second,
N->getOperand(0)};
2943 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
2954 EVT VT =
N->getValueType(0);
2955 switch (
N->getOpcode()) {
2961 "Unexpected custom legalisation");
2969 "Unexpected custom legalisation");
2971 Subtarget.hasDiv32() && VT == MVT::i32
2979 "Unexpected custom legalisation");
2988 "Unexpected custom legalisation");
2993 "Unexpected custom legalisation");
2998 if (Src.getValueType() == MVT::f16)
3009 EVT OpVT = Src.getValueType();
3013 std::tie(Result, Chain) =
3020 EVT SrcVT = Src.getValueType();
3021 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.
is64Bit() &&
3022 Subtarget.hasBasicF()) {
3031 "Unexpected custom legalisation");
3034 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
3040 assert((VT == MVT::i16 || VT == MVT::i32) &&
3041 "Unexpected custom legalization");
3062 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
3063 "Unexpected custom legalization");
3083 "Unexpected custom legalisation");
3091 const StringRef ErrorMsgOOR =
"argument out of range";
3092 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
3093 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
3095 switch (
N->getConstantOperandVal(1)) {
3098 case Intrinsic::loongarch_movfcsr2gr: {
3099 if (!Subtarget.hasBasicF()) {
3104 if (!isUInt<2>(Imm)) {
3116#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
3117 case Intrinsic::loongarch_##NAME: { \
3118 SDValue NODE = DAG.getNode( \
3119 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
3120 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
3121 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
3122 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
3123 Results.push_back(NODE.getValue(1)); \
3132#undef CRC_CASE_EXT_BINARYOP
3134#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
3135 case Intrinsic::loongarch_##NAME: { \
3136 SDValue NODE = DAG.getNode( \
3137 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
3139 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
3140 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
3141 Results.push_back(NODE.getValue(1)); \
3146#undef CRC_CASE_EXT_UNARYOP
3147#define CSR_CASE(ID) \
3148 case Intrinsic::loongarch_##ID: { \
3149 if (!Subtarget.is64Bit()) \
3150 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
3158 case Intrinsic::loongarch_csrrd_w: {
3160 if (!isUInt<14>(Imm)) {
3172 case Intrinsic::loongarch_csrwr_w: {
3173 unsigned Imm =
N->getConstantOperandVal(3);
3174 if (!isUInt<14>(Imm)) {
3187 case Intrinsic::loongarch_csrxchg_w: {
3188 unsigned Imm =
N->getConstantOperandVal(4);
3189 if (!isUInt<14>(Imm)) {
3203#define IOCSRRD_CASE(NAME, NODE) \
3204 case Intrinsic::loongarch_##NAME: { \
3205 SDValue IOCSRRDResults = \
3206 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
3207 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
3208 Results.push_back( \
3209 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
3210 Results.push_back(IOCSRRDResults.getValue(1)); \
3217 case Intrinsic::loongarch_cpucfg: {
3226 case Intrinsic::loongarch_lddir_d: {
3239 "On LA64, only 64-bit registers can be read.");
3242 "On LA32, only 32-bit registers can be read.");
3244 Results.push_back(
N->getOperand(0));
3255 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
3276 SDValue FirstOperand =
N->getOperand(0);
3277 SDValue SecondOperand =
N->getOperand(1);
3278 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
3279 EVT ValTy =
N->getValueType(0);
3282 unsigned SMIdx, SMLen;
3288 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||
3299 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))))
3340 NewOperand = FirstOperand;
3343 msb = lsb + SMLen - 1;
3347 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
3368 SDValue FirstOperand =
N->getOperand(0);
3370 EVT ValTy =
N->getValueType(0);
3373 unsigned MaskIdx, MaskLen;
3379 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.
getOperand(1))) ||
3384 if (!(CN = dyn_cast<ConstantSDNode>(
N->getOperand(1))))
3388 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
3401 EVT ValTy =
N->getValueType(0);
3402 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
3406 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
3408 bool SwapAndRetried =
false;
3413 if (ValBits != 32 && ValBits != 64)
3423 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
3426 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3428 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
3429 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
3431 (MaskIdx0 + MaskLen0 <= ValBits)) {
3445 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
3448 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3450 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
3452 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
3453 (MaskIdx0 + MaskLen0 <= ValBits)) {
3468 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
3470 (MaskIdx0 + MaskLen0 <= 64) &&
3471 (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) &&
3478 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
3479 : (MaskIdx0 + MaskLen0 - 1),
3491 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
3493 MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3495 (MaskIdx0 + MaskLen0 <= ValBits)) {
3510 (CN0 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) &&
3512 (CN1 = dyn_cast<ConstantSDNode>(N1)) &&
3518 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
3519 : (MaskIdx0 + MaskLen0 - 1),
3534 unsigned MaskIdx, MaskLen;
3535 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
3536 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
3538 MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3560 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3562 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
3563 (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
3576 if (!SwapAndRetried) {
3578 SwapAndRetried =
true;
3582 SwapAndRetried =
false;
3594 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
3608 if (!SwapAndRetried) {
3610 SwapAndRetried =
true;
3620 switch (V.getNode()->getOpcode()) {
3622 LoadSDNode *LoadNode = cast<LoadSDNode>(V.getNode());
3631 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
3632 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
3639 VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));
3640 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
3717 SDNode *AndNode =
N->getOperand(0).getNode();
3725 SDValue CmpInputValue =
N->getOperand(1);
3733 CN = dyn_cast<ConstantSDNode>(CmpInputValue);
3736 AndInputValue1 = AndInputValue1.
getOperand(0);
3740 if (AndInputValue2 != CmpInputValue)
3773 TruncInputValue1, TruncInputValue2);
3795template <
unsigned N>
3799 bool IsSigned =
false) {
3801 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
3803 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
3804 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
3806 ": argument out of range.");
3812template <
unsigned N>
3816 EVT ResTy =
Node->getValueType(0);
3817 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(ImmOp));
3820 if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||
3821 (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {
3823 ": argument out of range.");
3828 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
3834 EVT ResTy =
Node->getValueType(0);
3842 EVT ResTy =
Node->getValueType(0);
3851template <
unsigned N>
3854 EVT ResTy =
Node->getValueType(0);
3855 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
3857 if (!isUInt<N>(CImm->getZExtValue())) {
3859 ": argument out of range.");
3869template <
unsigned N>
3872 EVT ResTy =
Node->getValueType(0);
3873 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
3875 if (!isUInt<N>(CImm->getZExtValue())) {
3877 ": argument out of range.");
3886template <
unsigned N>
3889 EVT ResTy =
Node->getValueType(0);
3890 auto *CImm = cast<ConstantSDNode>(
Node->getOperand(2));
3892 if (!isUInt<N>(CImm->getZExtValue())) {
3894 ": argument out of range.");
3908 switch (
N->getConstantOperandVal(0)) {
3911 case Intrinsic::loongarch_lsx_vadd_b:
3912 case Intrinsic::loongarch_lsx_vadd_h:
3913 case Intrinsic::loongarch_lsx_vadd_w:
3914 case Intrinsic::loongarch_lsx_vadd_d:
3915 case Intrinsic::loongarch_lasx_xvadd_b:
3916 case Intrinsic::loongarch_lasx_xvadd_h:
3917 case Intrinsic::loongarch_lasx_xvadd_w:
3918 case Intrinsic::loongarch_lasx_xvadd_d:
3921 case Intrinsic::loongarch_lsx_vaddi_bu:
3922 case Intrinsic::loongarch_lsx_vaddi_hu:
3923 case Intrinsic::loongarch_lsx_vaddi_wu:
3924 case Intrinsic::loongarch_lsx_vaddi_du:
3925 case Intrinsic::loongarch_lasx_xvaddi_bu:
3926 case Intrinsic::loongarch_lasx_xvaddi_hu:
3927 case Intrinsic::loongarch_lasx_xvaddi_wu:
3928 case Intrinsic::loongarch_lasx_xvaddi_du:
3930 lowerVectorSplatImm<5>(
N, 2, DAG));
3931 case Intrinsic::loongarch_lsx_vsub_b:
3932 case Intrinsic::loongarch_lsx_vsub_h:
3933 case Intrinsic::loongarch_lsx_vsub_w:
3934 case Intrinsic::loongarch_lsx_vsub_d:
3935 case Intrinsic::loongarch_lasx_xvsub_b:
3936 case Intrinsic::loongarch_lasx_xvsub_h:
3937 case Intrinsic::loongarch_lasx_xvsub_w:
3938 case Intrinsic::loongarch_lasx_xvsub_d:
3941 case Intrinsic::loongarch_lsx_vsubi_bu:
3942 case Intrinsic::loongarch_lsx_vsubi_hu:
3943 case Intrinsic::loongarch_lsx_vsubi_wu:
3944 case Intrinsic::loongarch_lsx_vsubi_du:
3945 case Intrinsic::loongarch_lasx_xvsubi_bu:
3946 case Intrinsic::loongarch_lasx_xvsubi_hu:
3947 case Intrinsic::loongarch_lasx_xvsubi_wu:
3948 case Intrinsic::loongarch_lasx_xvsubi_du:
3950 lowerVectorSplatImm<5>(
N, 2, DAG));
3951 case Intrinsic::loongarch_lsx_vneg_b:
3952 case Intrinsic::loongarch_lsx_vneg_h:
3953 case Intrinsic::loongarch_lsx_vneg_w:
3954 case Intrinsic::loongarch_lsx_vneg_d:
3955 case Intrinsic::loongarch_lasx_xvneg_b:
3956 case Intrinsic::loongarch_lasx_xvneg_h:
3957 case Intrinsic::loongarch_lasx_xvneg_w:
3958 case Intrinsic::loongarch_lasx_xvneg_d:
3962 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
3964 SDLoc(
N),
N->getValueType(0)),
3966 case Intrinsic::loongarch_lsx_vmax_b:
3967 case Intrinsic::loongarch_lsx_vmax_h:
3968 case Intrinsic::loongarch_lsx_vmax_w:
3969 case Intrinsic::loongarch_lsx_vmax_d:
3970 case Intrinsic::loongarch_lasx_xvmax_b:
3971 case Intrinsic::loongarch_lasx_xvmax_h:
3972 case Intrinsic::loongarch_lasx_xvmax_w:
3973 case Intrinsic::loongarch_lasx_xvmax_d:
3976 case Intrinsic::loongarch_lsx_vmax_bu:
3977 case Intrinsic::loongarch_lsx_vmax_hu:
3978 case Intrinsic::loongarch_lsx_vmax_wu:
3979 case Intrinsic::loongarch_lsx_vmax_du:
3980 case Intrinsic::loongarch_lasx_xvmax_bu:
3981 case Intrinsic::loongarch_lasx_xvmax_hu:
3982 case Intrinsic::loongarch_lasx_xvmax_wu:
3983 case Intrinsic::loongarch_lasx_xvmax_du:
3986 case Intrinsic::loongarch_lsx_vmaxi_b:
3987 case Intrinsic::loongarch_lsx_vmaxi_h:
3988 case Intrinsic::loongarch_lsx_vmaxi_w:
3989 case Intrinsic::loongarch_lsx_vmaxi_d:
3990 case Intrinsic::loongarch_lasx_xvmaxi_b:
3991 case Intrinsic::loongarch_lasx_xvmaxi_h:
3992 case Intrinsic::loongarch_lasx_xvmaxi_w:
3993 case Intrinsic::loongarch_lasx_xvmaxi_d:
3995 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
3996 case Intrinsic::loongarch_lsx_vmaxi_bu:
3997 case Intrinsic::loongarch_lsx_vmaxi_hu:
3998 case Intrinsic::loongarch_lsx_vmaxi_wu:
3999 case Intrinsic::loongarch_lsx_vmaxi_du:
4000 case Intrinsic::loongarch_lasx_xvmaxi_bu:
4001 case Intrinsic::loongarch_lasx_xvmaxi_hu:
4002 case Intrinsic::loongarch_lasx_xvmaxi_wu:
4003 case Intrinsic::loongarch_lasx_xvmaxi_du:
4005 lowerVectorSplatImm<5>(
N, 2, DAG));
4006 case Intrinsic::loongarch_lsx_vmin_b:
4007 case Intrinsic::loongarch_lsx_vmin_h:
4008 case Intrinsic::loongarch_lsx_vmin_w:
4009 case Intrinsic::loongarch_lsx_vmin_d:
4010 case Intrinsic::loongarch_lasx_xvmin_b:
4011 case Intrinsic::loongarch_lasx_xvmin_h:
4012 case Intrinsic::loongarch_lasx_xvmin_w:
4013 case Intrinsic::loongarch_lasx_xvmin_d:
4016 case Intrinsic::loongarch_lsx_vmin_bu:
4017 case Intrinsic::loongarch_lsx_vmin_hu:
4018 case Intrinsic::loongarch_lsx_vmin_wu:
4019 case Intrinsic::loongarch_lsx_vmin_du:
4020 case Intrinsic::loongarch_lasx_xvmin_bu:
4021 case Intrinsic::loongarch_lasx_xvmin_hu:
4022 case Intrinsic::loongarch_lasx_xvmin_wu:
4023 case Intrinsic::loongarch_lasx_xvmin_du:
4026 case Intrinsic::loongarch_lsx_vmini_b:
4027 case Intrinsic::loongarch_lsx_vmini_h:
4028 case Intrinsic::loongarch_lsx_vmini_w:
4029 case Intrinsic::loongarch_lsx_vmini_d:
4030 case Intrinsic::loongarch_lasx_xvmini_b:
4031 case Intrinsic::loongarch_lasx_xvmini_h:
4032 case Intrinsic::loongarch_lasx_xvmini_w:
4033 case Intrinsic::loongarch_lasx_xvmini_d:
4035 lowerVectorSplatImm<5>(
N, 2, DAG,
true));
4036 case Intrinsic::loongarch_lsx_vmini_bu:
4037 case Intrinsic::loongarch_lsx_vmini_hu:
4038 case Intrinsic::loongarch_lsx_vmini_wu:
4039 case Intrinsic::loongarch_lsx_vmini_du:
4040 case Intrinsic::loongarch_lasx_xvmini_bu:
4041 case Intrinsic::loongarch_lasx_xvmini_hu:
4042 case Intrinsic::loongarch_lasx_xvmini_wu:
4043 case Intrinsic::loongarch_lasx_xvmini_du:
4045 lowerVectorSplatImm<5>(
N, 2, DAG));
4046 case Intrinsic::loongarch_lsx_vmul_b:
4047 case Intrinsic::loongarch_lsx_vmul_h:
4048 case Intrinsic::loongarch_lsx_vmul_w:
4049 case Intrinsic::loongarch_lsx_vmul_d:
4050 case Intrinsic::loongarch_lasx_xvmul_b:
4051 case Intrinsic::loongarch_lasx_xvmul_h:
4052 case Intrinsic::loongarch_lasx_xvmul_w:
4053 case Intrinsic::loongarch_lasx_xvmul_d:
4056 case Intrinsic::loongarch_lsx_vmadd_b:
4057 case Intrinsic::loongarch_lsx_vmadd_h:
4058 case Intrinsic::loongarch_lsx_vmadd_w:
4059 case Intrinsic::loongarch_lsx_vmadd_d:
4060 case Intrinsic::loongarch_lasx_xvmadd_b:
4061 case Intrinsic::loongarch_lasx_xvmadd_h:
4062 case Intrinsic::loongarch_lasx_xvmadd_w:
4063 case Intrinsic::loongarch_lasx_xvmadd_d: {
4064 EVT ResTy =
N->getValueType(0);
4069 case Intrinsic::loongarch_lsx_vmsub_b:
4070 case Intrinsic::loongarch_lsx_vmsub_h:
4071 case Intrinsic::loongarch_lsx_vmsub_w:
4072 case Intrinsic::loongarch_lsx_vmsub_d:
4073 case Intrinsic::loongarch_lasx_xvmsub_b:
4074 case Intrinsic::loongarch_lasx_xvmsub_h:
4075 case Intrinsic::loongarch_lasx_xvmsub_w:
4076 case Intrinsic::loongarch_lasx_xvmsub_d: {
4077 EVT ResTy =
N->getValueType(0);
4082 case Intrinsic::loongarch_lsx_vdiv_b:
4083 case Intrinsic::loongarch_lsx_vdiv_h:
4084 case Intrinsic::loongarch_lsx_vdiv_w:
4085 case Intrinsic::loongarch_lsx_vdiv_d:
4086 case Intrinsic::loongarch_lasx_xvdiv_b:
4087 case Intrinsic::loongarch_lasx_xvdiv_h:
4088 case Intrinsic::loongarch_lasx_xvdiv_w:
4089 case Intrinsic::loongarch_lasx_xvdiv_d:
4092 case Intrinsic::loongarch_lsx_vdiv_bu:
4093 case Intrinsic::loongarch_lsx_vdiv_hu:
4094 case Intrinsic::loongarch_lsx_vdiv_wu:
4095 case Intrinsic::loongarch_lsx_vdiv_du:
4096 case Intrinsic::loongarch_lasx_xvdiv_bu:
4097 case Intrinsic::loongarch_lasx_xvdiv_hu:
4098 case Intrinsic::loongarch_lasx_xvdiv_wu:
4099 case Intrinsic::loongarch_lasx_xvdiv_du:
4102 case Intrinsic::loongarch_lsx_vmod_b:
4103 case Intrinsic::loongarch_lsx_vmod_h:
4104 case Intrinsic::loongarch_lsx_vmod_w:
4105 case Intrinsic::loongarch_lsx_vmod_d:
4106 case Intrinsic::loongarch_lasx_xvmod_b:
4107 case Intrinsic::loongarch_lasx_xvmod_h:
4108 case Intrinsic::loongarch_lasx_xvmod_w:
4109 case Intrinsic::loongarch_lasx_xvmod_d:
4112 case Intrinsic::loongarch_lsx_vmod_bu:
4113 case Intrinsic::loongarch_lsx_vmod_hu:
4114 case Intrinsic::loongarch_lsx_vmod_wu:
4115 case Intrinsic::loongarch_lsx_vmod_du:
4116 case Intrinsic::loongarch_lasx_xvmod_bu:
4117 case Intrinsic::loongarch_lasx_xvmod_hu:
4118 case Intrinsic::loongarch_lasx_xvmod_wu:
4119 case Intrinsic::loongarch_lasx_xvmod_du:
4122 case Intrinsic::loongarch_lsx_vand_v:
4123 case Intrinsic::loongarch_lasx_xvand_v:
4126 case Intrinsic::loongarch_lsx_vor_v:
4127 case Intrinsic::loongarch_lasx_xvor_v:
4130 case Intrinsic::loongarch_lsx_vxor_v:
4131 case Intrinsic::loongarch_lasx_xvxor_v:
4134 case Intrinsic::loongarch_lsx_vnor_v:
4135 case Intrinsic::loongarch_lasx_xvnor_v: {
4140 case Intrinsic::loongarch_lsx_vandi_b:
4141 case Intrinsic::loongarch_lasx_xvandi_b:
4143 lowerVectorSplatImm<8>(
N, 2, DAG));
4144 case Intrinsic::loongarch_lsx_vori_b:
4145 case Intrinsic::loongarch_lasx_xvori_b:
4147 lowerVectorSplatImm<8>(
N, 2, DAG));
4148 case Intrinsic::loongarch_lsx_vxori_b:
4149 case Intrinsic::loongarch_lasx_xvxori_b:
4151 lowerVectorSplatImm<8>(
N, 2, DAG));
4152 case Intrinsic::loongarch_lsx_vsll_b:
4153 case Intrinsic::loongarch_lsx_vsll_h:
4154 case Intrinsic::loongarch_lsx_vsll_w:
4155 case Intrinsic::loongarch_lsx_vsll_d:
4156 case Intrinsic::loongarch_lasx_xvsll_b:
4157 case Intrinsic::loongarch_lasx_xvsll_h:
4158 case Intrinsic::loongarch_lasx_xvsll_w:
4159 case Intrinsic::loongarch_lasx_xvsll_d:
4162 case Intrinsic::loongarch_lsx_vslli_b:
4163 case Intrinsic::loongarch_lasx_xvslli_b:
4165 lowerVectorSplatImm<3>(
N, 2, DAG));
4166 case Intrinsic::loongarch_lsx_vslli_h:
4167 case Intrinsic::loongarch_lasx_xvslli_h:
4169 lowerVectorSplatImm<4>(
N, 2, DAG));
4170 case Intrinsic::loongarch_lsx_vslli_w:
4171 case Intrinsic::loongarch_lasx_xvslli_w:
4173 lowerVectorSplatImm<5>(
N, 2, DAG));
4174 case Intrinsic::loongarch_lsx_vslli_d:
4175 case Intrinsic::loongarch_lasx_xvslli_d:
4177 lowerVectorSplatImm<6>(
N, 2, DAG));
4178 case Intrinsic::loongarch_lsx_vsrl_b:
4179 case Intrinsic::loongarch_lsx_vsrl_h:
4180 case Intrinsic::loongarch_lsx_vsrl_w:
4181 case Intrinsic::loongarch_lsx_vsrl_d:
4182 case Intrinsic::loongarch_lasx_xvsrl_b:
4183 case Intrinsic::loongarch_lasx_xvsrl_h:
4184 case Intrinsic::loongarch_lasx_xvsrl_w:
4185 case Intrinsic::loongarch_lasx_xvsrl_d:
4188 case Intrinsic::loongarch_lsx_vsrli_b:
4189 case Intrinsic::loongarch_lasx_xvsrli_b:
4191 lowerVectorSplatImm<3>(
N, 2, DAG));
4192 case Intrinsic::loongarch_lsx_vsrli_h:
4193 case Intrinsic::loongarch_lasx_xvsrli_h:
4195 lowerVectorSplatImm<4>(
N, 2, DAG));
4196 case Intrinsic::loongarch_lsx_vsrli_w:
4197 case Intrinsic::loongarch_lasx_xvsrli_w:
4199 lowerVectorSplatImm<5>(
N, 2, DAG));
4200 case Intrinsic::loongarch_lsx_vsrli_d:
4201 case Intrinsic::loongarch_lasx_xvsrli_d:
4203 lowerVectorSplatImm<6>(
N, 2, DAG));
4204 case Intrinsic::loongarch_lsx_vsra_b:
4205 case Intrinsic::loongarch_lsx_vsra_h:
4206 case Intrinsic::loongarch_lsx_vsra_w:
4207 case Intrinsic::loongarch_lsx_vsra_d:
4208 case Intrinsic::loongarch_lasx_xvsra_b:
4209 case Intrinsic::loongarch_lasx_xvsra_h:
4210 case Intrinsic::loongarch_lasx_xvsra_w:
4211 case Intrinsic::loongarch_lasx_xvsra_d:
4214 case Intrinsic::loongarch_lsx_vsrai_b:
4215 case Intrinsic::loongarch_lasx_xvsrai_b:
4217 lowerVectorSplatImm<3>(
N, 2, DAG));
4218 case Intrinsic::loongarch_lsx_vsrai_h:
4219 case Intrinsic::loongarch_lasx_xvsrai_h:
4221 lowerVectorSplatImm<4>(
N, 2, DAG));
4222 case Intrinsic::loongarch_lsx_vsrai_w:
4223 case Intrinsic::loongarch_lasx_xvsrai_w:
4225 lowerVectorSplatImm<5>(
N, 2, DAG));
4226 case Intrinsic::loongarch_lsx_vsrai_d:
4227 case Intrinsic::loongarch_lasx_xvsrai_d:
4229 lowerVectorSplatImm<6>(
N, 2, DAG));
4230 case Intrinsic::loongarch_lsx_vclz_b:
4231 case Intrinsic::loongarch_lsx_vclz_h:
4232 case Intrinsic::loongarch_lsx_vclz_w:
4233 case Intrinsic::loongarch_lsx_vclz_d:
4234 case Intrinsic::loongarch_lasx_xvclz_b:
4235 case Intrinsic::loongarch_lasx_xvclz_h:
4236 case Intrinsic::loongarch_lasx_xvclz_w:
4237 case Intrinsic::loongarch_lasx_xvclz_d:
4239 case Intrinsic::loongarch_lsx_vpcnt_b:
4240 case Intrinsic::loongarch_lsx_vpcnt_h:
4241 case Intrinsic::loongarch_lsx_vpcnt_w:
4242 case Intrinsic::loongarch_lsx_vpcnt_d:
4243 case Intrinsic::loongarch_lasx_xvpcnt_b:
4244 case Intrinsic::loongarch_lasx_xvpcnt_h:
4245 case Intrinsic::loongarch_lasx_xvpcnt_w:
4246 case Intrinsic::loongarch_lasx_xvpcnt_d:
4248 case Intrinsic::loongarch_lsx_vbitclr_b:
4249 case Intrinsic::loongarch_lsx_vbitclr_h:
4250 case Intrinsic::loongarch_lsx_vbitclr_w:
4251 case Intrinsic::loongarch_lsx_vbitclr_d:
4252 case Intrinsic::loongarch_lasx_xvbitclr_b:
4253 case Intrinsic::loongarch_lasx_xvbitclr_h:
4254 case Intrinsic::loongarch_lasx_xvbitclr_w:
4255 case Intrinsic::loongarch_lasx_xvbitclr_d:
4257 case Intrinsic::loongarch_lsx_vbitclri_b:
4258 case Intrinsic::loongarch_lasx_xvbitclri_b:
4259 return lowerVectorBitClearImm<3>(
N, DAG);
4260 case Intrinsic::loongarch_lsx_vbitclri_h:
4261 case Intrinsic::loongarch_lasx_xvbitclri_h:
4262 return lowerVectorBitClearImm<4>(
N, DAG);
4263 case Intrinsic::loongarch_lsx_vbitclri_w:
4264 case Intrinsic::loongarch_lasx_xvbitclri_w:
4265 return lowerVectorBitClearImm<5>(
N, DAG);
4266 case Intrinsic::loongarch_lsx_vbitclri_d:
4267 case Intrinsic::loongarch_lasx_xvbitclri_d:
4268 return lowerVectorBitClearImm<6>(
N, DAG);
4269 case Intrinsic::loongarch_lsx_vbitset_b:
4270 case Intrinsic::loongarch_lsx_vbitset_h:
4271 case Intrinsic::loongarch_lsx_vbitset_w:
4272 case Intrinsic::loongarch_lsx_vbitset_d:
4273 case Intrinsic::loongarch_lasx_xvbitset_b:
4274 case Intrinsic::loongarch_lasx_xvbitset_h:
4275 case Intrinsic::loongarch_lasx_xvbitset_w:
4276 case Intrinsic::loongarch_lasx_xvbitset_d: {
4277 EVT VecTy =
N->getValueType(0);
4283 case Intrinsic::loongarch_lsx_vbitseti_b:
4284 case Intrinsic::loongarch_lasx_xvbitseti_b:
4285 return lowerVectorBitSetImm<3>(
N, DAG);
4286 case Intrinsic::loongarch_lsx_vbitseti_h:
4287 case Intrinsic::loongarch_lasx_xvbitseti_h:
4288 return lowerVectorBitSetImm<4>(
N, DAG);
4289 case Intrinsic::loongarch_lsx_vbitseti_w:
4290 case Intrinsic::loongarch_lasx_xvbitseti_w:
4291 return lowerVectorBitSetImm<5>(
N, DAG);
4292 case Intrinsic::loongarch_lsx_vbitseti_d:
4293 case Intrinsic::loongarch_lasx_xvbitseti_d:
4294 return lowerVectorBitSetImm<6>(
N, DAG);
4295 case Intrinsic::loongarch_lsx_vbitrev_b:
4296 case Intrinsic::loongarch_lsx_vbitrev_h:
4297 case Intrinsic::loongarch_lsx_vbitrev_w:
4298 case Intrinsic::loongarch_lsx_vbitrev_d:
4299 case Intrinsic::loongarch_lasx_xvbitrev_b:
4300 case Intrinsic::loongarch_lasx_xvbitrev_h:
4301 case Intrinsic::loongarch_lasx_xvbitrev_w:
4302 case Intrinsic::loongarch_lasx_xvbitrev_d: {
4303 EVT VecTy =
N->getValueType(0);
4309 case Intrinsic::loongarch_lsx_vbitrevi_b:
4310 case Intrinsic::loongarch_lasx_xvbitrevi_b:
4311 return lowerVectorBitRevImm<3>(
N, DAG);
4312 case Intrinsic::loongarch_lsx_vbitrevi_h:
4313 case Intrinsic::loongarch_lasx_xvbitrevi_h:
4314 return lowerVectorBitRevImm<4>(
N, DAG);
4315 case Intrinsic::loongarch_lsx_vbitrevi_w:
4316 case Intrinsic::loongarch_lasx_xvbitrevi_w:
4317 return lowerVectorBitRevImm<5>(
N, DAG);
4318 case Intrinsic::loongarch_lsx_vbitrevi_d:
4319 case Intrinsic::loongarch_lasx_xvbitrevi_d:
4320 return lowerVectorBitRevImm<6>(
N, DAG);
4321 case Intrinsic::loongarch_lsx_vfadd_s:
4322 case Intrinsic::loongarch_lsx_vfadd_d:
4323 case Intrinsic::loongarch_lasx_xvfadd_s:
4324 case Intrinsic::loongarch_lasx_xvfadd_d:
4327 case Intrinsic::loongarch_lsx_vfsub_s:
4328 case Intrinsic::loongarch_lsx_vfsub_d:
4329 case Intrinsic::loongarch_lasx_xvfsub_s:
4330 case Intrinsic::loongarch_lasx_xvfsub_d:
4333 case Intrinsic::loongarch_lsx_vfmul_s:
4334 case Intrinsic::loongarch_lsx_vfmul_d:
4335 case Intrinsic::loongarch_lasx_xvfmul_s:
4336 case Intrinsic::loongarch_lasx_xvfmul_d:
4339 case Intrinsic::loongarch_lsx_vfdiv_s:
4340 case Intrinsic::loongarch_lsx_vfdiv_d:
4341 case Intrinsic::loongarch_lasx_xvfdiv_s:
4342 case Intrinsic::loongarch_lasx_xvfdiv_d:
4345 case Intrinsic::loongarch_lsx_vfmadd_s:
4346 case Intrinsic::loongarch_lsx_vfmadd_d:
4347 case Intrinsic::loongarch_lasx_xvfmadd_s:
4348 case Intrinsic::loongarch_lasx_xvfmadd_d:
4350 N->getOperand(2),
N->getOperand(3));
4351 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
4353 N->getOperand(1),
N->getOperand(2),
4354 legalizeIntrinsicImmArg<4>(
N, 3, DAG, Subtarget));
4355 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
4356 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
4358 N->getOperand(1),
N->getOperand(2),
4359 legalizeIntrinsicImmArg<3>(
N, 3, DAG, Subtarget));
4360 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
4361 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
4363 N->getOperand(1),
N->getOperand(2),
4364 legalizeIntrinsicImmArg<2>(
N, 3, DAG, Subtarget));
4365 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
4367 N->getOperand(1),
N->getOperand(2),
4368 legalizeIntrinsicImmArg<1>(
N, 3, DAG, Subtarget));
4369 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
4370 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
4371 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
4372 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
4373 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
4374 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
4375 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
4376 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
4380 case Intrinsic::loongarch_lsx_vreplve_b:
4381 case Intrinsic::loongarch_lsx_vreplve_h:
4382 case Intrinsic::loongarch_lsx_vreplve_w:
4383 case Intrinsic::loongarch_lsx_vreplve_d:
4384 case Intrinsic::loongarch_lasx_xvreplve_b:
4385 case Intrinsic::loongarch_lasx_xvreplve_h:
4386 case Intrinsic::loongarch_lasx_xvreplve_w:
4387 case Intrinsic::loongarch_lasx_xvreplve_d:
4399 switch (
N->getOpcode()) {
4436 MF->
insert(It, BreakMBB);
4440 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->
end());
4441 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
4459 BreakMBB->addSuccessor(SinkMBB);
4471 switch (
MI.getOpcode()) {
4474 case LoongArch::PseudoVBZ:
4475 CondOpc = LoongArch::VSETEQZ_V;
4477 case LoongArch::PseudoVBZ_B:
4478 CondOpc = LoongArch::VSETANYEQZ_B;
4480 case LoongArch::PseudoVBZ_H:
4481 CondOpc = LoongArch::VSETANYEQZ_H;
4483 case LoongArch::PseudoVBZ_W:
4484 CondOpc = LoongArch::VSETANYEQZ_W;
4486 case LoongArch::PseudoVBZ_D:
4487 CondOpc = LoongArch::VSETANYEQZ_D;
4489 case LoongArch::PseudoVBNZ:
4490 CondOpc = LoongArch::VSETNEZ_V;
4492 case LoongArch::PseudoVBNZ_B:
4493 CondOpc = LoongArch::VSETALLNEZ_B;
4495 case LoongArch::PseudoVBNZ_H:
4496 CondOpc = LoongArch::VSETALLNEZ_H;
4498 case LoongArch::PseudoVBNZ_W:
4499 CondOpc = LoongArch::VSETALLNEZ_W;
4501 case LoongArch::PseudoVBNZ_D:
4502 CondOpc = LoongArch::VSETALLNEZ_D;
4504 case LoongArch::PseudoXVBZ:
4505 CondOpc = LoongArch::XVSETEQZ_V;
4507 case LoongArch::PseudoXVBZ_B:
4508 CondOpc = LoongArch::XVSETANYEQZ_B;
4510 case LoongArch::PseudoXVBZ_H:
4511 CondOpc = LoongArch::XVSETANYEQZ_H;
4513 case LoongArch::PseudoXVBZ_W:
4514 CondOpc = LoongArch::XVSETANYEQZ_W;
4516 case LoongArch::PseudoXVBZ_D:
4517 CondOpc = LoongArch::XVSETANYEQZ_D;
4519 case LoongArch::PseudoXVBNZ:
4520 CondOpc = LoongArch::XVSETNEZ_V;
4522 case LoongArch::PseudoXVBNZ_B:
4523 CondOpc = LoongArch::XVSETALLNEZ_B;
4525 case LoongArch::PseudoXVBNZ_H:
4526 CondOpc = LoongArch::XVSETALLNEZ_H;
4528 case LoongArch::PseudoXVBNZ_W:
4529 CondOpc = LoongArch::XVSETALLNEZ_W;
4531 case LoongArch::PseudoXVBNZ_D:
4532 CondOpc = LoongArch::XVSETALLNEZ_D;
4547 F->insert(It, FalseBB);
4548 F->insert(It, TrueBB);
4549 F->insert(It, SinkBB);
4552 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
4556 Register FCC =
MRI.createVirtualRegister(&LoongArch::CFRRegClass);
4565 Register RD1 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
4573 Register RD2 =
MRI.createVirtualRegister(&LoongArch::GPRRegClass);
4581 MI.getOperand(0).getReg())
4588 MI.eraseFromParent();
4597 switch (
MI.getOpcode()) {
4600 case LoongArch::PseudoXVINSGR2VR_B:
4602 InsOp = LoongArch::VINSGR2VR_B;
4604 case LoongArch::PseudoXVINSGR2VR_H:
4606 InsOp = LoongArch::VINSGR2VR_H;
4618 unsigned Idx =
MI.getOperand(3).getImm();
4621 if (
Idx >= HalfSize) {
4622 ScratchReg1 =
MRI.createVirtualRegister(RC);
4623 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg1)
4629 Register ScratchSubReg1 =
MRI.createVirtualRegister(SubRC);
4630 Register ScratchSubReg2 =
MRI.createVirtualRegister(SubRC);
4632 .
addReg(ScratchReg1, 0, LoongArch::sub_128);
4639 if (
Idx >= HalfSize)
4640 ScratchReg2 =
MRI.createVirtualRegister(RC);
4642 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::SUBREG_TO_REG), ScratchReg2)
4645 .
addImm(LoongArch::sub_128);
4647 if (
Idx >= HalfSize)
4653 MI.eraseFromParent();
4660 assert(Subtarget.hasExtLSX());
4667 Register ScratchReg1 =
MRI.createVirtualRegister(RC);
4668 Register ScratchReg2 =
MRI.createVirtualRegister(RC);
4669 Register ScratchReg3 =
MRI.createVirtualRegister(RC);
4673 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
4674 : LoongArch::VINSGR2VR_W),
4681 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
4685 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
4686 : LoongArch::VPICKVE2GR_W),
4691 MI.eraseFromParent();
4700 switch (
MI.getOpcode()) {
4703 case LoongArch::DIV_W:
4704 case LoongArch::DIV_WU:
4705 case LoongArch::MOD_W:
4706 case LoongArch::MOD_WU:
4707 case LoongArch::DIV_D:
4708 case LoongArch::DIV_DU:
4709 case LoongArch::MOD_D:
4710 case LoongArch::MOD_DU:
4713 case LoongArch::WRFCSR: {
4715 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
4716 .
addReg(
MI.getOperand(1).getReg());
4717 MI.eraseFromParent();
4720 case LoongArch::RDFCSR: {
4723 MI.getOperand(0).getReg())
4724 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
4726 MI.eraseFromParent();
4729 case LoongArch::PseudoVBZ:
4730 case LoongArch::PseudoVBZ_B:
4731 case LoongArch::PseudoVBZ_H:
4732 case LoongArch::PseudoVBZ_W:
4733 case LoongArch::PseudoVBZ_D:
4734 case LoongArch::PseudoVBNZ:
4735 case LoongArch::PseudoVBNZ_B:
4736 case LoongArch::PseudoVBNZ_H:
4737 case LoongArch::PseudoVBNZ_W:
4738 case LoongArch::PseudoVBNZ_D:
4739 case LoongArch::PseudoXVBZ:
4740 case LoongArch::PseudoXVBZ_B:
4741 case LoongArch::PseudoXVBZ_H:
4742 case LoongArch::PseudoXVBZ_W:
4743 case LoongArch::PseudoXVBZ_D:
4744 case LoongArch::PseudoXVBNZ:
4745 case LoongArch::PseudoXVBNZ_B:
4746 case LoongArch::PseudoXVBNZ_H:
4747 case LoongArch::PseudoXVBNZ_W:
4748 case LoongArch::PseudoXVBNZ_D:
4750 case LoongArch::PseudoXVINSGR2VR_B:
4751 case LoongArch::PseudoXVINSGR2VR_H:
4753 case LoongArch::PseudoCTPOP:
4755 case TargetOpcode::STATEPOINT:
4761 MI.addOperand(*
MI.getMF(),
4763 LoongArch::R1,
true,
4774 unsigned *
Fast)
const {
4775 if (!Subtarget.hasUAL())
4789#define NODE_NAME_CASE(node) \
4790 case LoongArchISD::node: \
4791 return "LoongArchISD::" #node;
4871#undef NODE_NAME_CASE
4884 LoongArch::R7, LoongArch::R8, LoongArch::R9,
4885 LoongArch::R10, LoongArch::R11};
4889 LoongArch::F3, LoongArch::F4, LoongArch::F5,
4890 LoongArch::F6, LoongArch::F7};
4893 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
4894 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
4897 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
4898 LoongArch::VR6, LoongArch::VR7};
4901 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
4902 LoongArch::XR6, LoongArch::XR7};
4908 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
4910 unsigned GRLenInBytes = GRLen / 8;
4943 unsigned ValNo,
MVT ValVT,
4945 CCState &State,
bool IsFixed,
bool IsRet,
4947 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
4948 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
4949 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
4954 if (IsRet && ValNo > 1)
4958 bool UseGPRForFloat =
true;
4968 UseGPRForFloat = !IsFixed;
4977 UseGPRForFloat =
true;
4979 if (UseGPRForFloat && ValVT == MVT::f32) {
4982 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
4985 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
4996 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
4998 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
5001 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
5010 "PendingLocs and PendingArgFlags out of sync");
5028 PendingLocs.
size() <= 2) {
5029 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
5034 PendingLocs.
clear();
5035 PendingArgFlags.
clear();
5042 unsigned StoreSizeBytes = GRLen / 8;
5045 if (ValVT == MVT::f32 && !UseGPRForFloat)
5047 else if (ValVT == MVT::f64 && !UseGPRForFloat)
5061 if (!PendingLocs.
empty()) {
5063 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
5064 for (
auto &It : PendingLocs) {
5066 It.convertToReg(Reg);
5071 PendingLocs.clear();
5072 PendingArgFlags.
clear();
5075 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
5076 "Expected an GRLenVT at this stage");
5093void LoongArchTargetLowering::analyzeInputArgs(
5096 LoongArchCCAssignFn Fn)
const {
5098 for (
unsigned i = 0, e =
Ins.size(); i != e; ++i) {
5100 Type *ArgTy =
nullptr;
5102 ArgTy = FType->getReturnType();
5103 else if (Ins[i].isOrigArg())
5104 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
5108 CCInfo,
true, IsRet, ArgTy)) {
5109 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
5116void LoongArchTargetLowering::analyzeOutputArgs(
5119 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
5120 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
5121 MVT ArgVT = Outs[i].VT;
5122 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
5126 CCInfo, Outs[i].IsFixed, IsRet, OrigTy)) {
5127 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
5168 if (In.isOrigArg()) {
5173 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
5174 (
BitWidth < 32 && In.Flags.isZExt())) {
5234 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
5238 LoongArch::R23, LoongArch::R24, LoongArch::R25,
5239 LoongArch::R26, LoongArch::R27, LoongArch::R28,
5240 LoongArch::R29, LoongArch::R30, LoongArch::R31};
5247 if (LocVT == MVT::f32) {
5250 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
5251 LoongArch::F26, LoongArch::F27};
5258 if (LocVT == MVT::f64) {
5261 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
5262 LoongArch::F30_64, LoongArch::F31_64};
5291 "GHC calling convention requires the F and D extensions");
5296 unsigned GRLenInBytes = Subtarget.
getGRLen() / 8;
5298 std::vector<SDValue> OutChains;
5307 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
5309 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
5321 unsigned ArgIndex = Ins[i].OrigArgIndex;
5322 unsigned ArgPartOffset = Ins[i].PartOffset;
5323 assert(ArgPartOffset == 0);
5324 while (i + 1 != e && Ins[i + 1].OrigArgIndex == ArgIndex) {
5326 unsigned PartOffset = Ins[i + 1].PartOffset - ArgPartOffset;
5349 int VaArgOffset, VarArgsSaveSize;
5355 VarArgsSaveSize = 0;
5357 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() -
Idx);
5358 VaArgOffset = -VarArgsSaveSize;
5364 LoongArchFI->setVarArgsFrameIndex(FI);
5372 VarArgsSaveSize += GRLenInBytes;
5377 for (
unsigned I =
Idx;
I < ArgRegs.
size();
5378 ++
I, VaArgOffset += GRLenInBytes) {
5386 cast<StoreSDNode>(Store.getNode())
5388 ->setValue((
Value *)
nullptr);
5389 OutChains.push_back(Store);
5391 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
5396 if (!OutChains.empty()) {
5397 OutChains.push_back(Chain);
5412 if (
N->getNumValues() != 1)
5414 if (!
N->hasNUsesOfValue(1, 0))
5417 SDNode *Copy = *
N->user_begin();
5423 if (Copy->getGluedNode())
5427 bool HasRet =
false;
5428 for (
SDNode *Node : Copy->users()) {
5437 Chain = Copy->getOperand(0);
5442bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
5446 auto CalleeCC = CLI.CallConv;
5447 auto &Outs = CLI.Outs;
5449 auto CallerCC = Caller.getCallingConv();
5456 for (
auto &VA : ArgLocs)
5462 auto IsCallerStructRet = Caller.hasStructRetAttr();
5463 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
5464 if (IsCallerStructRet || IsCalleeStructRet)
5468 for (
auto &Arg : Outs)
5469 if (Arg.Flags.isByVal())
5474 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
5475 if (CalleeCC != CallerCC) {
5476 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
5477 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
5515 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
5519 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
5525 "site marked musttail");
5532 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
5534 if (!Flags.isByVal())
5538 unsigned Size = Flags.getByValSize();
5539 Align Alignment = Flags.getNonZeroByValAlign();
5546 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
5548 false,
nullptr, std::nullopt,
5560 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(); i != e; ++i) {
5562 SDValue ArgValue = OutVals[i];
5575 unsigned ArgIndex = Outs[i].OrigArgIndex;
5576 unsigned ArgPartOffset = Outs[i].PartOffset;
5577 assert(ArgPartOffset == 0);
5582 while (i + 1 != e && Outs[i + 1].OrigArgIndex == ArgIndex) {
5583 SDValue PartValue = OutVals[i + 1];
5584 unsigned PartOffset = Outs[i + 1].PartOffset - ArgPartOffset;
5594 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
5598 for (
const auto &Part : Parts) {
5599 SDValue PartValue = Part.first;
5600 SDValue PartOffset = Part.second;
5607 ArgValue = SpillSlot;
5613 if (Flags.isByVal())
5614 ArgValue = ByValArgs[j++];
5621 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
5622 "for passing parameters");
5625 if (!StackPtr.getNode())
5638 if (!MemOpChains.
empty())
5644 for (
auto &Reg : RegsToPass) {
5645 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
5672 for (
auto &Reg : RegsToPass)
5678 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
5679 assert(Mask &&
"Missing call preserved mask for calling convention");
5697 assert(Subtarget.
is64Bit() &&
"Medium code model requires LA64");
5701 assert(Subtarget.
is64Bit() &&
"Large code model requires LA64");
5724 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
5727 for (
auto &VA : RVLocs) {
5748 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
5750 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
5754 Outs[i].Flags, CCInfo,
true,
true,
5781 for (
unsigned i = 0, e = RVLocs.
size(); i < e; ++i) {
5805 if (!Subtarget.hasExtLSX())
5808 if (VT == MVT::f32) {
5809 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
5810 return (masked == 0x3e000000 || masked == 0x40000000);
5813 if (VT == MVT::f64) {
5814 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
5815 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
5821bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
5822 bool ForCodeSize)
const {
5824 if (VT == MVT::f32 && !Subtarget.hasBasicF())
5826 if (VT == MVT::f64 && !Subtarget.hasBasicD())
5828 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
5839bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
5842 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
5844 if (isa<LoadInst>(
I))
5849 Type *Ty =
I->getOperand(0)->getType();
5868 return Y.getValueType().isScalarInteger() && !isa<ConstantSDNode>(
Y);
5874 unsigned Intrinsic)
const {
5875 switch (Intrinsic) {
5878 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
5879 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
5880 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
5881 case Intrinsic::loongarch_masked_atomicrmw_nand_i32:
5883 Info.memVT = MVT::i32;
5884 Info.ptrVal =
I.getArgOperand(0);
5903 "Unable to expand");
5904 unsigned MinWordSize = 4;
5917 Intrinsic::ptrmask, {PtrTy, IntTy},
5918 {
Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
5922 Value *PtrLSB = Builder.
CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
5924 ShiftAmt = Builder.
CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
5926 ConstantInt::get(WordType,
5930 Value *ValOperand_Shifted =
5932 ShiftAmt,
"ValOperand_Shifted");
5935 NewOperand = Builder.
CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
5937 NewOperand = ValOperand_Shifted;
5963 if (Subtarget.hasLAM_BH() && Subtarget.
is64Bit() &&
5971 if (Subtarget.hasLAMCAS()) {
5993 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
5995 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
5997 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
5999 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
6001 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
6003 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
6005 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
6007 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
6017 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
6019 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
6021 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
6023 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
6035 if (Subtarget.hasLAMCAS())
6048 Value *FailureOrdering =
6052 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
6058 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
6082 unsigned GRLen = Subtarget.
getGRLen();
6111 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
6114 Builder.
CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
6141 const Constant *PersonalityFn)
const {
6142 return LoongArch::R4;
6146 const Constant *PersonalityFn)
const {
6147 return LoongArch::R5;
6158 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
6159 return RefinementSteps;
6164 int &RefinementSteps,
6165 bool &UseOneConstNR,
6166 bool Reciprocal)
const {
6167 if (Subtarget.hasFrecipe()) {
6171 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
6172 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
6173 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
6174 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
6175 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
6194 int &RefinementSteps)
const {
6195 if (Subtarget.hasFrecipe()) {
6199 if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||
6200 (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||
6201 (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||
6202 (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||
6203 (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {
6220LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
6238 if (Constraint.
size() == 1) {
6239 switch (Constraint[0]) {
6254 if (Constraint ==
"ZC" || Constraint ==
"ZB")
6270std::pair<unsigned, const TargetRegisterClass *>
6271LoongArchTargetLowering::getRegForInlineAsmConstraint(
6275 if (Constraint.
size() == 1) {
6276 switch (Constraint[0]) {
6281 return std::make_pair(0U, &LoongArch::GPRRegClass);
6283 if (Subtarget.hasBasicF() && VT == MVT::f32)
6284 return std::make_pair(0U, &LoongArch::FPR32RegClass);
6285 if (Subtarget.hasBasicD() && VT == MVT::f64)
6286 return std::make_pair(0U, &LoongArch::FPR64RegClass);
6287 if (Subtarget.hasExtLSX() &&
6288 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
6289 return std::make_pair(0U, &LoongArch::LSX128RegClass);
6290 if (Subtarget.hasExtLASX() &&
6291 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
6292 return std::make_pair(0U, &LoongArch::LASX256RegClass);
6312 bool IsFP = Constraint[2] ==
'f';
6313 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
6314 std::pair<unsigned, const TargetRegisterClass *>
R;
6316 TRI, join_items(
"", Temp.first, Temp.second), VT);
6319 unsigned RegNo =
R.first;
6320 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
6321 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
6322 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
6323 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
6333void LoongArchTargetLowering::LowerAsmOperandForConstraint(
6337 if (Constraint.
size() == 1) {
6338 switch (Constraint[0]) {
6341 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6343 if (isInt<16>(CVal))
6350 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6352 if (isInt<12>(CVal))
6359 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op))
6360 if (
C->getZExtValue() == 0)
6366 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6368 if (isUInt<12>(CVal))
6380#define GET_REGISTER_MATCHER
6381#include "LoongArchGenAsmMatcher.inc"
6387 std::string NewRegName =
Name.second.str();
6389 if (Reg == LoongArch::NoRegister)
6391 if (Reg == LoongArch::NoRegister)
6395 if (!ReservedRegs.
test(Reg))
6411 if (
auto *ConstNode = dyn_cast<ConstantSDNode>(
C.getNode())) {
6412 const APInt &Imm = ConstNode->getAPIntValue();
6414 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
6415 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
6418 if (ConstNode->hasOneUse() &&
6419 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
6420 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
6426 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
6427 unsigned Shifts = Imm.countr_zero();
6433 APInt ImmPop = Imm.ashr(Shifts);
6434 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
6438 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
6439 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
6440 (ImmSmall - Imm).isPowerOf2())
6450 Type *Ty,
unsigned AS,
6466 !(isShiftedInt<14, 2>(AM.
BaseOffs) && Subtarget.hasUAL()))
6493 return isInt<12>(Imm);
6497 return isInt<12>(Imm);
6504 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
6505 EVT MemVT = LD->getMemoryVT();
6506 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
6517 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
6526 if (
Y.getValueType().isVector())
6529 return !isa<ConstantSDNode>(
Y);
6538 Type *Ty,
bool IsSigned)
const {
6559 Align &PrefAlign)
const {
6560 if (!isa<MemIntrinsic>(CI))
6565 PrefAlign =
Align(8);
6568 PrefAlign =
Align(4);
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)
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
#define NODE_NAME_CASE(node)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
Analysis containing CSE Info
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
const HexagonInstrInfo * TII
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
const MCPhysReg ArgFPR32s[]
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue 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 bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static void canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue 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 Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
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).
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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 void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
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)
#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 MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, 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 bool isConstantOrUndef(const SDValue Op)
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 MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRRD_CASE(NAME, NODE)
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static 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 bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static 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)
unsigned const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
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,...
SmallVectorImpl< ISD::ArgFlagsTy > & getPendingArgFlags()
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
SmallVectorImpl< CCValAssign > & getPendingLocs()
void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
void addLoc(const CCValAssign &V)
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Argument * getArg(unsigned i) const
Common base class shared among various IRBuilders.
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
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.
void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
This class is used to represent ISD::LOAD nodes.
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void addSExt32Register(Register Reg)
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getMaxBytesForAlignment() const
Align getPrefFunctionAlignment() const
unsigned getGRLen() const
Align getPrefLoopAlignment() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
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...
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
bool is128BitVector() const
Return true if this is a 128-bit vector type.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
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.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
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 '...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
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,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
EVT getMemoryVT() const
Return the type of the in-memory value.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
size_t use_size() const
Return the number of uses of this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
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...
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)
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
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),...
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...
SDValue getRegister(Register Reg, EVT VT)
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue 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.
SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
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.
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.
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)
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
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)
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
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.
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 ...
SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getValueType(EVT)
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)
MachineFunction & getMachineFunction() const
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
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.
SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
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.
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.
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
ArrayRef< int > getMask() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
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.
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.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass 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
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...
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
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 verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
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.
unsigned getIntegerBitWidth() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isIntegerTy() const
True if this is an instance of IntegerType.
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
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.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ 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.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ 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...
@ 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,...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
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)
Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
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 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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
AtomicOrdering
Atomic ordering for LLVM's memory model.
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
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).
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.
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.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Align getNonZeroOrigAlign() const
Register getFrameRegister(const MachineFunction &MF) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static 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
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT, bool Value=true)