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,
4349 int32_t ImmVal, ShiftVal;
4354 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4355 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4359bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4361 int64_t ImmVal = CNode->getSExtValue();
4363 if (ImmVal >= -128 && ImmVal < 128) {
4364 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4371bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4373 uint64_t ImmVal = CNode->getZExtValue();
4383 ImmVal &= 0xFFFFFFFF;
4392 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4399bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4402 uint64_t ImmVal = CNode->getZExtValue();
4412 ImmVal |= ImmVal << 8;
4413 ImmVal |= ImmVal << 16;
4414 ImmVal |= ImmVal << 32;
4418 ImmVal |= ImmVal << 16;
4419 ImmVal |= ImmVal << 32;
4422 ImmVal &= 0xFFFFFFFF;
4423 ImmVal |= ImmVal << 32;
4433 Imm = CurDAG->getTargetConstant(encoding,
DL, MVT::i64);
4445bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4446 uint64_t
High,
bool AllowSaturation,
4449 uint64_t ImmVal = CN->getZExtValue();
4456 if (ImmVal >
High) {
4457 if (!AllowSaturation)
4462 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4469bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4483 const TargetLowering *TLI = getTargetLowering();
4486 SDValue FiOp = CurDAG->getTargetFrameIndex(
4488 int TagOffset =
N->getConstantOperandVal(3);
4490 SDNode *Out = CurDAG->getMachineNode(
4491 AArch64::TAGPstack,
DL, MVT::i64,
4492 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4493 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4494 ReplaceNode(
N, Out);
4498void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4500 "llvm.aarch64.tagp third argument must be an immediate");
4501 if (trySelectStackSlotTagP(
N))
4508 int TagOffset =
N->getConstantOperandVal(3);
4509 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4510 {
N->getOperand(1),
N->getOperand(2)});
4511 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4512 {
SDValue(N1, 0),
N->getOperand(2)});
4513 SDNode *N3 = CurDAG->getMachineNode(
4514 AArch64::ADDG,
DL, MVT::i64,
4515 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4516 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4520bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4524 if (
N->getConstantOperandVal(2) != 0)
4526 if (!
N->getOperand(0).isUndef())
4530 EVT VT =
N->getValueType(0);
4531 EVT InVT =
N->getOperand(1).getValueType();
4542 "Expected to insert into a packed scalable vector!");
4545 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4546 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4547 N->getOperand(1), RC));
4551bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4555 if (
N->getConstantOperandVal(1) != 0)
4559 EVT VT =
N->getValueType(0);
4560 EVT InVT =
N->getOperand(0).getValueType();
4571 "Expected to extract from a packed scalable vector!");
4574 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4575 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4576 N->getOperand(0), RC));
4580bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4586 EVT VT =
N->getValueType(0);
4599 (Subtarget->hasSVE2() ||
4600 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4601 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4604 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4608 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4609 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4610 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4617 bool IsXOROperand =
true;
4619 IsXOROperand =
false;
4625 APInt ShlAmt, ShrAmt;
4633 if (!IsXOROperand) {
4635 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4638 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4639 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4640 VT, Zero, MOVIV, ZSub);
4651 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4652 AArch64::XAR_ZZZI_D})) {
4653 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4678 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4688 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4696 bool IsXOROperand =
true;
4698 IsXOROperand =
false;
4701 R1 =
XOR.getOperand(0);
4702 R2 =
XOR.getOperand(1);
4712 if (ShAmt + HsAmt != VTSizeInBits)
4715 if (!IsXOROperand) {
4718 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4727 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4733 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4734 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4736 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4739 if (
R2.getValueType() == VT)
4740 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4748 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4753 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4759 SDNode *XAR =
nullptr;
4763 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4764 AArch64::XAR_ZZZI_D}))
4765 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4767 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4770 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4776 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4777 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4780 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4781 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4787 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4791 ReplaceNode(
N, XAR);
4795void AArch64DAGToDAGISel::Select(SDNode *Node) {
4797 if (
Node->isMachineOpcode()) {
4799 Node->setNodeId(-1);
4804 EVT VT =
Node->getValueType(0);
4806 switch (
Node->getOpcode()) {
4810 case ISD::ATOMIC_CMP_SWAP:
4811 if (SelectCMP_SWAP(Node))
4816 case AArch64ISD::MRRS:
4817 if (tryReadRegister(Node))
4822 case AArch64ISD::MSRR:
4823 if (tryWriteRegister(Node))
4830 if (tryIndexedLoad(Node))
4839 if (tryBitfieldExtractOp(Node))
4841 if (tryBitfieldInsertInZeroOp(Node))
4846 if (tryShiftAmountMod(Node))
4851 if (tryBitfieldExtractOpFromSExt(Node))
4856 if (tryBitfieldInsertOp(Node))
4858 if (trySelectXAR(Node))
4863 if (trySelectCastScalableToFixedLengthVector(Node))
4869 if (trySelectCastFixedLengthToScalableVector(Node))
4878 if (ConstNode->
isZero()) {
4879 if (VT == MVT::i32) {
4881 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4882 ReplaceNode(Node,
New.getNode());
4884 }
else if (VT == MVT::i64) {
4886 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4887 ReplaceNode(Node,
New.getNode());
4898 const TargetLowering *TLI = getTargetLowering();
4899 SDValue TFI = CurDAG->getTargetFrameIndex(
4902 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4903 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4904 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4908 unsigned IntNo =
Node->getConstantOperandVal(1);
4912 case Intrinsic::aarch64_gcsss: {
4916 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4918 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4919 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4920 MVT::Other, Zero,
SDValue(SS1, 0));
4921 ReplaceNode(Node, SS2);
4924 case Intrinsic::aarch64_ldaxp:
4925 case Intrinsic::aarch64_ldxp: {
4927 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4932 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4933 MVT::Other, MemAddr, Chain);
4936 MachineMemOperand *MemOp =
4939 ReplaceNode(Node, Ld);
4942 case Intrinsic::aarch64_stlxp:
4943 case Intrinsic::aarch64_stxp: {
4945 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4953 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4955 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4957 MachineMemOperand *MemOp =
4961 ReplaceNode(Node, St);
4964 case Intrinsic::aarch64_neon_ld1x2:
4965 if (VT == MVT::v8i8) {
4966 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4968 }
else if (VT == MVT::v16i8) {
4969 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4971 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4972 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4974 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4975 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4977 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4978 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4980 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4981 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4983 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4984 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4986 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4987 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
4991 case Intrinsic::aarch64_neon_ld1x3:
4992 if (VT == MVT::v8i8) {
4993 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
4995 }
else if (VT == MVT::v16i8) {
4996 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
4998 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4999 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5001 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5002 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5004 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5005 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5007 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5008 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5010 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5011 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5013 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5014 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5018 case Intrinsic::aarch64_neon_ld1x4:
5019 if (VT == MVT::v8i8) {
5020 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5022 }
else if (VT == MVT::v16i8) {
5023 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5025 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5026 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5028 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5029 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5031 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5032 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5034 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5035 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5037 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5038 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5040 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5041 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5045 case Intrinsic::aarch64_neon_ld2:
5046 if (VT == MVT::v8i8) {
5047 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5049 }
else if (VT == MVT::v16i8) {
5050 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5052 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5053 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5055 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5056 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5058 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5059 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5061 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5062 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5064 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5065 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5067 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5068 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5072 case Intrinsic::aarch64_neon_ld3:
5073 if (VT == MVT::v8i8) {
5074 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5076 }
else if (VT == MVT::v16i8) {
5077 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5079 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5080 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5082 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5083 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5085 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5086 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5088 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5089 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5091 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5092 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5094 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5095 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5099 case Intrinsic::aarch64_neon_ld4:
5100 if (VT == MVT::v8i8) {
5101 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5103 }
else if (VT == MVT::v16i8) {
5104 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5106 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5107 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5109 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5110 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5112 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5113 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5115 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5116 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5118 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5119 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5121 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5122 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5126 case Intrinsic::aarch64_neon_ld2r:
5127 if (VT == MVT::v8i8) {
5128 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5130 }
else if (VT == MVT::v16i8) {
5131 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5133 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5134 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5136 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5137 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5139 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5140 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5142 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5143 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5145 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5146 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5148 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5149 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5153 case Intrinsic::aarch64_neon_ld3r:
5154 if (VT == MVT::v8i8) {
5155 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5157 }
else if (VT == MVT::v16i8) {
5158 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5160 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5161 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5163 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5164 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5166 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5167 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5169 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5170 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5172 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5173 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5175 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5176 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5180 case Intrinsic::aarch64_neon_ld4r:
5181 if (VT == MVT::v8i8) {
5182 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5184 }
else if (VT == MVT::v16i8) {
5185 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5187 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5188 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5190 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5191 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5193 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5194 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5196 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5197 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5199 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5200 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5202 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5203 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5207 case Intrinsic::aarch64_neon_ld2lane:
5208 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5209 SelectLoadLane(Node, 2, AArch64::LD2i8);
5211 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5212 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5213 SelectLoadLane(Node, 2, AArch64::LD2i16);
5215 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5217 SelectLoadLane(Node, 2, AArch64::LD2i32);
5219 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5221 SelectLoadLane(Node, 2, AArch64::LD2i64);
5225 case Intrinsic::aarch64_neon_ld3lane:
5226 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5227 SelectLoadLane(Node, 3, AArch64::LD3i8);
5229 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5230 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5231 SelectLoadLane(Node, 3, AArch64::LD3i16);
5233 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5235 SelectLoadLane(Node, 3, AArch64::LD3i32);
5237 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5239 SelectLoadLane(Node, 3, AArch64::LD3i64);
5243 case Intrinsic::aarch64_neon_ld4lane:
5244 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5245 SelectLoadLane(Node, 4, AArch64::LD4i8);
5247 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5248 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5249 SelectLoadLane(Node, 4, AArch64::LD4i16);
5251 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5253 SelectLoadLane(Node, 4, AArch64::LD4i32);
5255 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5257 SelectLoadLane(Node, 4, AArch64::LD4i64);
5261 case Intrinsic::aarch64_ld64b:
5262 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5264 case Intrinsic::aarch64_sve_ld2q_sret: {
5265 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5268 case Intrinsic::aarch64_sve_ld3q_sret: {
5269 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5272 case Intrinsic::aarch64_sve_ld4q_sret: {
5273 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5276 case Intrinsic::aarch64_sve_ld2_sret: {
5277 if (VT == MVT::nxv16i8) {
5278 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5281 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5282 VT == MVT::nxv8bf16) {
5283 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5286 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5287 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5290 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5291 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5297 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5298 if (VT == MVT::nxv16i8) {
5299 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5300 SelectContiguousMultiVectorLoad(
5301 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5302 else if (Subtarget->hasSVE2p1())
5303 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5308 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5309 VT == MVT::nxv8bf16) {
5310 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5311 SelectContiguousMultiVectorLoad(
5312 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5313 else if (Subtarget->hasSVE2p1())
5314 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5319 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5320 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5321 SelectContiguousMultiVectorLoad(
5322 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5323 else if (Subtarget->hasSVE2p1())
5324 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5329 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5330 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5331 SelectContiguousMultiVectorLoad(
5332 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5333 else if (Subtarget->hasSVE2p1())
5334 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5342 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5343 if (VT == MVT::nxv16i8) {
5344 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5345 SelectContiguousMultiVectorLoad(
5346 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5347 else if (Subtarget->hasSVE2p1())
5348 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5353 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5354 VT == MVT::nxv8bf16) {
5355 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5356 SelectContiguousMultiVectorLoad(
5357 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5358 else if (Subtarget->hasSVE2p1())
5359 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5364 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5365 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5366 SelectContiguousMultiVectorLoad(
5367 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5368 else if (Subtarget->hasSVE2p1())
5369 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5374 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5375 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5376 SelectContiguousMultiVectorLoad(
5377 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5378 else if (Subtarget->hasSVE2p1())
5379 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5387 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5388 if (VT == MVT::nxv16i8) {
5389 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5390 SelectContiguousMultiVectorLoad(Node, 2, 0,
5391 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5392 AArch64::LDNT1B_2Z_PSEUDO);
5393 else if (Subtarget->hasSVE2p1())
5394 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5395 AArch64::LDNT1B_2Z);
5399 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5400 VT == MVT::nxv8bf16) {
5401 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5402 SelectContiguousMultiVectorLoad(Node, 2, 1,
5403 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5404 AArch64::LDNT1H_2Z_PSEUDO);
5405 else if (Subtarget->hasSVE2p1())
5406 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5407 AArch64::LDNT1H_2Z);
5411 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5412 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5413 SelectContiguousMultiVectorLoad(Node, 2, 2,
5414 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5415 AArch64::LDNT1W_2Z_PSEUDO);
5416 else if (Subtarget->hasSVE2p1())
5417 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5418 AArch64::LDNT1W_2Z);
5422 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5423 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5424 SelectContiguousMultiVectorLoad(Node, 2, 3,
5425 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5426 AArch64::LDNT1D_2Z_PSEUDO);
5427 else if (Subtarget->hasSVE2p1())
5428 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5429 AArch64::LDNT1D_2Z);
5436 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5437 if (VT == MVT::nxv16i8) {
5438 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5439 SelectContiguousMultiVectorLoad(Node, 4, 0,
5440 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5441 AArch64::LDNT1B_4Z_PSEUDO);
5442 else if (Subtarget->hasSVE2p1())
5443 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5444 AArch64::LDNT1B_4Z);
5448 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5449 VT == MVT::nxv8bf16) {
5450 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5451 SelectContiguousMultiVectorLoad(Node, 4, 1,
5452 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5453 AArch64::LDNT1H_4Z_PSEUDO);
5454 else if (Subtarget->hasSVE2p1())
5455 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5456 AArch64::LDNT1H_4Z);
5460 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5461 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5462 SelectContiguousMultiVectorLoad(Node, 4, 2,
5463 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5464 AArch64::LDNT1W_4Z_PSEUDO);
5465 else if (Subtarget->hasSVE2p1())
5466 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5467 AArch64::LDNT1W_4Z);
5471 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5472 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5473 SelectContiguousMultiVectorLoad(Node, 4, 3,
5474 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5475 AArch64::LDNT1D_4Z_PSEUDO);
5476 else if (Subtarget->hasSVE2p1())
5477 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5478 AArch64::LDNT1D_4Z);
5485 case Intrinsic::aarch64_sve_ld3_sret: {
5486 if (VT == MVT::nxv16i8) {
5487 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5490 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5491 VT == MVT::nxv8bf16) {
5492 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5495 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5496 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5499 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5500 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5506 case Intrinsic::aarch64_sve_ld4_sret: {
5507 if (VT == MVT::nxv16i8) {
5508 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5511 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5512 VT == MVT::nxv8bf16) {
5513 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5516 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5517 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5520 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5521 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5527 case Intrinsic::aarch64_sme_read_hor_vg2: {
5528 if (VT == MVT::nxv16i8) {
5529 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5530 AArch64::MOVA_2ZMXI_H_B);
5532 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5533 VT == MVT::nxv8bf16) {
5534 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5535 AArch64::MOVA_2ZMXI_H_H);
5537 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5538 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5539 AArch64::MOVA_2ZMXI_H_S);
5541 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5542 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5543 AArch64::MOVA_2ZMXI_H_D);
5548 case Intrinsic::aarch64_sme_read_ver_vg2: {
5549 if (VT == MVT::nxv16i8) {
5550 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5551 AArch64::MOVA_2ZMXI_V_B);
5553 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5554 VT == MVT::nxv8bf16) {
5555 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5556 AArch64::MOVA_2ZMXI_V_H);
5558 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5559 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5560 AArch64::MOVA_2ZMXI_V_S);
5562 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5563 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5564 AArch64::MOVA_2ZMXI_V_D);
5569 case Intrinsic::aarch64_sme_read_hor_vg4: {
5570 if (VT == MVT::nxv16i8) {
5571 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5572 AArch64::MOVA_4ZMXI_H_B);
5574 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5575 VT == MVT::nxv8bf16) {
5576 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5577 AArch64::MOVA_4ZMXI_H_H);
5579 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5580 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5581 AArch64::MOVA_4ZMXI_H_S);
5583 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5584 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5585 AArch64::MOVA_4ZMXI_H_D);
5590 case Intrinsic::aarch64_sme_read_ver_vg4: {
5591 if (VT == MVT::nxv16i8) {
5592 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5593 AArch64::MOVA_4ZMXI_V_B);
5595 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5596 VT == MVT::nxv8bf16) {
5597 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5598 AArch64::MOVA_4ZMXI_V_H);
5600 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5601 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5602 AArch64::MOVA_4ZMXI_V_S);
5604 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5605 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5606 AArch64::MOVA_4ZMXI_V_D);
5611 case Intrinsic::aarch64_sme_read_vg1x2: {
5612 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5613 AArch64::MOVA_VG2_2ZMXI);
5616 case Intrinsic::aarch64_sme_read_vg1x4: {
5617 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5618 AArch64::MOVA_VG4_4ZMXI);
5621 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5622 if (VT == MVT::nxv16i8) {
5623 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5625 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5626 VT == MVT::nxv8bf16) {
5627 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5629 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5630 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5632 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5633 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5638 case Intrinsic::aarch64_sme_readz_vert_x2: {
5639 if (VT == MVT::nxv16i8) {
5640 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5642 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5643 VT == MVT::nxv8bf16) {
5644 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5646 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5647 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5649 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5650 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5655 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5656 if (VT == MVT::nxv16i8) {
5657 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5659 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5660 VT == MVT::nxv8bf16) {
5661 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5663 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5664 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5666 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5667 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5672 case Intrinsic::aarch64_sme_readz_vert_x4: {
5673 if (VT == MVT::nxv16i8) {
5674 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5676 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5677 VT == MVT::nxv8bf16) {
5678 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5680 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5681 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5683 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5684 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5689 case Intrinsic::aarch64_sme_readz_x2: {
5690 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5694 case Intrinsic::aarch64_sme_readz_x4: {
5695 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5699 case Intrinsic::swift_async_context_addr: {
5702 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5704 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5705 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5706 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5708 ReplaceUses(
SDValue(Node, 0), Res);
5710 CurDAG->RemoveDeadNode(Node);
5712 auto &MF = CurDAG->getMachineFunction();
5713 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5714 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5717 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5719 Node->getValueType(0),
5720 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5721 AArch64::LUTI2_4ZTZI_S}))
5723 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5726 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5728 Node->getValueType(0),
5729 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5731 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5734 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5736 Node->getValueType(0),
5737 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5738 AArch64::LUTI2_2ZTZI_S}))
5740 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5743 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5745 Node->getValueType(0),
5746 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5747 AArch64::LUTI4_2ZTZI_S}))
5749 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5752 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5753 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5756 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5758 Node->getValueType(0),
5759 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5760 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5762 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5764 Node->getValueType(0),
5765 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5766 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5768 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5770 Node->getValueType(0),
5771 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5772 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5774 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5776 Node->getValueType(0),
5777 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5778 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5783 unsigned IntNo =
Node->getConstantOperandVal(0);
5787 case Intrinsic::aarch64_tagp:
5791 case Intrinsic::ptrauth_auth:
5792 SelectPtrauthAuth(Node);
5795 case Intrinsic::ptrauth_resign:
5796 SelectPtrauthResign(Node);
5799 case Intrinsic::aarch64_neon_tbl2:
5800 SelectTable(Node, 2,
5801 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5804 case Intrinsic::aarch64_neon_tbl3:
5805 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5806 : AArch64::TBLv16i8Three,
5809 case Intrinsic::aarch64_neon_tbl4:
5810 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5811 : AArch64::TBLv16i8Four,
5814 case Intrinsic::aarch64_neon_tbx2:
5815 SelectTable(Node, 2,
5816 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5819 case Intrinsic::aarch64_neon_tbx3:
5820 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5821 : AArch64::TBXv16i8Three,
5824 case Intrinsic::aarch64_neon_tbx4:
5825 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5826 : AArch64::TBXv16i8Four,
5829 case Intrinsic::aarch64_sve_srshl_single_x2:
5831 Node->getValueType(0),
5832 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5833 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5834 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5836 case Intrinsic::aarch64_sve_srshl_single_x4:
5838 Node->getValueType(0),
5839 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5840 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5841 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5843 case Intrinsic::aarch64_sve_urshl_single_x2:
5845 Node->getValueType(0),
5846 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5847 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5848 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5850 case Intrinsic::aarch64_sve_urshl_single_x4:
5852 Node->getValueType(0),
5853 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5854 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5855 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5857 case Intrinsic::aarch64_sve_srshl_x2:
5859 Node->getValueType(0),
5860 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5861 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5862 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5864 case Intrinsic::aarch64_sve_srshl_x4:
5866 Node->getValueType(0),
5867 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5868 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5869 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5871 case Intrinsic::aarch64_sve_urshl_x2:
5873 Node->getValueType(0),
5874 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5875 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5876 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5878 case Intrinsic::aarch64_sve_urshl_x4:
5880 Node->getValueType(0),
5881 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5882 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5883 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5885 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5887 Node->getValueType(0),
5888 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5889 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5890 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5892 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5894 Node->getValueType(0),
5895 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5896 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5897 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5899 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5901 Node->getValueType(0),
5902 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5903 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5904 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5906 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5908 Node->getValueType(0),
5909 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5910 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5911 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5913 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5915 Node->getValueType(0),
5916 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5917 AArch64::FSCALE_2ZZ_D}))
5918 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5920 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5922 Node->getValueType(0),
5923 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5924 AArch64::FSCALE_4ZZ_D}))
5925 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5927 case Intrinsic::aarch64_sme_fp8_scale_x2:
5929 Node->getValueType(0),
5930 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5931 AArch64::FSCALE_2Z2Z_D}))
5932 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5934 case Intrinsic::aarch64_sme_fp8_scale_x4:
5936 Node->getValueType(0),
5937 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5938 AArch64::FSCALE_4Z4Z_D}))
5939 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5941 case Intrinsic::aarch64_sve_whilege_x2:
5943 Node->getValueType(0),
5944 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5945 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5946 SelectWhilePair(Node,
Op);
5948 case Intrinsic::aarch64_sve_whilegt_x2:
5950 Node->getValueType(0),
5951 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5952 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5953 SelectWhilePair(Node,
Op);
5955 case Intrinsic::aarch64_sve_whilehi_x2:
5957 Node->getValueType(0),
5958 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5959 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5960 SelectWhilePair(Node,
Op);
5962 case Intrinsic::aarch64_sve_whilehs_x2:
5964 Node->getValueType(0),
5965 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5966 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5967 SelectWhilePair(Node,
Op);
5969 case Intrinsic::aarch64_sve_whilele_x2:
5971 Node->getValueType(0),
5972 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5973 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5974 SelectWhilePair(Node,
Op);
5976 case Intrinsic::aarch64_sve_whilelo_x2:
5978 Node->getValueType(0),
5979 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5980 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5981 SelectWhilePair(Node,
Op);
5983 case Intrinsic::aarch64_sve_whilels_x2:
5985 Node->getValueType(0),
5986 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5987 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5988 SelectWhilePair(Node,
Op);
5990 case Intrinsic::aarch64_sve_whilelt_x2:
5992 Node->getValueType(0),
5993 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
5994 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
5995 SelectWhilePair(Node,
Op);
5997 case Intrinsic::aarch64_sve_smax_single_x2:
5999 Node->getValueType(0),
6000 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6001 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6002 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6004 case Intrinsic::aarch64_sve_umax_single_x2:
6006 Node->getValueType(0),
6007 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6008 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6009 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6011 case Intrinsic::aarch64_sve_fmax_single_x2:
6013 Node->getValueType(0),
6014 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6015 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6016 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6018 case Intrinsic::aarch64_sve_smax_single_x4:
6020 Node->getValueType(0),
6021 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6022 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6023 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6025 case Intrinsic::aarch64_sve_umax_single_x4:
6027 Node->getValueType(0),
6028 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6029 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6030 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6032 case Intrinsic::aarch64_sve_fmax_single_x4:
6034 Node->getValueType(0),
6035 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6036 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6037 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6039 case Intrinsic::aarch64_sve_smin_single_x2:
6041 Node->getValueType(0),
6042 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6043 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6044 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6046 case Intrinsic::aarch64_sve_umin_single_x2:
6048 Node->getValueType(0),
6049 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6050 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6051 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6053 case Intrinsic::aarch64_sve_fmin_single_x2:
6055 Node->getValueType(0),
6056 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6057 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6058 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6060 case Intrinsic::aarch64_sve_smin_single_x4:
6062 Node->getValueType(0),
6063 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6064 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6065 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6067 case Intrinsic::aarch64_sve_umin_single_x4:
6069 Node->getValueType(0),
6070 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6071 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6072 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6074 case Intrinsic::aarch64_sve_fmin_single_x4:
6076 Node->getValueType(0),
6077 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6078 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6079 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6081 case Intrinsic::aarch64_sve_smax_x2:
6083 Node->getValueType(0),
6084 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6085 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6086 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6088 case Intrinsic::aarch64_sve_umax_x2:
6090 Node->getValueType(0),
6091 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6092 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6093 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6095 case Intrinsic::aarch64_sve_fmax_x2:
6097 Node->getValueType(0),
6098 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6099 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6100 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6102 case Intrinsic::aarch64_sve_smax_x4:
6104 Node->getValueType(0),
6105 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6106 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6107 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6109 case Intrinsic::aarch64_sve_umax_x4:
6111 Node->getValueType(0),
6112 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6113 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6114 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6116 case Intrinsic::aarch64_sve_fmax_x4:
6118 Node->getValueType(0),
6119 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6120 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6121 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6123 case Intrinsic::aarch64_sme_famax_x2:
6125 Node->getValueType(0),
6126 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6127 AArch64::FAMAX_2Z2Z_D}))
6128 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6130 case Intrinsic::aarch64_sme_famax_x4:
6132 Node->getValueType(0),
6133 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6134 AArch64::FAMAX_4Z4Z_D}))
6135 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6137 case Intrinsic::aarch64_sme_famin_x2:
6139 Node->getValueType(0),
6140 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6141 AArch64::FAMIN_2Z2Z_D}))
6142 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6144 case Intrinsic::aarch64_sme_famin_x4:
6146 Node->getValueType(0),
6147 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6148 AArch64::FAMIN_4Z4Z_D}))
6149 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6151 case Intrinsic::aarch64_sve_smin_x2:
6153 Node->getValueType(0),
6154 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6155 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6156 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6158 case Intrinsic::aarch64_sve_umin_x2:
6160 Node->getValueType(0),
6161 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6162 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6163 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6165 case Intrinsic::aarch64_sve_fmin_x2:
6167 Node->getValueType(0),
6168 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6169 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6170 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6172 case Intrinsic::aarch64_sve_smin_x4:
6174 Node->getValueType(0),
6175 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6176 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6177 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6179 case Intrinsic::aarch64_sve_umin_x4:
6181 Node->getValueType(0),
6182 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6183 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6184 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6186 case Intrinsic::aarch64_sve_fmin_x4:
6188 Node->getValueType(0),
6189 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6190 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6191 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6193 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6195 Node->getValueType(0),
6196 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6197 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6198 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6200 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6202 Node->getValueType(0),
6203 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6204 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6205 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6207 case Intrinsic::aarch64_sve_fminnm_single_x2:
6209 Node->getValueType(0),
6210 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6211 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6212 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6214 case Intrinsic::aarch64_sve_fminnm_single_x4:
6216 Node->getValueType(0),
6217 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6218 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6219 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6221 case Intrinsic::aarch64_sve_fmaxnm_x2:
6223 Node->getValueType(0),
6224 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6225 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6226 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6228 case Intrinsic::aarch64_sve_fmaxnm_x4:
6230 Node->getValueType(0),
6231 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6232 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6233 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6235 case Intrinsic::aarch64_sve_fminnm_x2:
6237 Node->getValueType(0),
6238 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6239 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6240 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6242 case Intrinsic::aarch64_sve_fminnm_x4:
6244 Node->getValueType(0),
6245 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6246 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6247 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6249 case Intrinsic::aarch64_sve_fcvtzs_x2:
6250 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6252 case Intrinsic::aarch64_sve_scvtf_x2:
6253 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6255 case Intrinsic::aarch64_sve_fcvtzu_x2:
6256 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6258 case Intrinsic::aarch64_sve_ucvtf_x2:
6259 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6261 case Intrinsic::aarch64_sve_fcvtzs_x4:
6262 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6264 case Intrinsic::aarch64_sve_scvtf_x4:
6265 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6267 case Intrinsic::aarch64_sve_fcvtzu_x4:
6268 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6270 case Intrinsic::aarch64_sve_ucvtf_x4:
6271 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6273 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6274 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6276 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6277 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6279 case Intrinsic::aarch64_sve_sclamp_single_x2:
6281 Node->getValueType(0),
6282 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6283 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6284 SelectClamp(Node, 2,
Op);
6286 case Intrinsic::aarch64_sve_uclamp_single_x2:
6288 Node->getValueType(0),
6289 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6290 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6291 SelectClamp(Node, 2,
Op);
6293 case Intrinsic::aarch64_sve_fclamp_single_x2:
6295 Node->getValueType(0),
6296 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6297 AArch64::FCLAMP_VG2_2Z2Z_D}))
6298 SelectClamp(Node, 2,
Op);
6300 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6301 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6303 case Intrinsic::aarch64_sve_sclamp_single_x4:
6305 Node->getValueType(0),
6306 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6307 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6308 SelectClamp(Node, 4,
Op);
6310 case Intrinsic::aarch64_sve_uclamp_single_x4:
6312 Node->getValueType(0),
6313 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6314 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6315 SelectClamp(Node, 4,
Op);
6317 case Intrinsic::aarch64_sve_fclamp_single_x4:
6319 Node->getValueType(0),
6320 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6321 AArch64::FCLAMP_VG4_4Z4Z_D}))
6322 SelectClamp(Node, 4,
Op);
6324 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6325 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6327 case Intrinsic::aarch64_sve_add_single_x2:
6329 Node->getValueType(0),
6330 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6331 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6332 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6334 case Intrinsic::aarch64_sve_add_single_x4:
6336 Node->getValueType(0),
6337 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6338 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6339 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6341 case Intrinsic::aarch64_sve_zip_x2:
6343 Node->getValueType(0),
6344 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6345 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6346 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6348 case Intrinsic::aarch64_sve_zipq_x2:
6349 SelectUnaryMultiIntrinsic(Node, 2,
false,
6350 AArch64::ZIP_VG2_2ZZZ_Q);
6352 case Intrinsic::aarch64_sve_zip_x4:
6354 Node->getValueType(0),
6355 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6356 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6357 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6359 case Intrinsic::aarch64_sve_zipq_x4:
6360 SelectUnaryMultiIntrinsic(Node, 4,
true,
6361 AArch64::ZIP_VG4_4Z4Z_Q);
6363 case Intrinsic::aarch64_sve_uzp_x2:
6365 Node->getValueType(0),
6366 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6367 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6368 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6370 case Intrinsic::aarch64_sve_uzpq_x2:
6371 SelectUnaryMultiIntrinsic(Node, 2,
false,
6372 AArch64::UZP_VG2_2ZZZ_Q);
6374 case Intrinsic::aarch64_sve_uzp_x4:
6376 Node->getValueType(0),
6377 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6378 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6379 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6381 case Intrinsic::aarch64_sve_uzpq_x4:
6382 SelectUnaryMultiIntrinsic(Node, 4,
true,
6383 AArch64::UZP_VG4_4Z4Z_Q);
6385 case Intrinsic::aarch64_sve_sel_x2:
6387 Node->getValueType(0),
6388 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6389 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6390 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6392 case Intrinsic::aarch64_sve_sel_x4:
6394 Node->getValueType(0),
6395 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6396 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6397 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6399 case Intrinsic::aarch64_sve_frinta_x2:
6400 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6402 case Intrinsic::aarch64_sve_frinta_x4:
6403 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6405 case Intrinsic::aarch64_sve_frintm_x2:
6406 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6408 case Intrinsic::aarch64_sve_frintm_x4:
6409 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6411 case Intrinsic::aarch64_sve_frintn_x2:
6412 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6414 case Intrinsic::aarch64_sve_frintn_x4:
6415 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6417 case Intrinsic::aarch64_sve_frintp_x2:
6418 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6420 case Intrinsic::aarch64_sve_frintp_x4:
6421 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6423 case Intrinsic::aarch64_sve_sunpk_x2:
6425 Node->getValueType(0),
6426 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6427 AArch64::SUNPK_VG2_2ZZ_D}))
6428 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6430 case Intrinsic::aarch64_sve_uunpk_x2:
6432 Node->getValueType(0),
6433 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6434 AArch64::UUNPK_VG2_2ZZ_D}))
6435 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6437 case Intrinsic::aarch64_sve_sunpk_x4:
6439 Node->getValueType(0),
6440 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6441 AArch64::SUNPK_VG4_4Z2Z_D}))
6442 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6444 case Intrinsic::aarch64_sve_uunpk_x4:
6446 Node->getValueType(0),
6447 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6448 AArch64::UUNPK_VG4_4Z2Z_D}))
6449 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6451 case Intrinsic::aarch64_sve_pext_x2: {
6453 Node->getValueType(0),
6454 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6455 AArch64::PEXT_2PCI_D}))
6456 SelectPExtPair(Node,
Op);
6463 unsigned IntNo =
Node->getConstantOperandVal(1);
6464 if (
Node->getNumOperands() >= 3)
6465 VT =
Node->getOperand(2)->getValueType(0);
6469 case Intrinsic::aarch64_neon_st1x2: {
6470 if (VT == MVT::v8i8) {
6471 SelectStore(Node, 2, AArch64::ST1Twov8b);
6473 }
else if (VT == MVT::v16i8) {
6474 SelectStore(Node, 2, AArch64::ST1Twov16b);
6476 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6477 VT == MVT::v4bf16) {
6478 SelectStore(Node, 2, AArch64::ST1Twov4h);
6480 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6481 VT == MVT::v8bf16) {
6482 SelectStore(Node, 2, AArch64::ST1Twov8h);
6484 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6485 SelectStore(Node, 2, AArch64::ST1Twov2s);
6487 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6488 SelectStore(Node, 2, AArch64::ST1Twov4s);
6490 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6491 SelectStore(Node, 2, AArch64::ST1Twov2d);
6493 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6494 SelectStore(Node, 2, AArch64::ST1Twov1d);
6499 case Intrinsic::aarch64_neon_st1x3: {
6500 if (VT == MVT::v8i8) {
6501 SelectStore(Node, 3, AArch64::ST1Threev8b);
6503 }
else if (VT == MVT::v16i8) {
6504 SelectStore(Node, 3, AArch64::ST1Threev16b);
6506 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6507 VT == MVT::v4bf16) {
6508 SelectStore(Node, 3, AArch64::ST1Threev4h);
6510 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6511 VT == MVT::v8bf16) {
6512 SelectStore(Node, 3, AArch64::ST1Threev8h);
6514 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6515 SelectStore(Node, 3, AArch64::ST1Threev2s);
6517 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6518 SelectStore(Node, 3, AArch64::ST1Threev4s);
6520 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6521 SelectStore(Node, 3, AArch64::ST1Threev2d);
6523 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6524 SelectStore(Node, 3, AArch64::ST1Threev1d);
6529 case Intrinsic::aarch64_neon_st1x4: {
6530 if (VT == MVT::v8i8) {
6531 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6533 }
else if (VT == MVT::v16i8) {
6534 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6536 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6537 VT == MVT::v4bf16) {
6538 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6540 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6541 VT == MVT::v8bf16) {
6542 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6544 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6545 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6547 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6548 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6550 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6551 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6553 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6554 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6559 case Intrinsic::aarch64_neon_st2: {
6560 if (VT == MVT::v8i8) {
6561 SelectStore(Node, 2, AArch64::ST2Twov8b);
6563 }
else if (VT == MVT::v16i8) {
6564 SelectStore(Node, 2, AArch64::ST2Twov16b);
6566 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6567 VT == MVT::v4bf16) {
6568 SelectStore(Node, 2, AArch64::ST2Twov4h);
6570 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6571 VT == MVT::v8bf16) {
6572 SelectStore(Node, 2, AArch64::ST2Twov8h);
6574 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6575 SelectStore(Node, 2, AArch64::ST2Twov2s);
6577 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6578 SelectStore(Node, 2, AArch64::ST2Twov4s);
6580 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6581 SelectStore(Node, 2, AArch64::ST2Twov2d);
6583 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6584 SelectStore(Node, 2, AArch64::ST1Twov1d);
6589 case Intrinsic::aarch64_neon_st3: {
6590 if (VT == MVT::v8i8) {
6591 SelectStore(Node, 3, AArch64::ST3Threev8b);
6593 }
else if (VT == MVT::v16i8) {
6594 SelectStore(Node, 3, AArch64::ST3Threev16b);
6596 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6597 VT == MVT::v4bf16) {
6598 SelectStore(Node, 3, AArch64::ST3Threev4h);
6600 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6601 VT == MVT::v8bf16) {
6602 SelectStore(Node, 3, AArch64::ST3Threev8h);
6604 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6605 SelectStore(Node, 3, AArch64::ST3Threev2s);
6607 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6608 SelectStore(Node, 3, AArch64::ST3Threev4s);
6610 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6611 SelectStore(Node, 3, AArch64::ST3Threev2d);
6613 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6614 SelectStore(Node, 3, AArch64::ST1Threev1d);
6619 case Intrinsic::aarch64_neon_st4: {
6620 if (VT == MVT::v8i8) {
6621 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6623 }
else if (VT == MVT::v16i8) {
6624 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6626 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6627 VT == MVT::v4bf16) {
6628 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6630 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6631 VT == MVT::v8bf16) {
6632 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6634 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6635 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6637 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6638 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6640 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6641 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6643 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6644 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6649 case Intrinsic::aarch64_neon_st2lane: {
6650 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6651 SelectStoreLane(Node, 2, AArch64::ST2i8);
6653 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6654 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6655 SelectStoreLane(Node, 2, AArch64::ST2i16);
6657 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6659 SelectStoreLane(Node, 2, AArch64::ST2i32);
6661 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6663 SelectStoreLane(Node, 2, AArch64::ST2i64);
6668 case Intrinsic::aarch64_neon_st3lane: {
6669 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6670 SelectStoreLane(Node, 3, AArch64::ST3i8);
6672 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6673 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6674 SelectStoreLane(Node, 3, AArch64::ST3i16);
6676 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6678 SelectStoreLane(Node, 3, AArch64::ST3i32);
6680 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6682 SelectStoreLane(Node, 3, AArch64::ST3i64);
6687 case Intrinsic::aarch64_neon_st4lane: {
6688 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6689 SelectStoreLane(Node, 4, AArch64::ST4i8);
6691 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6692 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6693 SelectStoreLane(Node, 4, AArch64::ST4i16);
6695 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6697 SelectStoreLane(Node, 4, AArch64::ST4i32);
6699 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6701 SelectStoreLane(Node, 4, AArch64::ST4i64);
6706 case Intrinsic::aarch64_sve_st2q: {
6707 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6710 case Intrinsic::aarch64_sve_st3q: {
6711 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6714 case Intrinsic::aarch64_sve_st4q: {
6715 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6718 case Intrinsic::aarch64_sve_st2: {
6719 if (VT == MVT::nxv16i8) {
6720 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6722 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6723 VT == MVT::nxv8bf16) {
6724 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6726 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6727 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6729 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6730 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6735 case Intrinsic::aarch64_sve_st3: {
6736 if (VT == MVT::nxv16i8) {
6737 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6739 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6740 VT == MVT::nxv8bf16) {
6741 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6743 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6744 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6746 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6747 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6752 case Intrinsic::aarch64_sve_st4: {
6753 if (VT == MVT::nxv16i8) {
6754 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6756 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6757 VT == MVT::nxv8bf16) {
6758 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6760 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6761 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6763 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6764 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6772 case AArch64ISD::LD2post: {
6773 if (VT == MVT::v8i8) {
6774 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6776 }
else if (VT == MVT::v16i8) {
6777 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6779 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6780 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6782 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6783 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6785 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6786 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6788 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6789 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6791 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6792 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6794 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6795 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6800 case AArch64ISD::LD3post: {
6801 if (VT == MVT::v8i8) {
6802 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6804 }
else if (VT == MVT::v16i8) {
6805 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6807 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6808 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6810 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6811 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6813 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6814 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6816 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6817 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6819 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6820 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6822 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6823 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6828 case AArch64ISD::LD4post: {
6829 if (VT == MVT::v8i8) {
6830 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6832 }
else if (VT == MVT::v16i8) {
6833 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6835 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6836 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6838 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6839 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6841 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6842 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6844 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6845 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6847 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6848 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6850 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6851 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6856 case AArch64ISD::LD1x2post: {
6857 if (VT == MVT::v8i8) {
6858 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6860 }
else if (VT == MVT::v16i8) {
6861 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6863 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6864 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6866 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6867 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6869 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6870 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6872 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6873 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6875 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6876 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6878 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6879 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6884 case AArch64ISD::LD1x3post: {
6885 if (VT == MVT::v8i8) {
6886 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6888 }
else if (VT == MVT::v16i8) {
6889 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6891 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6892 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6894 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6895 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6897 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6898 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6900 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6901 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6903 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6904 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6906 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6907 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6912 case AArch64ISD::LD1x4post: {
6913 if (VT == MVT::v8i8) {
6914 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6916 }
else if (VT == MVT::v16i8) {
6917 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6919 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6920 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6922 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6923 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6925 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6926 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6928 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6929 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6931 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6932 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6934 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6935 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6940 case AArch64ISD::LD1DUPpost: {
6941 if (VT == MVT::v8i8) {
6942 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6944 }
else if (VT == MVT::v16i8) {
6945 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6947 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6948 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6950 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6951 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6953 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6954 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6956 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6957 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
6959 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6960 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
6962 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6963 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
6968 case AArch64ISD::LD2DUPpost: {
6969 if (VT == MVT::v8i8) {
6970 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
6972 }
else if (VT == MVT::v16i8) {
6973 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
6975 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6976 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
6978 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6979 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
6981 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6982 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
6984 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6985 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
6987 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6988 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
6990 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6991 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
6996 case AArch64ISD::LD3DUPpost: {
6997 if (VT == MVT::v8i8) {
6998 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7000 }
else if (VT == MVT::v16i8) {
7001 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7003 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7004 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7006 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7007 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7009 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7010 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7012 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7013 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7015 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7016 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7018 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7019 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7024 case AArch64ISD::LD4DUPpost: {
7025 if (VT == MVT::v8i8) {
7026 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7028 }
else if (VT == MVT::v16i8) {
7029 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7031 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7032 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7034 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7035 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7037 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7038 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7040 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7041 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7043 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7044 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7046 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7047 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7052 case AArch64ISD::LD1LANEpost: {
7053 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7054 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7056 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7057 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7058 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7060 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7062 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7064 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7066 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7071 case AArch64ISD::LD2LANEpost: {
7072 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7073 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7075 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7076 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7077 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7079 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7081 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7083 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7085 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7090 case AArch64ISD::LD3LANEpost: {
7091 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7092 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7094 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7095 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7096 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7098 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7100 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7102 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7104 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7109 case AArch64ISD::LD4LANEpost: {
7110 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7111 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7113 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7114 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7115 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7117 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7119 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7121 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7123 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7128 case AArch64ISD::ST2post: {
7129 VT =
Node->getOperand(1).getValueType();
7130 if (VT == MVT::v8i8) {
7131 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7133 }
else if (VT == MVT::v16i8) {
7134 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7136 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7137 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7139 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7140 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7142 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7143 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7145 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7146 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7148 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7149 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7151 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7152 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7157 case AArch64ISD::ST3post: {
7158 VT =
Node->getOperand(1).getValueType();
7159 if (VT == MVT::v8i8) {
7160 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7162 }
else if (VT == MVT::v16i8) {
7163 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7165 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7166 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7168 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7169 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7171 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7172 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7174 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7175 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7177 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7178 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7180 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7181 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7186 case AArch64ISD::ST4post: {
7187 VT =
Node->getOperand(1).getValueType();
7188 if (VT == MVT::v8i8) {
7189 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7191 }
else if (VT == MVT::v16i8) {
7192 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7194 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7195 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7197 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7198 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7200 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7201 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7203 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7204 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7206 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7207 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7209 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7210 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7215 case AArch64ISD::ST1x2post: {
7216 VT =
Node->getOperand(1).getValueType();
7217 if (VT == MVT::v8i8) {
7218 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7220 }
else if (VT == MVT::v16i8) {
7221 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7223 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7224 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7226 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7227 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7229 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7230 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7232 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7233 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7235 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7236 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7238 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7239 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7244 case AArch64ISD::ST1x3post: {
7245 VT =
Node->getOperand(1).getValueType();
7246 if (VT == MVT::v8i8) {
7247 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7249 }
else if (VT == MVT::v16i8) {
7250 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7252 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7253 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7255 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7256 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7258 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7259 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7261 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7262 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7264 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7265 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7267 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7268 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7273 case AArch64ISD::ST1x4post: {
7274 VT =
Node->getOperand(1).getValueType();
7275 if (VT == MVT::v8i8) {
7276 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7278 }
else if (VT == MVT::v16i8) {
7279 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7281 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7282 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7284 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7285 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7287 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7288 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7290 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7291 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7293 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7294 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7296 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7297 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7302 case AArch64ISD::ST2LANEpost: {
7303 VT =
Node->getOperand(1).getValueType();
7304 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7305 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7307 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7308 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7309 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7311 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7313 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7315 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7317 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7322 case AArch64ISD::ST3LANEpost: {
7323 VT =
Node->getOperand(1).getValueType();
7324 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7325 SelectPostStoreLane(Node, 3, AArch64::ST3i8_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, 3, AArch64::ST3i16_POST);
7331 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7333 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7335 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7337 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7342 case AArch64ISD::ST4LANEpost: {
7343 VT =
Node->getOperand(1).getValueType();
7344 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7345 SelectPostStoreLane(Node, 4, AArch64::ST4i8_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, 4, AArch64::ST4i16_POST);
7351 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7353 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7355 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7357 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7372 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7384 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7388 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7389 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7404 return MemIntr->getMemoryVT();
7411 DataVT = Load->getValueType(0);
7413 DataVT = Load->getValueType(0);
7415 DataVT = Store->getValue().getValueType();
7417 DataVT = Store->getValue().getValueType();
7424 const unsigned Opcode = Root->
getOpcode();
7428 case AArch64ISD::LD1_MERGE_ZERO:
7429 case AArch64ISD::LD1S_MERGE_ZERO:
7430 case AArch64ISD::LDNF1_MERGE_ZERO:
7431 case AArch64ISD::LDNF1S_MERGE_ZERO:
7433 case AArch64ISD::ST1_PRED:
7445 case Intrinsic::aarch64_sme_ldr:
7446 case Intrinsic::aarch64_sme_str:
7447 return MVT::nxv16i8;
7448 case Intrinsic::aarch64_sve_prf:
7453 case Intrinsic::aarch64_sve_ld2_sret:
7454 case Intrinsic::aarch64_sve_ld2q_sret:
7457 case Intrinsic::aarch64_sve_st2q:
7460 case Intrinsic::aarch64_sve_ld3_sret:
7461 case Intrinsic::aarch64_sve_ld3q_sret:
7464 case Intrinsic::aarch64_sve_st3q:
7467 case Intrinsic::aarch64_sve_ld4_sret:
7468 case Intrinsic::aarch64_sve_ld4q_sret:
7471 case Intrinsic::aarch64_sve_st4q:
7474 case Intrinsic::aarch64_sve_ld1udq:
7475 case Intrinsic::aarch64_sve_st1dq:
7476 return EVT(MVT::nxv1i64);
7477 case Intrinsic::aarch64_sve_ld1uwq:
7478 case Intrinsic::aarch64_sve_st1wq:
7479 return EVT(MVT::nxv1i32);
7486template <
int64_t Min,
int64_t Max>
7487bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7491 const DataLayout &
DL = CurDAG->getDataLayout();
7492 const MachineFrameInfo &MFI = MF->getFrameInfo();
7500 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7514 int64_t MulImm = std::numeric_limits<int64_t>::max();
7515 if (VScale.
getOpcode() == ISD::VSCALE) {
7518 int64_t ByteOffset =
C->getSExtValue();
7519 const auto KnownVScale =
7522 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7525 MulImm = ByteOffset / KnownVScale;
7532 if ((MulImm % MemWidthBytes) != 0)
7535 int64_t
Offset = MulImm / MemWidthBytes;
7539 Base =
N.getOperand(0);
7548 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7554bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7573 int64_t ImmOff =
C->getSExtValue();
7574 unsigned Size = 1 << Scale;
7583 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7585 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7596 if (
C->getZExtValue() == Scale) {
7605bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7606 const AArch64TargetLowering *TLI =
7607 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7612bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7613 EVT VT =
N.getValueType();
7617bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7622 int64_t ImmOff =
C->getSExtValue();
7623 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7624 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7629 if (
SDValue C = MatchConstantOffset(
N)) {
7630 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7636 if (CurDAG->isBaseWithConstantOffset(
N)) {
7637 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7638 Base =
N.getOperand(0);
7646 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7650bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7670 uint64_t LowerBound = 0, UpperBound = 64;
7688 if (CN->getAPIntValue().uge(LowerBound) &&
7689 CN->getAPIntValue().ult(UpperBound)) {
7691 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 getScalarSizeInBits() const
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 bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
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.