22#include "llvm/IR/IntrinsicsAArch64.h"
31#define DEBUG_TYPE "aarch64-isel"
32#define PASS_NAME "AArch64 Instruction Selection"
35#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
36#pragma inline_depth(0)
52 AArch64DAGToDAGISel() =
delete;
67 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
69 std::vector<SDValue> &OutOps)
override;
71 template <
signed Low,
signed High,
signed Scale>
74 template <
signed Low,
signed High>
82 return SelectShiftedRegister(
N,
false,
Reg, Shift);
85 return SelectShiftedRegister(
N,
true,
Reg, Shift);
88 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
91 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
94 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
97 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
100 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
103 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
106 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
109 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
112 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
115 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
118 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
121 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
124 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
127 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
130 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
133 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
136 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
138 template <
unsigned Size,
unsigned Max>
142 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
145 int64_t
C = CI->getSExtValue();
153 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
160 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
166 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
171 N =
N->getOperand(0);
175 EVT VT =
N->getValueType(0);
176 EVT LVT =
N->getOperand(0).getValueType();
177 unsigned Index =
N->getConstantOperandVal(1);
181 Res =
N->getOperand(0);
186 if (
N.getOpcode() != AArch64ISD::VLSHR)
189 EVT VT =
Op.getValueType();
190 unsigned ShtAmt =
N->getConstantOperandVal(1);
195 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
197 Op.getOperand(1).getConstantOperandVal(0)
198 <<
Op.getOperand(1).getConstantOperandVal(1));
199 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
202 Op.getOperand(1).getConstantOperandVal(0));
206 if (Imm != 1ULL << (ShtAmt - 1))
209 Res1 =
Op.getOperand(0);
210 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
214 bool SelectDupZeroOrUndef(
SDValue N) {
215 switch(
N->getOpcode()) {
218 case AArch64ISD::DUP:
220 auto Opnd0 =
N->getOperand(0);
234 bool SelectAny(
SDValue) {
return true; }
237 switch(
N->getOpcode()) {
238 case AArch64ISD::DUP:
240 auto Opnd0 =
N->getOperand(0);
252 template <MVT::SimpleValueType VT,
bool Negate>
254 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
257 template <MVT::SimpleValueType VT,
bool Negate>
259 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
262 template <MVT::SimpleValueType VT>
264 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
267 template <MVT::SimpleValueType VT,
bool Invert = false>
269 return SelectSVELogicalImm(
N, VT, Imm, Invert);
272 template <MVT::SimpleValueType VT>
274 return SelectSVEArithImm(
N, VT, Imm);
277 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
279 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
286 EVT EltVT =
N->getValueType(0).getVectorElementType();
287 return SelectSVEShiftImm(
N->getOperand(0), 1,
293 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
300 MulImm = 1LL << MulImm;
302 if ((MulImm % std::abs(Scale)) != 0)
306 if ((MulImm >= Min) && (MulImm <= Max)) {
307 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
314 template <
signed Max,
signed Scale>
321 if (MulImm >= 0 && MulImm <= Max) {
323 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
330 template <
unsigned BaseReg,
unsigned Max>
338 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
361 const unsigned SubRegs[]);
363 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
365 bool tryIndexedLoad(
SDNode *
N);
367 void SelectPtrauthAuth(
SDNode *
N);
368 void SelectPtrauthResign(
SDNode *
N);
370 bool trySelectStackSlotTagP(
SDNode *
N);
373 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
375 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
377 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
378 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
379 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
380 unsigned Opc_rr,
unsigned Opc_ri,
381 bool IsIntr =
false);
382 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
383 unsigned Scale,
unsigned Opc_ri,
385 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
386 bool IsZmMulti,
unsigned Opcode,
387 bool HasPred =
false);
389 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
390 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
391 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
392 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
393 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
394 bool IsTupleInput,
unsigned Opc);
395 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
397 template <
unsigned MaxIdx,
unsigned Scale>
398 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
400 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
401 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
402 unsigned BaseReg = 0);
405 template <
int64_t Min,
int64_t Max>
409 template <
unsigned Scale>
411 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
414 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
417 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc);
419 template <
unsigned MaxIdx,
unsigned Scale>
424 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
425 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
426 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
427 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
428 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
429 unsigned Opc_rr,
unsigned Opc_ri);
430 std::tuple<unsigned, SDValue, SDValue>
431 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
435 bool tryBitfieldExtractOp(
SDNode *
N);
436 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
437 bool tryBitfieldInsertOp(
SDNode *
N);
438 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
439 bool tryShiftAmountMod(
SDNode *
N);
441 bool tryReadRegister(
SDNode *
N);
442 bool tryWriteRegister(
SDNode *
N);
444 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
445 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
450#include "AArch64GenDAGISel.inc"
458 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
460 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
473 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
474 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
475 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
478 template<
unsigned RegW
idth>
480 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
483 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
485 template<
unsigned RegW
idth>
487 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
493 bool SelectCMP_SWAP(
SDNode *
N);
504 bool AllowSaturation,
SDValue &Imm);
512 bool SelectAllActivePredicate(
SDValue N);
524 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
528char AArch64DAGToDAGISelLegacy::ID = 0;
536 Imm =
C->getZExtValue();
553 return N->getOpcode() ==
Opc &&
564 return Imm == ImmExpected;
568bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
570 std::vector<SDValue> &OutOps) {
571 switch(ConstraintID) {
574 case InlineAsm::ConstraintCode::m:
575 case InlineAsm::ConstraintCode::o:
576 case InlineAsm::ConstraintCode::Q:
580 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
582 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
584 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
585 dl,
Op.getValueType(),
587 OutOps.push_back(NewOp);
606 uint64_t Immed =
N.getNode()->getAsZExtVal();
609 if (Immed >> 12 == 0) {
611 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
619 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
620 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
637 uint64_t Immed =
N.getNode()->getAsZExtVal();
645 if (
N.getValueType() == MVT::i32)
646 Immed = ~((uint32_t)Immed) + 1;
648 Immed = ~Immed + 1ULL;
649 if (Immed & 0xFFFFFFFFFF000000ULL)
652 Immed &= 0xFFFFFFULL;
653 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
660 switch (
N.getOpcode()) {
686 unsigned ShiftVal = CSD->getZExtValue();
704bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
707 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
712 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
736 EVT VT =
N.getValueType();
737 if (VT != MVT::i32 && VT != MVT::i64)
740 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
746 unsigned LHSOpcode =
LHS->getOpcode();
760 unsigned LowZBits, MaskLen;
764 unsigned BitWidth =
N.getValueSizeInBits();
771 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
774 NewShiftC = LowZBits - ShiftAmtC;
775 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
781 NewShiftC = LowZBits + ShiftAmtC;
794 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
796 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
800 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
802 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
803 NewShiftAmt, BitWidthMinus1),
806 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
820 SrcVT =
N.getOperand(0).getValueType();
822 if (!IsLoadStore && SrcVT == MVT::i8)
824 else if (!IsLoadStore && SrcVT == MVT::i16)
826 else if (SrcVT == MVT::i32)
828 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
833 EVT SrcVT =
N.getOperand(0).getValueType();
834 if (!IsLoadStore && SrcVT == MVT::i8)
836 else if (!IsLoadStore && SrcVT == MVT::i16)
838 else if (SrcVT == MVT::i32)
840 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
868bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
871 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
876 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
877 V.getConstantOperandVal(1) <= 4 &&
890bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
892 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
902 unsigned BitSize =
N.getValueSizeInBits();
903 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
906 Reg =
N.getOperand(0);
907 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
908 return isWorthFoldingALU(
N,
true);
919 if (
N.getValueType() == MVT::i32)
927template<
signed Low,
signed High,
signed Scale>
933 if ((MulImm % std::abs(Scale)) == 0) {
934 int64_t RDVLImm = MulImm / Scale;
935 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
936 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
945template <
signed Low,
signed High>
946bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
951 if (MulImm >=
Low && MulImm <=
High) {
952 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
963 unsigned ShiftVal = 0;
978 Reg =
N.getOperand(0).getOperand(0);
984 Reg =
N.getOperand(0);
989 unsigned Opc =
N.getOpcode();
1007 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1009 return isWorthFoldingALU(
N);
1016 unsigned ShiftVal = 0;
1030 Reg =
N.getOperand(0);
1031 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1033 return isWorthFoldingALU(
N);
1042 for (
auto *
User :
N->users()) {
1043 if (
User->getOpcode() != ISD::LOAD &&
User->getOpcode() != ISD::STORE &&
1044 User->getOpcode() != ISD::ATOMIC_LOAD &&
1045 User->getOpcode() != ISD::ATOMIC_STORE)
1069bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1070 unsigned BW,
unsigned Size,
1074 const DataLayout &
DL = CurDAG->getDataLayout();
1075 const TargetLowering *TLI = getTargetLowering();
1079 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1085 if (CurDAG->isBaseWithConstantOffset(
N)) {
1088 int64_t RHSC =
RHS->getSExtValue();
1090 int64_t
Range = 0x1LL << (BW - 1);
1092 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1093 RHSC < (
Range << Scale)) {
1094 Base =
N.getOperand(0);
1099 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1104 uint64_t RHSC =
RHS->getZExtValue();
1106 uint64_t
Range = 0x1ULL << BW;
1108 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1109 Base =
N.getOperand(0);
1114 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1125 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1132bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1135 const DataLayout &
DL = CurDAG->getDataLayout();
1136 const TargetLowering *TLI = getTargetLowering();
1140 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1145 GlobalAddressSDNode *GAN =
1147 Base =
N.getOperand(0);
1157 if (CurDAG->isBaseWithConstantOffset(
N)) {
1159 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1162 Base =
N.getOperand(0);
1167 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1175 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1183 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1192bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1195 if (!CurDAG->isBaseWithConstantOffset(
N))
1198 int64_t RHSC =
RHS->getSExtValue();
1199 if (RHSC >= -256 && RHSC < 256) {
1200 Base =
N.getOperand(0);
1203 const TargetLowering *TLI = getTargetLowering();
1204 Base = CurDAG->getTargetFrameIndex(
1207 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1217 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1224bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1244 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1250 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1253 return isWorthFoldingAddr(
N,
Size);
1256bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1274 const SDNode *
Node =
N.getNode();
1275 for (SDNode *UI :
Node->users()) {
1281 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1284 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1287 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1292 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1295 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1300 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1304 if (IsExtendedRegisterWorthFolding &&
1311 if (isWorthFoldingAddr(
LHS,
Size))
1316 if (IsExtendedRegisterWorthFolding &&
1323 if (isWorthFoldingAddr(
RHS,
Size))
1335 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1338 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1340 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1341 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1345bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1358 const SDNode *
Node =
N.getNode();
1359 for (SDNode *UI :
Node->users()) {
1376 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1386 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1393 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1396 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1399 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1404 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1407 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1414 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1415 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1421 static const unsigned RegClassIDs[] = {
1422 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1423 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1424 AArch64::dsub2, AArch64::dsub3};
1430 static const unsigned RegClassIDs[] = {
1431 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1432 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1433 AArch64::qsub2, AArch64::qsub3};
1439 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1440 AArch64::ZPR3RegClassID,
1441 AArch64::ZPR4RegClassID};
1442 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1443 AArch64::zsub2, AArch64::zsub3};
1453 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1454 AArch64::ZPR4Mul4RegClassID};
1455 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1456 AArch64::zsub2, AArch64::zsub3};
1461 const unsigned RegClassIDs[],
1462 const unsigned SubRegs[]) {
1465 if (Regs.
size() == 1)
1476 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1479 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1480 Ops.push_back(Regs[i]);
1481 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1485 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1489void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1492 EVT VT =
N->getValueType(0);
1494 unsigned ExtOff = isExt;
1497 unsigned Vec0Off = ExtOff + 1;
1503 Ops.push_back(
N->getOperand(1));
1504 Ops.push_back(RegSeq);
1505 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1506 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1509static std::tuple<SDValue, SDValue>
1530 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1535 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1537 return std::make_tuple(
1542void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1547 SDValue AUTDisc =
N->getOperand(3);
1550 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1552 SDValue AUTAddrDisc, AUTConstDisc;
1553 std::tie(AUTConstDisc, AUTAddrDisc) =
1557 SDValue Ops[] = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1560 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1561 ReplaceNode(
N, AUT);
1563 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1564 AArch64::X16, Val,
SDValue());
1567 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1568 ReplaceNode(
N, AUT);
1572void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1584 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1585 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1587 SDValue AUTAddrDisc, AUTConstDisc;
1588 std::tie(AUTConstDisc, AUTAddrDisc) =
1591 SDValue PACAddrDisc, PACConstDisc;
1592 std::tie(PACConstDisc, PACAddrDisc) =
1595 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1596 AArch64::X16, Val,
SDValue());
1598 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1599 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1601 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1602 ReplaceNode(
N, AUTPAC);
1605bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1607 if (
LD->isUnindexed())
1609 EVT VT =
LD->getMemoryVT();
1610 EVT DstVT =
N->getValueType(0);
1614 int OffsetVal = (int)
OffsetOp->getZExtValue();
1619 unsigned Opcode = 0;
1622 bool InsertTo64 =
false;
1624 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1625 else if (VT == MVT::i32) {
1627 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1629 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1631 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1637 }
else if (VT == MVT::i16) {
1639 if (DstVT == MVT::i64)
1640 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1642 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1644 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1645 InsertTo64 = DstVT == MVT::i64;
1650 }
else if (VT == MVT::i8) {
1652 if (DstVT == MVT::i64)
1653 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1655 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1657 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1658 InsertTo64 = DstVT == MVT::i64;
1663 }
else if (VT == MVT::f16) {
1664 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1665 }
else if (VT == MVT::bf16) {
1666 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1667 }
else if (VT == MVT::f32) {
1668 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1669 }
else if (VT == MVT::f64 ||
1671 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1673 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1675 if (IsPre || OffsetVal != 8)
1679 Opcode = AArch64::LD1Onev8b_POST;
1682 Opcode = AArch64::LD1Onev4h_POST;
1685 Opcode = AArch64::LD1Onev2s_POST;
1688 Opcode = AArch64::LD1Onev1d_POST;
1694 if (IsPre || OffsetVal != 16)
1698 Opcode = AArch64::LD1Onev16b_POST;
1701 Opcode = AArch64::LD1Onev8h_POST;
1704 Opcode = AArch64::LD1Onev4s_POST;
1707 Opcode = AArch64::LD1Onev2d_POST;
1719 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1720 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1722 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1732 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1734 SDValue(CurDAG->getMachineNode(
1735 AArch64::SUBREG_TO_REG, dl, MVT::i64,
1736 CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1741 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1744 CurDAG->RemoveDeadNode(
N);
1748void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1749 unsigned SubRegIdx) {
1751 EVT VT =
N->getValueType(0);
1757 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1759 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1761 for (
unsigned i = 0; i < NumVecs; ++i)
1763 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1770 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1774 CurDAG->RemoveDeadNode(
N);
1777void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1778 unsigned Opc,
unsigned SubRegIdx) {
1780 EVT VT =
N->getValueType(0);
1787 const EVT ResTys[] = {MVT::i64,
1788 MVT::Untyped, MVT::Other};
1790 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1798 ReplaceUses(
SDValue(
N, 0), SuperReg);
1800 for (
unsigned i = 0; i < NumVecs; ++i)
1802 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1806 CurDAG->RemoveDeadNode(
N);
1812std::tuple<unsigned, SDValue, SDValue>
1813AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1819 SDValue NewOffset = OldOffset;
1821 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1822 N, OldBase, NewBase, NewOffset);
1826 const bool IsRegReg =
1827 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1830 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
1843template <SelectTypeKind Kind>
1855 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
1860 if (EltVT != MVT::i1)
1864 if (EltVT == MVT::bf16)
1866 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
1896void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
1899 if (
Imm->getZExtValue() > 1)
1903 EVT VT =
N->getValueType(0);
1905 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1908 for (
unsigned I = 0;
I < 2; ++
I)
1909 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1910 AArch64::psub0 +
I,
DL, VT, SuperReg));
1912 CurDAG->RemoveDeadNode(
N);
1915void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
1917 EVT VT =
N->getValueType(0);
1921 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1924 for (
unsigned I = 0;
I < 2; ++
I)
1925 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1926 AArch64::psub0 +
I,
DL, VT, SuperReg));
1928 CurDAG->RemoveDeadNode(
N);
1931void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
1933 EVT VT =
N->getValueType(0);
1937 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
1939 for (
unsigned i = 0; i < NumVecs; ++i)
1940 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1941 AArch64::zsub0 + i,
DL, VT, SuperReg));
1943 CurDAG->RemoveDeadNode(
N);
1946void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
1949 EVT VT =
N->getValueType(0);
1951 Ops.push_back(
N->getOperand(0));
1954 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
1957 for (
unsigned i = 0; i < NumVecs; ++i)
1958 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1959 AArch64::zsub0 + i,
DL, VT, SuperReg));
1962 unsigned ChainIdx = NumVecs;
1964 CurDAG->RemoveDeadNode(
N);
1967void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
1972 assert(Opcode != 0 &&
"Unexpected opcode");
1975 EVT VT =
N->getValueType(0);
1976 unsigned FirstVecIdx = HasPred ? 2 : 1;
1978 auto GetMultiVecOperand = [=](
unsigned StartIdx) {
1980 return createZMulTuple(Regs);
1983 SDValue Zdn = GetMultiVecOperand(FirstVecIdx);
1987 Zm = GetMultiVecOperand(NumVecs + FirstVecIdx);
1993 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
1994 N->getOperand(1), Zdn, Zm);
1996 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped, Zdn, Zm);
1998 for (
unsigned i = 0; i < NumVecs; ++i)
1999 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2000 AArch64::zsub0 + i,
DL, VT, SuperReg));
2002 CurDAG->RemoveDeadNode(
N);
2005void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2006 unsigned Scale,
unsigned Opc_ri,
2007 unsigned Opc_rr,
bool IsIntr) {
2008 assert(Scale < 5 &&
"Invalid scaling value.");
2010 EVT VT =
N->getValueType(0);
2017 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2018 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2024 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2026 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2028 for (
unsigned i = 0; i < NumVecs; ++i)
2029 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2030 AArch64::zsub0 + i,
DL, VT, SuperReg));
2033 unsigned ChainIdx = NumVecs;
2035 CurDAG->RemoveDeadNode(
N);
2038void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2043 assert(Scale < 4 &&
"Invalid scaling value.");
2045 EVT VT =
N->getValueType(0);
2053 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2059 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2061 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2063 for (
unsigned i = 0; i < NumVecs; ++i)
2064 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2065 AArch64::zsub0 + i,
DL, VT, SuperReg));
2068 unsigned ChainIdx = NumVecs;
2070 CurDAG->RemoveDeadNode(
N);
2073void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2075 if (
N->getValueType(0) != MVT::nxv4f32)
2077 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2080void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2081 unsigned NumOutVecs,
2085 if (
Imm->getZExtValue() > MaxImm)
2089 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2094 EVT VT =
Node->getValueType(0);
2097 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2100 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2101 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2102 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2105 unsigned ChainIdx = NumOutVecs;
2107 CurDAG->RemoveDeadNode(Node);
2110void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2111 unsigned NumOutVecs,
2116 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2119 Ops.push_back(ZtValue);
2120 Ops.push_back(createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}));
2122 EVT VT =
Node->getValueType(0);
2125 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2128 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2129 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2130 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2133 unsigned ChainIdx = NumOutVecs;
2135 CurDAG->RemoveDeadNode(Node);
2138void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2141 EVT VT =
N->getValueType(0);
2144 SDValue Zd = createZMulTuple(Regs);
2145 SDValue Zn =
N->getOperand(1 + NumVecs);
2152 for (
unsigned i = 0; i < NumVecs; ++i)
2153 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2154 AArch64::zsub0 + i,
DL, VT, SuperReg));
2156 CurDAG->RemoveDeadNode(
N);
2186template <
unsigned MaxIdx,
unsigned Scale>
2187void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2188 unsigned BaseReg,
unsigned Op) {
2189 unsigned TileNum = 0;
2190 if (BaseReg != AArch64::ZA)
2191 TileNum =
N->getConstantOperandVal(2);
2197 if (BaseReg == AArch64::ZA)
2202 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2208 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2210 EVT VT =
N->getValueType(0);
2211 for (
unsigned I = 0;
I < NumVecs; ++
I)
2213 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2216 unsigned ChainIdx = NumVecs;
2218 CurDAG->RemoveDeadNode(
N);
2221void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2222 unsigned Op,
unsigned MaxIdx,
2223 unsigned Scale,
unsigned BaseReg) {
2228 if (BaseReg != AArch64::ZA)
2232 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2239 if (BaseReg != AArch64::ZA )
2240 Ops.push_back(
N->getOperand(2));
2243 Ops.push_back(
N->getOperand(0));
2244 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2246 EVT VT =
N->getValueType(0);
2247 for (
unsigned I = 0;
I < NumVecs; ++
I)
2249 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2253 unsigned ChainIdx = NumVecs;
2255 CurDAG->RemoveDeadNode(
N);
2258void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2259 unsigned NumOutVecs,
2263 EVT VT =
N->getValueType(0);
2264 unsigned NumInVecs =
N->getNumOperands() - 1;
2268 assert((NumInVecs == 2 || NumInVecs == 4) &&
2269 "Don't know how to handle multi-register input!");
2271 Ops.push_back(createZMulTuple(Regs));
2274 for (
unsigned I = 0;
I < NumInVecs;
I++)
2275 Ops.push_back(
N->getOperand(1 +
I));
2278 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2281 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2282 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2283 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2284 CurDAG->RemoveDeadNode(
N);
2287void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2290 EVT VT =
N->getOperand(2)->getValueType(0);
2298 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2307void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2308 unsigned Scale,
unsigned Opc_rr,
2314 SDValue RegSeq = createZTuple(Regs);
2320 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2321 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2327 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2335 const DataLayout &
DL = CurDAG->getDataLayout();
2336 const TargetLowering *TLI = getTargetLowering();
2340 int FI = FINode->getIndex();
2342 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2349void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2352 EVT VT =
N->getOperand(2)->getValueType(0);
2353 const EVT ResTys[] = {MVT::i64,
2365 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2405void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2408 EVT VT =
N->getValueType(0);
2420 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2422 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2424 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2426 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2430 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2431 AArch64::qsub2, AArch64::qsub3 };
2432 for (
unsigned i = 0; i < NumVecs; ++i) {
2433 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2440 CurDAG->RemoveDeadNode(
N);
2443void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2446 EVT VT =
N->getValueType(0);
2458 const EVT ResTys[] = {MVT::i64,
2461 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2464 CurDAG->getTargetConstant(LaneNo, dl,
2469 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2481 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2482 AArch64::qsub2, AArch64::qsub3 };
2483 for (
unsigned i = 0; i < NumVecs; ++i) {
2484 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2494 CurDAG->RemoveDeadNode(
N);
2497void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2500 EVT VT =
N->getOperand(2)->getValueType(0);
2512 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2514 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2516 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2525void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2528 EVT VT =
N->getOperand(2)->getValueType(0);
2540 const EVT ResTys[] = {MVT::i64,
2543 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2545 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2549 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2560 unsigned &LSB,
unsigned &MSB,
2561 unsigned NumberOfIgnoredLowBits,
2562 bool BiggerPattern) {
2564 "N must be a AND operation to call this function");
2566 EVT VT =
N->getValueType(0);
2571 assert((VT == MVT::i32 || VT == MVT::i64) &&
2572 "Type checking must have been done before calling this function");
2586 const SDNode *Op0 =
N->getOperand(0).getNode();
2593 if (AndImm & (AndImm + 1))
2596 bool ClampMSB =
false;
2616 ClampMSB = (VT == MVT::i32);
2617 }
else if (BiggerPattern) {
2623 Opd0 =
N->getOperand(0);
2629 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2632 <<
": Found large shift immediate, this should not happen\n"));
2646 MSB = MSB > 31 ? 31 : MSB;
2648 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2653 SDValue &Opd0,
unsigned &Immr,
2657 EVT VT =
N->getValueType(0);
2659 assert((VT == MVT::i32 || VT == MVT::i64) &&
2660 "Type checking must have been done before calling this function");
2664 Op =
Op->getOperand(0);
2665 VT =
Op->getValueType(0);
2674 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2678 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2679 Opd0 =
Op.getOperand(0);
2681 Imms = ShiftImm + Width - 1;
2709 Opd0 =
N->getOperand(0).getOperand(0);
2719 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2726 unsigned &Immr,
unsigned &Imms,
2727 bool BiggerPattern) {
2729 "N must be a SHR/SRA operation to call this function");
2731 EVT VT =
N->getValueType(0);
2736 assert((VT == MVT::i32 || VT == MVT::i64) &&
2737 "Type checking must have been done before calling this function");
2747 Opd0 =
N->getOperand(0).getOperand(0);
2748 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2754 Opd0 =
N->getOperand(0).getOperand(0);
2757 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2758 }
else if (BiggerPattern) {
2762 Opd0 =
N->getOperand(0);
2771 <<
": Found large shift immediate, this should not happen\n"));
2780 "bad amount in shift node!");
2781 int immr = SrlImm - ShlImm;
2786 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2788 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2792bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2795 EVT VT =
N->getValueType(0);
2796 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2797 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2808 unsigned Immr = ShiftImm;
2810 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2811 CurDAG->getTargetConstant(Imms, dl, VT)};
2812 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2817 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2818 unsigned NumberOfIgnoredLowBits = 0,
2819 bool BiggerPattern =
false) {
2820 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2823 switch (
N->getOpcode()) {
2825 if (!
N->isMachineOpcode())
2830 NumberOfIgnoredLowBits, BiggerPattern);
2839 unsigned NOpc =
N->getMachineOpcode();
2843 case AArch64::SBFMWri:
2844 case AArch64::UBFMWri:
2845 case AArch64::SBFMXri:
2846 case AArch64::UBFMXri:
2848 Opd0 =
N->getOperand(0);
2849 Immr =
N->getConstantOperandVal(1);
2850 Imms =
N->getConstantOperandVal(2);
2857bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2858 unsigned Opc, Immr, Imms;
2863 EVT VT =
N->getValueType(0);
2868 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2869 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2870 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2872 SDNode *
BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2873 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2879 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2880 CurDAG->getTargetConstant(Imms, dl, VT)};
2881 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2890 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2891 assert((VT == MVT::i32 || VT == MVT::i64) &&
2892 "i32 or i64 mask type expected!");
2896 APInt SignificantDstMask =
2900 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2901 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2934 APInt OpUsefulBits(UsefulBits);
2938 OpUsefulBits <<= MSB - Imm + 1;
2943 OpUsefulBits <<= Imm;
2945 OpUsefulBits <<= MSB + 1;
2948 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2954 UsefulBits &= OpUsefulBits;
2971 APInt Mask(UsefulBits);
2972 Mask.clearAllBits();
2980 Mask.lshrInPlace(ShiftAmt);
2986 Mask.lshrInPlace(ShiftAmt);
3002 APInt OpUsefulBits(UsefulBits);
3016 OpUsefulBits <<= Width;
3019 if (
Op.getOperand(1) == Orig) {
3021 Mask = ResultUsefulBits & OpUsefulBits;
3025 if (
Op.getOperand(0) == Orig)
3027 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3033 OpUsefulBits <<= Width;
3035 OpUsefulBits <<= LSB;
3037 if (
Op.getOperand(1) == Orig) {
3039 Mask = ResultUsefulBits & OpUsefulBits;
3040 Mask.lshrInPlace(LSB);
3043 if (
Op.getOperand(0) == Orig)
3044 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3061 case AArch64::ANDSWri:
3062 case AArch64::ANDSXri:
3063 case AArch64::ANDWri:
3064 case AArch64::ANDXri:
3068 case AArch64::UBFMWri:
3069 case AArch64::UBFMXri:
3072 case AArch64::ORRWrs:
3073 case AArch64::ORRXrs:
3078 case AArch64::BFMWri:
3079 case AArch64::BFMXri:
3082 case AArch64::STRBBui:
3083 case AArch64::STURBBi:
3089 case AArch64::STRHHui:
3090 case AArch64::STURHHi:
3103 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3105 UsefulBits =
APInt(Bitwidth, 0);
3114 UsersUsefulBits |= UsefulBitsForUse;
3119 UsefulBits &= UsersUsefulBits;
3129 EVT VT =
Op.getValueType();
3132 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3135 if (ShlAmount > 0) {
3138 UBFMOpc, dl, VT,
Op,
3143 assert(ShlAmount < 0 &&
"expected right shift");
3144 int ShrAmount = -ShlAmount;
3156 const uint64_t NonZeroBits,
3163 const uint64_t NonZeroBits,
3170 bool BiggerPattern,
SDValue &Src,
3171 int &DstLSB,
int &Width) {
3172 EVT VT =
Op.getValueType();
3181 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3185 switch (
Op.getOpcode()) {
3190 NonZeroBits, Src, DstLSB, Width);
3193 NonZeroBits, Src, DstLSB, Width);
3206 EVT VT =
Op.getValueType();
3207 assert((VT == MVT::i32 || VT == MVT::i64) &&
3208 "Caller guarantees VT is one of i32 or i64");
3221 assert((~AndImm & NonZeroBits) == 0 &&
3222 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3251 if (!BiggerPattern && !AndOp0.
hasOneUse())
3270 <<
"Found large Width in bit-field-positioning -- this indicates no "
3271 "proper combining / constant folding was performed\n");
3280 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3295 "Op.getNode() should be a SHL node to call this function");
3297 "Op.getNode() should shift ShlImm to call this function");
3304 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3328 EVT VT =
Op.getValueType();
3329 assert((VT == MVT::i32 || VT == MVT::i64) &&
3330 "Caller guarantees that type is i32 or i64");
3337 if (!BiggerPattern && !
Op.hasOneUse())
3346 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3354 assert(VT == MVT::i32 || VT == MVT::i64);
3365 EVT VT =
N->getValueType(0);
3366 if (VT != MVT::i32 && VT != MVT::i64)
3384 if (!
And.hasOneUse() ||
3394 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3401 if ((OrImm & NotKnownZero) != 0) {
3413 unsigned ImmS = Width - 1;
3419 bool IsBFI = LSB != 0;
3424 unsigned OrChunks = 0, BFIChunks = 0;
3425 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3426 if (((OrImm >> Shift) & 0xFFFF) != 0)
3428 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3431 if (BFIChunks > OrChunks)
3437 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3445 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3454 if (!Dst.hasOneUse())
3457 EVT VT = Dst.getValueType();
3458 assert((VT == MVT::i32 || VT == MVT::i64) &&
3459 "Caller should guarantee that VT is one of i32 or i64");
3487 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3488 unsigned MaskWidth =
3491 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3497 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3498 ShiftedOperand =
SDValue(UBFMNode, 0);
3527 const bool BiggerPattern) {
3528 EVT VT =
N->getValueType(0);
3529 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3530 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3531 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3532 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3533 assert((VT == MVT::i32 || VT == MVT::i64) &&
3534 "Expect result type to be i32 or i64 since N is combinable to BFM");
3541 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3544 if (BiggerPattern) {
3567 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3629 EVT VT =
N->getValueType(0);
3630 if (VT != MVT::i32 && VT != MVT::i64)
3638 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3639 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3659 for (
int I = 0;
I < 4; ++
I) {
3662 unsigned ImmR, ImmS;
3663 bool BiggerPattern =
I / 2;
3664 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3666 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3672 NumberOfIgnoredLowBits, BiggerPattern)) {
3675 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3676 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3681 Width = ImmS - ImmR + 1;
3692 Src, DstLSB, Width)) {
3700 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3710 APInt BitsToBeInserted =
3713 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3737 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3770 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3772 if (Src->hasOneUse() &&
3775 Src = Src->getOperand(0);
3785 unsigned ImmS = Width - 1;
3791 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3799bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3808 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3821bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3825 EVT VT =
N->getValueType(0);
3826 if (VT != MVT::i32 && VT != MVT::i64)
3832 Op0, DstLSB, Width))
3838 unsigned ImmS = Width - 1;
3841 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3842 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3843 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3844 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3850bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3851 EVT VT =
N->getValueType(0);
3854 switch (
N->getOpcode()) {
3856 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3859 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3862 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3865 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3873 if (VT == MVT::i32) {
3876 }
else if (VT == MVT::i64) {
3882 SDValue ShiftAmt =
N->getOperand(1);
3902 (Add0Imm %
Size == 0)) {
3908 if (SubVT == MVT::i32) {
3909 NegOpc = AArch64::SUBWrr;
3910 ZeroReg = AArch64::WZR;
3912 assert(SubVT == MVT::i64);
3913 NegOpc = AArch64::SUBXrr;
3914 ZeroReg = AArch64::XZR;
3917 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3918 MachineSDNode *Neg =
3919 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3920 NewShiftAmt =
SDValue(Neg, 0);
3928 if (SubVT == MVT::i32) {
3929 NotOpc = AArch64::ORNWrr;
3930 ZeroReg = AArch64::WZR;
3932 assert(SubVT == MVT::i64);
3933 NotOpc = AArch64::ORNXrr;
3934 ZeroReg = AArch64::XZR;
3937 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3938 MachineSDNode *
Not =
3939 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3940 NewShiftAmt =
SDValue(Not, 0);
3961 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3962 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3963 MachineSDNode *
Ext = CurDAG->getMachineNode(
3964 AArch64::SUBREG_TO_REG,
DL, VT,
3965 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3966 NewShiftAmt =
SDValue(Ext, 0);
3970 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3977 bool isReciprocal) {
3980 FVal = CN->getValueAPF();
3983 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4012 if (!IsExact || !IntVal.isPowerOf2())
4014 unsigned FBits = IntVal.logBase2();
4018 if (FBits == 0 || FBits > RegWidth)
return false;
4024bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4025 unsigned RegWidth) {
4030bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4032 unsigned RegWidth) {
4042 RegString.
split(Fields,
':');
4044 if (Fields.
size() == 1)
4048 &&
"Invalid number of fields in read register string");
4051 bool AllIntFields =
true;
4055 AllIntFields &= !
Field.getAsInteger(10, IntField);
4056 Ops.push_back(IntField);
4060 "Unexpected non-integer value in special register string.");
4065 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4066 (
Ops[3] << 3) | (
Ops[4]);
4073bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4075 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4078 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4080 unsigned Opcode64Bit = AArch64::MRS;
4085 const auto *TheReg =
4086 AArch64SysReg::lookupSysRegByName(RegString->getString());
4087 if (TheReg && TheReg->Readable &&
4088 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4089 Imm = TheReg->Encoding;
4095 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4096 Opcode64Bit = AArch64::ADR;
4104 SDValue InChain =
N->getOperand(0);
4105 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4106 if (!ReadIs128Bit) {
4107 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4108 {SysRegImm, InChain});
4110 SDNode *MRRS = CurDAG->getMachineNode(
4112 {MVT::Untyped , MVT::Other },
4113 {SysRegImm, InChain});
4117 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4119 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4125 ReplaceUses(
SDValue(
N, 2), OutChain);
4134bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4136 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4139 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4141 if (!WriteIs128Bit) {
4147 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4150 "Expected a constant integer expression.");
4151 unsigned Reg = PMapper->Encoding;
4152 uint64_t Immed =
N->getConstantOperandVal(2);
4153 CurDAG->SelectNodeTo(
4154 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4155 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4161 if (trySelectPState(
4162 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4163 AArch64::MSRpstateImm4))
4165 if (trySelectPState(
4166 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4167 AArch64::MSRpstateImm1))
4176 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4177 if (TheReg && TheReg->Writeable &&
4178 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4179 Imm = TheReg->Encoding;
4188 if (!WriteIs128Bit) {
4189 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4190 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4191 N->getOperand(2), InChain);
4195 SDNode *Pair = CurDAG->getMachineNode(
4196 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4197 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4200 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4202 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4204 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4205 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4213bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4218 if (Subtarget->hasLSE())
return false;
4220 if (MemTy == MVT::i8)
4221 Opcode = AArch64::CMP_SWAP_8;
4222 else if (MemTy == MVT::i16)
4223 Opcode = AArch64::CMP_SWAP_16;
4224 else if (MemTy == MVT::i32)
4225 Opcode = AArch64::CMP_SWAP_32;
4226 else if (MemTy == MVT::i64)
4227 Opcode = AArch64::CMP_SWAP_64;
4231 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4232 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4234 SDNode *CmpSwap = CurDAG->getMachineNode(
4236 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4243 CurDAG->RemoveDeadNode(
N);
4248bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4249 SDValue &Shift,
bool Negate) {
4263 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4270 if ((Val & ~0xff) == 0) {
4271 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4276 if ((Val & ~0xff00) == 0) {
4277 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4289bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4313 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4314 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4321 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4322 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4326 if (Val <= 65280 && Val % 256 == 0) {
4327 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4328 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4339bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4353 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4354 Imm = CurDAG->getTargetConstant(Val & 0xFF,
DL, MVT::i32);
4360 if (Val >= -128 && Val <= 127) {
4361 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4362 Imm = CurDAG->getTargetConstant(Val & 0xFF,
DL, MVT::i32);
4366 if (Val >= -32768 && Val <= 32512 && Val % 256 == 0) {
4367 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4368 Imm = CurDAG->getTargetConstant((Val >> 8) & 0xFF,
DL, MVT::i32);
4379bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4381 int64_t ImmVal = CNode->getSExtValue();
4383 if (ImmVal >= -128 && ImmVal < 128) {
4384 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4391bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4393 uint64_t ImmVal = CNode->getZExtValue();
4403 ImmVal &= 0xFFFFFFFF;
4412 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4419bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4422 uint64_t ImmVal = CNode->getZExtValue();
4432 ImmVal |= ImmVal << 8;
4433 ImmVal |= ImmVal << 16;
4434 ImmVal |= ImmVal << 32;
4438 ImmVal |= ImmVal << 16;
4439 ImmVal |= ImmVal << 32;
4442 ImmVal &= 0xFFFFFFFF;
4443 ImmVal |= ImmVal << 32;
4453 Imm = CurDAG->getTargetConstant(encoding,
DL, MVT::i64);
4465bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4466 uint64_t
High,
bool AllowSaturation,
4469 uint64_t ImmVal = CN->getZExtValue();
4476 if (ImmVal >
High) {
4477 if (!AllowSaturation)
4482 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4489bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4503 const TargetLowering *TLI = getTargetLowering();
4506 SDValue FiOp = CurDAG->getTargetFrameIndex(
4508 int TagOffset =
N->getConstantOperandVal(3);
4510 SDNode *Out = CurDAG->getMachineNode(
4511 AArch64::TAGPstack,
DL, MVT::i64,
4512 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4513 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4514 ReplaceNode(
N, Out);
4518void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4520 "llvm.aarch64.tagp third argument must be an immediate");
4521 if (trySelectStackSlotTagP(
N))
4528 int TagOffset =
N->getConstantOperandVal(3);
4529 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4530 {
N->getOperand(1),
N->getOperand(2)});
4531 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4532 {
SDValue(N1, 0),
N->getOperand(2)});
4533 SDNode *N3 = CurDAG->getMachineNode(
4534 AArch64::ADDG,
DL, MVT::i64,
4535 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4536 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4540bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4544 if (
N->getConstantOperandVal(2) != 0)
4546 if (!
N->getOperand(0).isUndef())
4550 EVT VT =
N->getValueType(0);
4551 EVT InVT =
N->getOperand(1).getValueType();
4562 "Expected to insert into a packed scalable vector!");
4565 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4566 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4567 N->getOperand(1), RC));
4571bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4575 if (
N->getConstantOperandVal(1) != 0)
4579 EVT VT =
N->getValueType(0);
4580 EVT InVT =
N->getOperand(0).getValueType();
4591 "Expected to extract from a packed scalable vector!");
4594 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4595 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4596 N->getOperand(0), RC));
4600bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4606 EVT VT =
N->getValueType(0);
4619 (Subtarget->hasSVE2() ||
4620 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4621 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4624 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4628 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4629 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4630 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4637 bool IsXOROperand =
true;
4639 IsXOROperand =
false;
4645 APInt ShlAmt, ShrAmt;
4653 if (!IsXOROperand) {
4655 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4658 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4659 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4660 VT, Zero, MOVIV, ZSub);
4671 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4672 AArch64::XAR_ZZZI_D})) {
4673 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4698 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4708 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4716 bool IsXOROperand =
true;
4718 IsXOROperand =
false;
4721 R1 =
XOR.getOperand(0);
4722 R2 =
XOR.getOperand(1);
4732 if (ShAmt + HsAmt != VTSizeInBits)
4735 if (!IsXOROperand) {
4738 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4747 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4753 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4754 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4756 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4759 if (
R2.getValueType() == VT)
4760 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4768 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4773 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4779 SDNode *XAR =
nullptr;
4783 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4784 AArch64::XAR_ZZZI_D}))
4785 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4787 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4790 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4796 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4797 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4800 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4801 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4807 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4811 ReplaceNode(
N, XAR);
4815void AArch64DAGToDAGISel::Select(SDNode *Node) {
4817 if (
Node->isMachineOpcode()) {
4819 Node->setNodeId(-1);
4824 EVT VT =
Node->getValueType(0);
4826 switch (
Node->getOpcode()) {
4830 case ISD::ATOMIC_CMP_SWAP:
4831 if (SelectCMP_SWAP(Node))
4836 case AArch64ISD::MRRS:
4837 if (tryReadRegister(Node))
4842 case AArch64ISD::MSRR:
4843 if (tryWriteRegister(Node))
4850 if (tryIndexedLoad(Node))
4859 if (tryBitfieldExtractOp(Node))
4861 if (tryBitfieldInsertInZeroOp(Node))
4866 if (tryShiftAmountMod(Node))
4871 if (tryBitfieldExtractOpFromSExt(Node))
4876 if (tryBitfieldInsertOp(Node))
4878 if (trySelectXAR(Node))
4883 if (trySelectCastScalableToFixedLengthVector(Node))
4889 if (trySelectCastFixedLengthToScalableVector(Node))
4898 if (ConstNode->
isZero()) {
4899 if (VT == MVT::i32) {
4901 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4902 ReplaceNode(Node,
New.getNode());
4904 }
else if (VT == MVT::i64) {
4906 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4907 ReplaceNode(Node,
New.getNode());
4918 const TargetLowering *TLI = getTargetLowering();
4919 SDValue TFI = CurDAG->getTargetFrameIndex(
4922 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4923 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4924 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4928 unsigned IntNo =
Node->getConstantOperandVal(1);
4932 case Intrinsic::aarch64_gcsss: {
4936 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4938 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4939 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4940 MVT::Other, Zero,
SDValue(SS1, 0));
4941 ReplaceNode(Node, SS2);
4944 case Intrinsic::aarch64_ldaxp:
4945 case Intrinsic::aarch64_ldxp: {
4947 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4952 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4953 MVT::Other, MemAddr, Chain);
4956 MachineMemOperand *MemOp =
4959 ReplaceNode(Node, Ld);
4962 case Intrinsic::aarch64_stlxp:
4963 case Intrinsic::aarch64_stxp: {
4965 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4973 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4975 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4977 MachineMemOperand *MemOp =
4981 ReplaceNode(Node, St);
4984 case Intrinsic::aarch64_neon_ld1x2:
4985 if (VT == MVT::v8i8) {
4986 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4988 }
else if (VT == MVT::v16i8) {
4989 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4991 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4992 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4994 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4995 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4997 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4998 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5000 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5001 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5003 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5004 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5006 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5007 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5011 case Intrinsic::aarch64_neon_ld1x3:
5012 if (VT == MVT::v8i8) {
5013 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5015 }
else if (VT == MVT::v16i8) {
5016 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5018 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5019 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5021 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5022 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5024 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5025 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5027 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5028 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5030 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5031 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5033 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5034 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5038 case Intrinsic::aarch64_neon_ld1x4:
5039 if (VT == MVT::v8i8) {
5040 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5042 }
else if (VT == MVT::v16i8) {
5043 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5045 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5046 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5048 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5049 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5051 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5052 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5054 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5055 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5057 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5058 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5060 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5061 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5065 case Intrinsic::aarch64_neon_ld2:
5066 if (VT == MVT::v8i8) {
5067 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5069 }
else if (VT == MVT::v16i8) {
5070 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5072 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5073 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5075 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5076 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5078 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5079 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5081 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5082 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5084 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5085 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5087 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5088 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5092 case Intrinsic::aarch64_neon_ld3:
5093 if (VT == MVT::v8i8) {
5094 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5096 }
else if (VT == MVT::v16i8) {
5097 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5099 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5100 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5102 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5103 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5105 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5106 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5108 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5109 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5111 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5112 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5114 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5115 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5119 case Intrinsic::aarch64_neon_ld4:
5120 if (VT == MVT::v8i8) {
5121 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5123 }
else if (VT == MVT::v16i8) {
5124 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5126 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5127 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5129 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5130 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5132 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5133 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5135 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5136 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5138 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5139 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5141 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5142 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5146 case Intrinsic::aarch64_neon_ld2r:
5147 if (VT == MVT::v8i8) {
5148 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5150 }
else if (VT == MVT::v16i8) {
5151 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5153 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5154 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5156 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5157 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5159 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5160 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5162 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5163 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5165 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5166 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5168 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5169 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5173 case Intrinsic::aarch64_neon_ld3r:
5174 if (VT == MVT::v8i8) {
5175 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5177 }
else if (VT == MVT::v16i8) {
5178 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5180 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5181 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5183 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5184 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5186 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5187 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5189 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5190 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5192 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5193 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5195 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5196 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5200 case Intrinsic::aarch64_neon_ld4r:
5201 if (VT == MVT::v8i8) {
5202 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5204 }
else if (VT == MVT::v16i8) {
5205 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5207 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5208 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5210 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5211 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5213 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5214 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5216 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5217 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5219 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5220 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5222 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5223 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5227 case Intrinsic::aarch64_neon_ld2lane:
5228 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5229 SelectLoadLane(Node, 2, AArch64::LD2i8);
5231 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5232 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5233 SelectLoadLane(Node, 2, AArch64::LD2i16);
5235 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5237 SelectLoadLane(Node, 2, AArch64::LD2i32);
5239 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5241 SelectLoadLane(Node, 2, AArch64::LD2i64);
5245 case Intrinsic::aarch64_neon_ld3lane:
5246 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5247 SelectLoadLane(Node, 3, AArch64::LD3i8);
5249 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5250 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5251 SelectLoadLane(Node, 3, AArch64::LD3i16);
5253 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5255 SelectLoadLane(Node, 3, AArch64::LD3i32);
5257 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5259 SelectLoadLane(Node, 3, AArch64::LD3i64);
5263 case Intrinsic::aarch64_neon_ld4lane:
5264 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5265 SelectLoadLane(Node, 4, AArch64::LD4i8);
5267 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5268 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5269 SelectLoadLane(Node, 4, AArch64::LD4i16);
5271 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5273 SelectLoadLane(Node, 4, AArch64::LD4i32);
5275 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5277 SelectLoadLane(Node, 4, AArch64::LD4i64);
5281 case Intrinsic::aarch64_ld64b:
5282 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5284 case Intrinsic::aarch64_sve_ld2q_sret: {
5285 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5288 case Intrinsic::aarch64_sve_ld3q_sret: {
5289 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5292 case Intrinsic::aarch64_sve_ld4q_sret: {
5293 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5296 case Intrinsic::aarch64_sve_ld2_sret: {
5297 if (VT == MVT::nxv16i8) {
5298 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5301 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5302 VT == MVT::nxv8bf16) {
5303 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5306 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5307 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5310 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5311 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5317 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5318 if (VT == MVT::nxv16i8) {
5319 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5320 SelectContiguousMultiVectorLoad(
5321 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5322 else if (Subtarget->hasSVE2p1())
5323 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5328 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5329 VT == MVT::nxv8bf16) {
5330 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5331 SelectContiguousMultiVectorLoad(
5332 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5333 else if (Subtarget->hasSVE2p1())
5334 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5339 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5340 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5341 SelectContiguousMultiVectorLoad(
5342 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5343 else if (Subtarget->hasSVE2p1())
5344 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5349 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5350 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5351 SelectContiguousMultiVectorLoad(
5352 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5353 else if (Subtarget->hasSVE2p1())
5354 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5362 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5363 if (VT == MVT::nxv16i8) {
5364 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5365 SelectContiguousMultiVectorLoad(
5366 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5367 else if (Subtarget->hasSVE2p1())
5368 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5373 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5374 VT == MVT::nxv8bf16) {
5375 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5376 SelectContiguousMultiVectorLoad(
5377 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5378 else if (Subtarget->hasSVE2p1())
5379 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5384 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5385 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5386 SelectContiguousMultiVectorLoad(
5387 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5388 else if (Subtarget->hasSVE2p1())
5389 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5394 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5395 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5396 SelectContiguousMultiVectorLoad(
5397 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5398 else if (Subtarget->hasSVE2p1())
5399 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5407 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5408 if (VT == MVT::nxv16i8) {
5409 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5410 SelectContiguousMultiVectorLoad(Node, 2, 0,
5411 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5412 AArch64::LDNT1B_2Z_PSEUDO);
5413 else if (Subtarget->hasSVE2p1())
5414 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5415 AArch64::LDNT1B_2Z);
5419 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5420 VT == MVT::nxv8bf16) {
5421 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5422 SelectContiguousMultiVectorLoad(Node, 2, 1,
5423 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5424 AArch64::LDNT1H_2Z_PSEUDO);
5425 else if (Subtarget->hasSVE2p1())
5426 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5427 AArch64::LDNT1H_2Z);
5431 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5432 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5433 SelectContiguousMultiVectorLoad(Node, 2, 2,
5434 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5435 AArch64::LDNT1W_2Z_PSEUDO);
5436 else if (Subtarget->hasSVE2p1())
5437 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5438 AArch64::LDNT1W_2Z);
5442 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5443 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5444 SelectContiguousMultiVectorLoad(Node, 2, 3,
5445 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5446 AArch64::LDNT1D_2Z_PSEUDO);
5447 else if (Subtarget->hasSVE2p1())
5448 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5449 AArch64::LDNT1D_2Z);
5456 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5457 if (VT == MVT::nxv16i8) {
5458 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5459 SelectContiguousMultiVectorLoad(Node, 4, 0,
5460 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5461 AArch64::LDNT1B_4Z_PSEUDO);
5462 else if (Subtarget->hasSVE2p1())
5463 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5464 AArch64::LDNT1B_4Z);
5468 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5469 VT == MVT::nxv8bf16) {
5470 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5471 SelectContiguousMultiVectorLoad(Node, 4, 1,
5472 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5473 AArch64::LDNT1H_4Z_PSEUDO);
5474 else if (Subtarget->hasSVE2p1())
5475 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5476 AArch64::LDNT1H_4Z);
5480 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5481 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5482 SelectContiguousMultiVectorLoad(Node, 4, 2,
5483 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5484 AArch64::LDNT1W_4Z_PSEUDO);
5485 else if (Subtarget->hasSVE2p1())
5486 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5487 AArch64::LDNT1W_4Z);
5491 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5492 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5493 SelectContiguousMultiVectorLoad(Node, 4, 3,
5494 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5495 AArch64::LDNT1D_4Z_PSEUDO);
5496 else if (Subtarget->hasSVE2p1())
5497 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5498 AArch64::LDNT1D_4Z);
5505 case Intrinsic::aarch64_sve_ld3_sret: {
5506 if (VT == MVT::nxv16i8) {
5507 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5510 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5511 VT == MVT::nxv8bf16) {
5512 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5515 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5516 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5519 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5520 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5526 case Intrinsic::aarch64_sve_ld4_sret: {
5527 if (VT == MVT::nxv16i8) {
5528 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5531 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5532 VT == MVT::nxv8bf16) {
5533 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5536 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5537 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5540 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5541 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5547 case Intrinsic::aarch64_sme_read_hor_vg2: {
5548 if (VT == MVT::nxv16i8) {
5549 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5550 AArch64::MOVA_2ZMXI_H_B);
5552 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5553 VT == MVT::nxv8bf16) {
5554 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5555 AArch64::MOVA_2ZMXI_H_H);
5557 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5558 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5559 AArch64::MOVA_2ZMXI_H_S);
5561 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5562 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5563 AArch64::MOVA_2ZMXI_H_D);
5568 case Intrinsic::aarch64_sme_read_ver_vg2: {
5569 if (VT == MVT::nxv16i8) {
5570 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5571 AArch64::MOVA_2ZMXI_V_B);
5573 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5574 VT == MVT::nxv8bf16) {
5575 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5576 AArch64::MOVA_2ZMXI_V_H);
5578 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5579 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5580 AArch64::MOVA_2ZMXI_V_S);
5582 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5583 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5584 AArch64::MOVA_2ZMXI_V_D);
5589 case Intrinsic::aarch64_sme_read_hor_vg4: {
5590 if (VT == MVT::nxv16i8) {
5591 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5592 AArch64::MOVA_4ZMXI_H_B);
5594 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5595 VT == MVT::nxv8bf16) {
5596 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5597 AArch64::MOVA_4ZMXI_H_H);
5599 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5600 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5601 AArch64::MOVA_4ZMXI_H_S);
5603 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5604 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5605 AArch64::MOVA_4ZMXI_H_D);
5610 case Intrinsic::aarch64_sme_read_ver_vg4: {
5611 if (VT == MVT::nxv16i8) {
5612 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5613 AArch64::MOVA_4ZMXI_V_B);
5615 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5616 VT == MVT::nxv8bf16) {
5617 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5618 AArch64::MOVA_4ZMXI_V_H);
5620 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5621 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5622 AArch64::MOVA_4ZMXI_V_S);
5624 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5625 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5626 AArch64::MOVA_4ZMXI_V_D);
5631 case Intrinsic::aarch64_sme_read_vg1x2: {
5632 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5633 AArch64::MOVA_VG2_2ZMXI);
5636 case Intrinsic::aarch64_sme_read_vg1x4: {
5637 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5638 AArch64::MOVA_VG4_4ZMXI);
5641 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5642 if (VT == MVT::nxv16i8) {
5643 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5645 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5646 VT == MVT::nxv8bf16) {
5647 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5649 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5650 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5652 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5653 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5658 case Intrinsic::aarch64_sme_readz_vert_x2: {
5659 if (VT == MVT::nxv16i8) {
5660 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5662 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5663 VT == MVT::nxv8bf16) {
5664 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5666 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5667 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5669 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5670 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5675 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5676 if (VT == MVT::nxv16i8) {
5677 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5679 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5680 VT == MVT::nxv8bf16) {
5681 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5683 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5684 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5686 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5687 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5692 case Intrinsic::aarch64_sme_readz_vert_x4: {
5693 if (VT == MVT::nxv16i8) {
5694 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5696 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5697 VT == MVT::nxv8bf16) {
5698 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5700 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5701 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5703 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5704 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5709 case Intrinsic::aarch64_sme_readz_x2: {
5710 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5714 case Intrinsic::aarch64_sme_readz_x4: {
5715 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5719 case Intrinsic::swift_async_context_addr: {
5722 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5724 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5725 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5726 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5728 ReplaceUses(
SDValue(Node, 0), Res);
5730 CurDAG->RemoveDeadNode(Node);
5732 auto &MF = CurDAG->getMachineFunction();
5733 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5734 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5737 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5739 Node->getValueType(0),
5740 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5741 AArch64::LUTI2_4ZTZI_S}))
5743 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5746 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5748 Node->getValueType(0),
5749 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5751 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5754 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5756 Node->getValueType(0),
5757 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5758 AArch64::LUTI2_2ZTZI_S}))
5760 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5763 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5765 Node->getValueType(0),
5766 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5767 AArch64::LUTI4_2ZTZI_S}))
5769 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5772 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5773 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5776 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5778 Node->getValueType(0),
5779 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5780 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5782 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5784 Node->getValueType(0),
5785 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5786 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5788 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5790 Node->getValueType(0),
5791 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5792 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5794 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5796 Node->getValueType(0),
5797 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5798 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5803 unsigned IntNo =
Node->getConstantOperandVal(0);
5807 case Intrinsic::aarch64_tagp:
5811 case Intrinsic::ptrauth_auth:
5812 SelectPtrauthAuth(Node);
5815 case Intrinsic::ptrauth_resign:
5816 SelectPtrauthResign(Node);
5819 case Intrinsic::aarch64_neon_tbl2:
5820 SelectTable(Node, 2,
5821 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5824 case Intrinsic::aarch64_neon_tbl3:
5825 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5826 : AArch64::TBLv16i8Three,
5829 case Intrinsic::aarch64_neon_tbl4:
5830 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5831 : AArch64::TBLv16i8Four,
5834 case Intrinsic::aarch64_neon_tbx2:
5835 SelectTable(Node, 2,
5836 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5839 case Intrinsic::aarch64_neon_tbx3:
5840 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5841 : AArch64::TBXv16i8Three,
5844 case Intrinsic::aarch64_neon_tbx4:
5845 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5846 : AArch64::TBXv16i8Four,
5849 case Intrinsic::aarch64_sve_srshl_single_x2:
5851 Node->getValueType(0),
5852 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5853 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5854 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5856 case Intrinsic::aarch64_sve_srshl_single_x4:
5858 Node->getValueType(0),
5859 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5860 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5861 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5863 case Intrinsic::aarch64_sve_urshl_single_x2:
5865 Node->getValueType(0),
5866 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5867 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5868 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5870 case Intrinsic::aarch64_sve_urshl_single_x4:
5872 Node->getValueType(0),
5873 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5874 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5875 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5877 case Intrinsic::aarch64_sve_srshl_x2:
5879 Node->getValueType(0),
5880 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5881 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5882 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5884 case Intrinsic::aarch64_sve_srshl_x4:
5886 Node->getValueType(0),
5887 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5888 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5889 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5891 case Intrinsic::aarch64_sve_urshl_x2:
5893 Node->getValueType(0),
5894 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5895 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5896 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5898 case Intrinsic::aarch64_sve_urshl_x4:
5900 Node->getValueType(0),
5901 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5902 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5903 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5905 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5907 Node->getValueType(0),
5908 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5909 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5910 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5912 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5914 Node->getValueType(0),
5915 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5916 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5917 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5919 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5921 Node->getValueType(0),
5922 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5923 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5924 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5926 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5928 Node->getValueType(0),
5929 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5930 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5931 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5933 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5935 Node->getValueType(0),
5936 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5937 AArch64::FSCALE_2ZZ_D}))
5938 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5940 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5942 Node->getValueType(0),
5943 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5944 AArch64::FSCALE_4ZZ_D}))
5945 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5947 case Intrinsic::aarch64_sme_fp8_scale_x2:
5949 Node->getValueType(0),
5950 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5951 AArch64::FSCALE_2Z2Z_D}))
5952 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5954 case Intrinsic::aarch64_sme_fp8_scale_x4:
5956 Node->getValueType(0),
5957 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5958 AArch64::FSCALE_4Z4Z_D}))
5959 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5961 case Intrinsic::aarch64_sve_whilege_x2:
5963 Node->getValueType(0),
5964 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5965 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5966 SelectWhilePair(Node,
Op);
5968 case Intrinsic::aarch64_sve_whilegt_x2:
5970 Node->getValueType(0),
5971 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5972 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5973 SelectWhilePair(Node,
Op);
5975 case Intrinsic::aarch64_sve_whilehi_x2:
5977 Node->getValueType(0),
5978 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5979 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5980 SelectWhilePair(Node,
Op);
5982 case Intrinsic::aarch64_sve_whilehs_x2:
5984 Node->getValueType(0),
5985 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5986 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5987 SelectWhilePair(Node,
Op);
5989 case Intrinsic::aarch64_sve_whilele_x2:
5991 Node->getValueType(0),
5992 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5993 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5994 SelectWhilePair(Node,
Op);
5996 case Intrinsic::aarch64_sve_whilelo_x2:
5998 Node->getValueType(0),
5999 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6000 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6001 SelectWhilePair(Node,
Op);
6003 case Intrinsic::aarch64_sve_whilels_x2:
6005 Node->getValueType(0),
6006 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6007 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6008 SelectWhilePair(Node,
Op);
6010 case Intrinsic::aarch64_sve_whilelt_x2:
6012 Node->getValueType(0),
6013 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6014 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6015 SelectWhilePair(Node,
Op);
6017 case Intrinsic::aarch64_sve_smax_single_x2:
6019 Node->getValueType(0),
6020 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6021 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6022 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6024 case Intrinsic::aarch64_sve_umax_single_x2:
6026 Node->getValueType(0),
6027 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6028 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6029 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6031 case Intrinsic::aarch64_sve_fmax_single_x2:
6033 Node->getValueType(0),
6034 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6035 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6036 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6038 case Intrinsic::aarch64_sve_smax_single_x4:
6040 Node->getValueType(0),
6041 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6042 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6043 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6045 case Intrinsic::aarch64_sve_umax_single_x4:
6047 Node->getValueType(0),
6048 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6049 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6050 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6052 case Intrinsic::aarch64_sve_fmax_single_x4:
6054 Node->getValueType(0),
6055 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6056 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6057 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6059 case Intrinsic::aarch64_sve_smin_single_x2:
6061 Node->getValueType(0),
6062 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6063 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6064 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6066 case Intrinsic::aarch64_sve_umin_single_x2:
6068 Node->getValueType(0),
6069 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6070 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6071 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6073 case Intrinsic::aarch64_sve_fmin_single_x2:
6075 Node->getValueType(0),
6076 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6077 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6078 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6080 case Intrinsic::aarch64_sve_smin_single_x4:
6082 Node->getValueType(0),
6083 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6084 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6085 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6087 case Intrinsic::aarch64_sve_umin_single_x4:
6089 Node->getValueType(0),
6090 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6091 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6092 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6094 case Intrinsic::aarch64_sve_fmin_single_x4:
6096 Node->getValueType(0),
6097 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6098 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6099 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6101 case Intrinsic::aarch64_sve_smax_x2:
6103 Node->getValueType(0),
6104 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6105 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6106 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6108 case Intrinsic::aarch64_sve_umax_x2:
6110 Node->getValueType(0),
6111 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6112 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6113 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6115 case Intrinsic::aarch64_sve_fmax_x2:
6117 Node->getValueType(0),
6118 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6119 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6120 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6122 case Intrinsic::aarch64_sve_smax_x4:
6124 Node->getValueType(0),
6125 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6126 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6127 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6129 case Intrinsic::aarch64_sve_umax_x4:
6131 Node->getValueType(0),
6132 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6133 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6134 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6136 case Intrinsic::aarch64_sve_fmax_x4:
6138 Node->getValueType(0),
6139 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6140 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6141 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6143 case Intrinsic::aarch64_sme_famax_x2:
6145 Node->getValueType(0),
6146 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6147 AArch64::FAMAX_2Z2Z_D}))
6148 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6150 case Intrinsic::aarch64_sme_famax_x4:
6152 Node->getValueType(0),
6153 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6154 AArch64::FAMAX_4Z4Z_D}))
6155 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6157 case Intrinsic::aarch64_sme_famin_x2:
6159 Node->getValueType(0),
6160 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6161 AArch64::FAMIN_2Z2Z_D}))
6162 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6164 case Intrinsic::aarch64_sme_famin_x4:
6166 Node->getValueType(0),
6167 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6168 AArch64::FAMIN_4Z4Z_D}))
6169 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6171 case Intrinsic::aarch64_sve_smin_x2:
6173 Node->getValueType(0),
6174 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6175 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6176 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6178 case Intrinsic::aarch64_sve_umin_x2:
6180 Node->getValueType(0),
6181 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6182 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6183 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6185 case Intrinsic::aarch64_sve_fmin_x2:
6187 Node->getValueType(0),
6188 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6189 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6190 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6192 case Intrinsic::aarch64_sve_smin_x4:
6194 Node->getValueType(0),
6195 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6196 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6197 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6199 case Intrinsic::aarch64_sve_umin_x4:
6201 Node->getValueType(0),
6202 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6203 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6204 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6206 case Intrinsic::aarch64_sve_fmin_x4:
6208 Node->getValueType(0),
6209 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6210 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6211 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6213 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6215 Node->getValueType(0),
6216 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6217 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6218 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6220 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6222 Node->getValueType(0),
6223 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6224 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6225 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6227 case Intrinsic::aarch64_sve_fminnm_single_x2:
6229 Node->getValueType(0),
6230 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6231 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6232 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6234 case Intrinsic::aarch64_sve_fminnm_single_x4:
6236 Node->getValueType(0),
6237 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6238 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6239 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6241 case Intrinsic::aarch64_sve_fmaxnm_x2:
6243 Node->getValueType(0),
6244 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6245 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6246 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6248 case Intrinsic::aarch64_sve_fmaxnm_x4:
6250 Node->getValueType(0),
6251 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6252 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6253 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6255 case Intrinsic::aarch64_sve_fminnm_x2:
6257 Node->getValueType(0),
6258 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6259 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6260 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6262 case Intrinsic::aarch64_sve_fminnm_x4:
6264 Node->getValueType(0),
6265 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6266 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6267 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6269 case Intrinsic::aarch64_sve_fcvtzs_x2:
6270 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6272 case Intrinsic::aarch64_sve_scvtf_x2:
6273 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6275 case Intrinsic::aarch64_sve_fcvtzu_x2:
6276 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6278 case Intrinsic::aarch64_sve_ucvtf_x2:
6279 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6281 case Intrinsic::aarch64_sve_fcvtzs_x4:
6282 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6284 case Intrinsic::aarch64_sve_scvtf_x4:
6285 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6287 case Intrinsic::aarch64_sve_fcvtzu_x4:
6288 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6290 case Intrinsic::aarch64_sve_ucvtf_x4:
6291 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6293 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6294 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6296 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6297 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6299 case Intrinsic::aarch64_sve_sclamp_single_x2:
6301 Node->getValueType(0),
6302 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6303 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6304 SelectClamp(Node, 2,
Op);
6306 case Intrinsic::aarch64_sve_uclamp_single_x2:
6308 Node->getValueType(0),
6309 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6310 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6311 SelectClamp(Node, 2,
Op);
6313 case Intrinsic::aarch64_sve_fclamp_single_x2:
6315 Node->getValueType(0),
6316 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6317 AArch64::FCLAMP_VG2_2Z2Z_D}))
6318 SelectClamp(Node, 2,
Op);
6320 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6321 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6323 case Intrinsic::aarch64_sve_sclamp_single_x4:
6325 Node->getValueType(0),
6326 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6327 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6328 SelectClamp(Node, 4,
Op);
6330 case Intrinsic::aarch64_sve_uclamp_single_x4:
6332 Node->getValueType(0),
6333 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6334 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6335 SelectClamp(Node, 4,
Op);
6337 case Intrinsic::aarch64_sve_fclamp_single_x4:
6339 Node->getValueType(0),
6340 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6341 AArch64::FCLAMP_VG4_4Z4Z_D}))
6342 SelectClamp(Node, 4,
Op);
6344 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6345 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6347 case Intrinsic::aarch64_sve_add_single_x2:
6349 Node->getValueType(0),
6350 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6351 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6352 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6354 case Intrinsic::aarch64_sve_add_single_x4:
6356 Node->getValueType(0),
6357 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6358 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6359 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6361 case Intrinsic::aarch64_sve_zip_x2:
6363 Node->getValueType(0),
6364 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6365 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6366 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6368 case Intrinsic::aarch64_sve_zipq_x2:
6369 SelectUnaryMultiIntrinsic(Node, 2,
false,
6370 AArch64::ZIP_VG2_2ZZZ_Q);
6372 case Intrinsic::aarch64_sve_zip_x4:
6374 Node->getValueType(0),
6375 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6376 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6377 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6379 case Intrinsic::aarch64_sve_zipq_x4:
6380 SelectUnaryMultiIntrinsic(Node, 4,
true,
6381 AArch64::ZIP_VG4_4Z4Z_Q);
6383 case Intrinsic::aarch64_sve_uzp_x2:
6385 Node->getValueType(0),
6386 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6387 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6388 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6390 case Intrinsic::aarch64_sve_uzpq_x2:
6391 SelectUnaryMultiIntrinsic(Node, 2,
false,
6392 AArch64::UZP_VG2_2ZZZ_Q);
6394 case Intrinsic::aarch64_sve_uzp_x4:
6396 Node->getValueType(0),
6397 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6398 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6399 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6401 case Intrinsic::aarch64_sve_uzpq_x4:
6402 SelectUnaryMultiIntrinsic(Node, 4,
true,
6403 AArch64::UZP_VG4_4Z4Z_Q);
6405 case Intrinsic::aarch64_sve_sel_x2:
6407 Node->getValueType(0),
6408 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6409 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6410 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6412 case Intrinsic::aarch64_sve_sel_x4:
6414 Node->getValueType(0),
6415 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6416 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6417 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6419 case Intrinsic::aarch64_sve_frinta_x2:
6420 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6422 case Intrinsic::aarch64_sve_frinta_x4:
6423 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6425 case Intrinsic::aarch64_sve_frintm_x2:
6426 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6428 case Intrinsic::aarch64_sve_frintm_x4:
6429 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6431 case Intrinsic::aarch64_sve_frintn_x2:
6432 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6434 case Intrinsic::aarch64_sve_frintn_x4:
6435 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6437 case Intrinsic::aarch64_sve_frintp_x2:
6438 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6440 case Intrinsic::aarch64_sve_frintp_x4:
6441 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6443 case Intrinsic::aarch64_sve_sunpk_x2:
6445 Node->getValueType(0),
6446 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6447 AArch64::SUNPK_VG2_2ZZ_D}))
6448 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6450 case Intrinsic::aarch64_sve_uunpk_x2:
6452 Node->getValueType(0),
6453 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6454 AArch64::UUNPK_VG2_2ZZ_D}))
6455 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6457 case Intrinsic::aarch64_sve_sunpk_x4:
6459 Node->getValueType(0),
6460 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6461 AArch64::SUNPK_VG4_4Z2Z_D}))
6462 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6464 case Intrinsic::aarch64_sve_uunpk_x4:
6466 Node->getValueType(0),
6467 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6468 AArch64::UUNPK_VG4_4Z2Z_D}))
6469 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6471 case Intrinsic::aarch64_sve_pext_x2: {
6473 Node->getValueType(0),
6474 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6475 AArch64::PEXT_2PCI_D}))
6476 SelectPExtPair(Node,
Op);
6483 unsigned IntNo =
Node->getConstantOperandVal(1);
6484 if (
Node->getNumOperands() >= 3)
6485 VT =
Node->getOperand(2)->getValueType(0);
6489 case Intrinsic::aarch64_neon_st1x2: {
6490 if (VT == MVT::v8i8) {
6491 SelectStore(Node, 2, AArch64::ST1Twov8b);
6493 }
else if (VT == MVT::v16i8) {
6494 SelectStore(Node, 2, AArch64::ST1Twov16b);
6496 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6497 VT == MVT::v4bf16) {
6498 SelectStore(Node, 2, AArch64::ST1Twov4h);
6500 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6501 VT == MVT::v8bf16) {
6502 SelectStore(Node, 2, AArch64::ST1Twov8h);
6504 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6505 SelectStore(Node, 2, AArch64::ST1Twov2s);
6507 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6508 SelectStore(Node, 2, AArch64::ST1Twov4s);
6510 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6511 SelectStore(Node, 2, AArch64::ST1Twov2d);
6513 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6514 SelectStore(Node, 2, AArch64::ST1Twov1d);
6519 case Intrinsic::aarch64_neon_st1x3: {
6520 if (VT == MVT::v8i8) {
6521 SelectStore(Node, 3, AArch64::ST1Threev8b);
6523 }
else if (VT == MVT::v16i8) {
6524 SelectStore(Node, 3, AArch64::ST1Threev16b);
6526 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6527 VT == MVT::v4bf16) {
6528 SelectStore(Node, 3, AArch64::ST1Threev4h);
6530 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6531 VT == MVT::v8bf16) {
6532 SelectStore(Node, 3, AArch64::ST1Threev8h);
6534 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6535 SelectStore(Node, 3, AArch64::ST1Threev2s);
6537 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6538 SelectStore(Node, 3, AArch64::ST1Threev4s);
6540 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6541 SelectStore(Node, 3, AArch64::ST1Threev2d);
6543 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6544 SelectStore(Node, 3, AArch64::ST1Threev1d);
6549 case Intrinsic::aarch64_neon_st1x4: {
6550 if (VT == MVT::v8i8) {
6551 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6553 }
else if (VT == MVT::v16i8) {
6554 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6556 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6557 VT == MVT::v4bf16) {
6558 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6560 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6561 VT == MVT::v8bf16) {
6562 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6564 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6565 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6567 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6568 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6570 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6571 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6573 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6574 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6579 case Intrinsic::aarch64_neon_st2: {
6580 if (VT == MVT::v8i8) {
6581 SelectStore(Node, 2, AArch64::ST2Twov8b);
6583 }
else if (VT == MVT::v16i8) {
6584 SelectStore(Node, 2, AArch64::ST2Twov16b);
6586 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6587 VT == MVT::v4bf16) {
6588 SelectStore(Node, 2, AArch64::ST2Twov4h);
6590 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6591 VT == MVT::v8bf16) {
6592 SelectStore(Node, 2, AArch64::ST2Twov8h);
6594 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6595 SelectStore(Node, 2, AArch64::ST2Twov2s);
6597 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6598 SelectStore(Node, 2, AArch64::ST2Twov4s);
6600 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6601 SelectStore(Node, 2, AArch64::ST2Twov2d);
6603 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6604 SelectStore(Node, 2, AArch64::ST1Twov1d);
6609 case Intrinsic::aarch64_neon_st3: {
6610 if (VT == MVT::v8i8) {
6611 SelectStore(Node, 3, AArch64::ST3Threev8b);
6613 }
else if (VT == MVT::v16i8) {
6614 SelectStore(Node, 3, AArch64::ST3Threev16b);
6616 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6617 VT == MVT::v4bf16) {
6618 SelectStore(Node, 3, AArch64::ST3Threev4h);
6620 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6621 VT == MVT::v8bf16) {
6622 SelectStore(Node, 3, AArch64::ST3Threev8h);
6624 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6625 SelectStore(Node, 3, AArch64::ST3Threev2s);
6627 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6628 SelectStore(Node, 3, AArch64::ST3Threev4s);
6630 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6631 SelectStore(Node, 3, AArch64::ST3Threev2d);
6633 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6634 SelectStore(Node, 3, AArch64::ST1Threev1d);
6639 case Intrinsic::aarch64_neon_st4: {
6640 if (VT == MVT::v8i8) {
6641 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6643 }
else if (VT == MVT::v16i8) {
6644 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6646 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6647 VT == MVT::v4bf16) {
6648 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6650 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6651 VT == MVT::v8bf16) {
6652 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6654 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6655 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6657 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6658 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6660 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6661 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6663 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6664 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6669 case Intrinsic::aarch64_neon_st2lane: {
6670 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6671 SelectStoreLane(Node, 2, AArch64::ST2i8);
6673 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6674 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6675 SelectStoreLane(Node, 2, AArch64::ST2i16);
6677 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6679 SelectStoreLane(Node, 2, AArch64::ST2i32);
6681 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6683 SelectStoreLane(Node, 2, AArch64::ST2i64);
6688 case Intrinsic::aarch64_neon_st3lane: {
6689 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6690 SelectStoreLane(Node, 3, AArch64::ST3i8);
6692 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6693 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6694 SelectStoreLane(Node, 3, AArch64::ST3i16);
6696 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6698 SelectStoreLane(Node, 3, AArch64::ST3i32);
6700 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6702 SelectStoreLane(Node, 3, AArch64::ST3i64);
6707 case Intrinsic::aarch64_neon_st4lane: {
6708 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6709 SelectStoreLane(Node, 4, AArch64::ST4i8);
6711 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6712 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6713 SelectStoreLane(Node, 4, AArch64::ST4i16);
6715 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6717 SelectStoreLane(Node, 4, AArch64::ST4i32);
6719 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6721 SelectStoreLane(Node, 4, AArch64::ST4i64);
6726 case Intrinsic::aarch64_sve_st2q: {
6727 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6730 case Intrinsic::aarch64_sve_st3q: {
6731 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6734 case Intrinsic::aarch64_sve_st4q: {
6735 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6738 case Intrinsic::aarch64_sve_st2: {
6739 if (VT == MVT::nxv16i8) {
6740 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6742 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6743 VT == MVT::nxv8bf16) {
6744 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6746 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6747 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6749 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6750 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6755 case Intrinsic::aarch64_sve_st3: {
6756 if (VT == MVT::nxv16i8) {
6757 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6759 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6760 VT == MVT::nxv8bf16) {
6761 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6763 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6764 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6766 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6767 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6772 case Intrinsic::aarch64_sve_st4: {
6773 if (VT == MVT::nxv16i8) {
6774 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6776 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6777 VT == MVT::nxv8bf16) {
6778 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6780 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6781 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6783 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6784 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6792 case AArch64ISD::LD2post: {
6793 if (VT == MVT::v8i8) {
6794 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6796 }
else if (VT == MVT::v16i8) {
6797 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6799 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6800 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6802 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6803 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6805 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6806 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6808 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6809 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6811 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6812 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6814 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6815 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6820 case AArch64ISD::LD3post: {
6821 if (VT == MVT::v8i8) {
6822 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6824 }
else if (VT == MVT::v16i8) {
6825 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6827 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6828 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6830 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6831 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6833 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6834 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6836 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6837 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6839 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6840 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6842 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6843 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6848 case AArch64ISD::LD4post: {
6849 if (VT == MVT::v8i8) {
6850 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6852 }
else if (VT == MVT::v16i8) {
6853 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6855 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6856 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6858 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6859 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6861 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6862 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6864 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6865 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6867 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6868 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6870 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6871 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6876 case AArch64ISD::LD1x2post: {
6877 if (VT == MVT::v8i8) {
6878 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6880 }
else if (VT == MVT::v16i8) {
6881 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6883 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6884 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6886 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6887 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6889 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6890 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6892 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6893 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6895 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6896 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6898 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6899 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6904 case AArch64ISD::LD1x3post: {
6905 if (VT == MVT::v8i8) {
6906 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6908 }
else if (VT == MVT::v16i8) {
6909 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6911 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6912 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6914 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6915 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6917 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6918 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6920 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6921 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6923 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6924 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6926 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6927 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6932 case AArch64ISD::LD1x4post: {
6933 if (VT == MVT::v8i8) {
6934 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6936 }
else if (VT == MVT::v16i8) {
6937 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6939 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6940 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6942 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6943 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6945 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6946 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6948 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6949 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6951 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6952 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6954 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6955 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6960 case AArch64ISD::LD1DUPpost: {
6961 if (VT == MVT::v8i8) {
6962 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6964 }
else if (VT == MVT::v16i8) {
6965 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6967 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6968 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6970 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6971 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6973 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6974 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6976 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6977 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
6979 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6980 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
6982 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6983 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
6988 case AArch64ISD::LD2DUPpost: {
6989 if (VT == MVT::v8i8) {
6990 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
6992 }
else if (VT == MVT::v16i8) {
6993 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
6995 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6996 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
6998 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6999 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7001 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7002 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7004 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7005 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7007 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7008 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7010 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7011 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7016 case AArch64ISD::LD3DUPpost: {
7017 if (VT == MVT::v8i8) {
7018 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7020 }
else if (VT == MVT::v16i8) {
7021 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7023 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7024 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7026 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7027 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7029 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7030 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7032 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7033 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7035 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7036 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7038 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7039 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7044 case AArch64ISD::LD4DUPpost: {
7045 if (VT == MVT::v8i8) {
7046 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7048 }
else if (VT == MVT::v16i8) {
7049 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7051 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7052 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7054 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7055 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7057 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7058 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7060 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7061 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7063 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7064 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7066 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7067 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7072 case AArch64ISD::LD1LANEpost: {
7073 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7074 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7076 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7077 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7078 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7080 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7082 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7084 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7086 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7091 case AArch64ISD::LD2LANEpost: {
7092 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7093 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7095 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7096 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7097 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7099 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7101 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7103 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7105 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7110 case AArch64ISD::LD3LANEpost: {
7111 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7112 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7114 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7115 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7116 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7118 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7120 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7122 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7124 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7129 case AArch64ISD::LD4LANEpost: {
7130 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7131 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7133 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7134 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7135 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7137 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7139 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7141 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7143 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7148 case AArch64ISD::ST2post: {
7149 VT =
Node->getOperand(1).getValueType();
7150 if (VT == MVT::v8i8) {
7151 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7153 }
else if (VT == MVT::v16i8) {
7154 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7156 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7157 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7159 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7160 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7162 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7163 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7165 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7166 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7168 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7169 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7171 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7172 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7177 case AArch64ISD::ST3post: {
7178 VT =
Node->getOperand(1).getValueType();
7179 if (VT == MVT::v8i8) {
7180 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7182 }
else if (VT == MVT::v16i8) {
7183 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7185 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7186 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7188 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7189 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7191 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7192 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7194 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7195 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7197 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7198 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7200 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7201 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7206 case AArch64ISD::ST4post: {
7207 VT =
Node->getOperand(1).getValueType();
7208 if (VT == MVT::v8i8) {
7209 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7211 }
else if (VT == MVT::v16i8) {
7212 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7214 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7215 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7217 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7218 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7220 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7221 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7223 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7224 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7226 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7227 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7229 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7230 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7235 case AArch64ISD::ST1x2post: {
7236 VT =
Node->getOperand(1).getValueType();
7237 if (VT == MVT::v8i8) {
7238 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7240 }
else if (VT == MVT::v16i8) {
7241 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7243 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7244 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7246 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7247 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7249 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7250 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7252 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7253 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7255 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7256 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7258 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7259 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7264 case AArch64ISD::ST1x3post: {
7265 VT =
Node->getOperand(1).getValueType();
7266 if (VT == MVT::v8i8) {
7267 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7269 }
else if (VT == MVT::v16i8) {
7270 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7272 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7273 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7275 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7276 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7278 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7279 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7281 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7282 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7284 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7285 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7287 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7288 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7293 case AArch64ISD::ST1x4post: {
7294 VT =
Node->getOperand(1).getValueType();
7295 if (VT == MVT::v8i8) {
7296 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7298 }
else if (VT == MVT::v16i8) {
7299 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7301 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7302 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7304 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7305 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7307 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7308 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7310 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7311 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7313 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7314 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7316 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7317 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7322 case AArch64ISD::ST2LANEpost: {
7323 VT =
Node->getOperand(1).getValueType();
7324 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7325 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7327 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7328 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7329 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7331 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7333 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7335 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7337 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7342 case AArch64ISD::ST3LANEpost: {
7343 VT =
Node->getOperand(1).getValueType();
7344 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7345 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7347 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7348 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7349 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7351 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7353 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7355 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7357 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7362 case AArch64ISD::ST4LANEpost: {
7363 VT =
Node->getOperand(1).getValueType();
7364 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7365 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7367 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7368 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7369 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7371 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7373 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7375 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7377 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7392 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7404 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7408 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7409 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7424 return MemIntr->getMemoryVT();
7431 DataVT = Load->getValueType(0);
7433 DataVT = Load->getValueType(0);
7435 DataVT = Store->getValue().getValueType();
7437 DataVT = Store->getValue().getValueType();
7444 const unsigned Opcode = Root->
getOpcode();
7448 case AArch64ISD::LD1_MERGE_ZERO:
7449 case AArch64ISD::LD1S_MERGE_ZERO:
7450 case AArch64ISD::LDNF1_MERGE_ZERO:
7451 case AArch64ISD::LDNF1S_MERGE_ZERO:
7453 case AArch64ISD::ST1_PRED:
7465 case Intrinsic::aarch64_sme_ldr:
7466 case Intrinsic::aarch64_sme_str:
7467 return MVT::nxv16i8;
7468 case Intrinsic::aarch64_sve_prf:
7473 case Intrinsic::aarch64_sve_ld2_sret:
7474 case Intrinsic::aarch64_sve_ld2q_sret:
7477 case Intrinsic::aarch64_sve_st2q:
7480 case Intrinsic::aarch64_sve_ld3_sret:
7481 case Intrinsic::aarch64_sve_ld3q_sret:
7484 case Intrinsic::aarch64_sve_st3q:
7487 case Intrinsic::aarch64_sve_ld4_sret:
7488 case Intrinsic::aarch64_sve_ld4q_sret:
7491 case Intrinsic::aarch64_sve_st4q:
7494 case Intrinsic::aarch64_sve_ld1udq:
7495 case Intrinsic::aarch64_sve_st1dq:
7496 return EVT(MVT::nxv1i64);
7497 case Intrinsic::aarch64_sve_ld1uwq:
7498 case Intrinsic::aarch64_sve_st1wq:
7499 return EVT(MVT::nxv1i32);
7506template <
int64_t Min,
int64_t Max>
7507bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7511 const DataLayout &
DL = CurDAG->getDataLayout();
7512 const MachineFrameInfo &MFI = MF->getFrameInfo();
7520 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7534 int64_t MulImm = std::numeric_limits<int64_t>::max();
7535 if (VScale.
getOpcode() == ISD::VSCALE) {
7538 int64_t ByteOffset =
C->getSExtValue();
7539 const auto KnownVScale =
7542 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7545 MulImm = ByteOffset / KnownVScale;
7552 if ((MulImm % MemWidthBytes) != 0)
7555 int64_t
Offset = MulImm / MemWidthBytes;
7559 Base =
N.getOperand(0);
7568 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7574bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7593 int64_t ImmOff =
C->getSExtValue();
7594 unsigned Size = 1 << Scale;
7603 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7605 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7616 if (
C->getZExtValue() == Scale) {
7625bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7626 const AArch64TargetLowering *TLI =
7627 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7632bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7633 EVT VT =
N.getValueType();
7637bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7642 int64_t ImmOff =
C->getSExtValue();
7643 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7644 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7649 if (
SDValue C = MatchConstantOffset(
N)) {
7650 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7656 if (CurDAG->isBaseWithConstantOffset(
N)) {
7657 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7658 Base =
N.getOperand(0);
7666 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7670bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7690 uint64_t LowerBound = 0, UpperBound = 64;
7708 if (CN->getAPIntValue().uge(LowerBound) &&
7709 CN->getAPIntValue().ult(UpperBound)) {
7711 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const AArch64RegisterInfo * getRegisterInfo() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(SelectionDAG &DAG, SDValue N) const
bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static MVT getVectorVT(MVT VT, unsigned NumElements)
uint8_t getStackID(int ObjectIdx) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
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...
unsigned getID() const
Return the register class ID number.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t parseGenericRegister(StringRef Name)
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t &Encoding)
processLogicalImmediate - Determine if an immediate value can be encoded as the immediate operand of ...
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static constexpr unsigned SVEBitsPerBlock
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SIGN_EXTEND
Conversion operators.
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
@ Undef
Value of the register doesn't matter.
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
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...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmTowardZero
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
unsigned getBitWidth() const
Get the bit width of this value.