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))
2095 EVT VT =
Node->getValueType(0);
2098 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2101 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2102 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2103 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2106 unsigned ChainIdx = NumOutVecs;
2108 CurDAG->RemoveDeadNode(Node);
2111void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2112 unsigned NumOutVecs,
2115 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2120 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2124 EVT VT =
Node->getValueType(0);
2127 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2130 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2131 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2132 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2135 unsigned ChainIdx = NumOutVecs;
2137 CurDAG->RemoveDeadNode(Node);
2140void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2143 EVT VT =
N->getValueType(0);
2146 SDValue Zd = createZMulTuple(Regs);
2147 SDValue Zn =
N->getOperand(1 + NumVecs);
2154 for (
unsigned i = 0; i < NumVecs; ++i)
2155 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2156 AArch64::zsub0 + i,
DL, VT, SuperReg));
2158 CurDAG->RemoveDeadNode(
N);
2188template <
unsigned MaxIdx,
unsigned Scale>
2189void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2190 unsigned BaseReg,
unsigned Op) {
2191 unsigned TileNum = 0;
2192 if (BaseReg != AArch64::ZA)
2193 TileNum =
N->getConstantOperandVal(2);
2199 if (BaseReg == AArch64::ZA)
2204 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2210 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2212 EVT VT =
N->getValueType(0);
2213 for (
unsigned I = 0;
I < NumVecs; ++
I)
2215 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2218 unsigned ChainIdx = NumVecs;
2220 CurDAG->RemoveDeadNode(
N);
2223void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2224 unsigned Op,
unsigned MaxIdx,
2225 unsigned Scale,
unsigned BaseReg) {
2230 if (BaseReg != AArch64::ZA)
2234 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2241 if (BaseReg != AArch64::ZA )
2242 Ops.push_back(
N->getOperand(2));
2245 Ops.push_back(
N->getOperand(0));
2246 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2248 EVT VT =
N->getValueType(0);
2249 for (
unsigned I = 0;
I < NumVecs; ++
I)
2251 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2255 unsigned ChainIdx = NumVecs;
2257 CurDAG->RemoveDeadNode(
N);
2260void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2261 unsigned NumOutVecs,
2265 EVT VT =
N->getValueType(0);
2266 unsigned NumInVecs =
N->getNumOperands() - 1;
2270 assert((NumInVecs == 2 || NumInVecs == 4) &&
2271 "Don't know how to handle multi-register input!");
2273 Ops.push_back(createZMulTuple(Regs));
2276 for (
unsigned I = 0;
I < NumInVecs;
I++)
2277 Ops.push_back(
N->getOperand(1 +
I));
2280 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2283 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2284 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2285 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2286 CurDAG->RemoveDeadNode(
N);
2289void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2292 EVT VT =
N->getOperand(2)->getValueType(0);
2300 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2309void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2310 unsigned Scale,
unsigned Opc_rr,
2316 SDValue RegSeq = createZTuple(Regs);
2322 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2323 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2329 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2337 const DataLayout &
DL = CurDAG->getDataLayout();
2338 const TargetLowering *TLI = getTargetLowering();
2342 int FI = FINode->getIndex();
2344 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2351void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2354 EVT VT =
N->getOperand(2)->getValueType(0);
2355 const EVT ResTys[] = {MVT::i64,
2367 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2407void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2410 EVT VT =
N->getValueType(0);
2422 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2424 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2426 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2428 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2432 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2433 AArch64::qsub2, AArch64::qsub3 };
2434 for (
unsigned i = 0; i < NumVecs; ++i) {
2435 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2442 CurDAG->RemoveDeadNode(
N);
2445void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2448 EVT VT =
N->getValueType(0);
2460 const EVT ResTys[] = {MVT::i64,
2463 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2466 CurDAG->getTargetConstant(LaneNo, dl,
2471 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2483 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2484 AArch64::qsub2, AArch64::qsub3 };
2485 for (
unsigned i = 0; i < NumVecs; ++i) {
2486 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2496 CurDAG->RemoveDeadNode(
N);
2499void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2502 EVT VT =
N->getOperand(2)->getValueType(0);
2514 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2516 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2518 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2527void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2530 EVT VT =
N->getOperand(2)->getValueType(0);
2542 const EVT ResTys[] = {MVT::i64,
2545 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2547 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2551 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2562 unsigned &LSB,
unsigned &MSB,
2563 unsigned NumberOfIgnoredLowBits,
2564 bool BiggerPattern) {
2566 "N must be a AND operation to call this function");
2568 EVT VT =
N->getValueType(0);
2573 assert((VT == MVT::i32 || VT == MVT::i64) &&
2574 "Type checking must have been done before calling this function");
2588 const SDNode *Op0 =
N->getOperand(0).getNode();
2595 if (AndImm & (AndImm + 1))
2598 bool ClampMSB =
false;
2618 ClampMSB = (VT == MVT::i32);
2619 }
else if (BiggerPattern) {
2625 Opd0 =
N->getOperand(0);
2631 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2634 <<
": Found large shift immediate, this should not happen\n"));
2648 MSB = MSB > 31 ? 31 : MSB;
2650 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2655 SDValue &Opd0,
unsigned &Immr,
2659 EVT VT =
N->getValueType(0);
2661 assert((VT == MVT::i32 || VT == MVT::i64) &&
2662 "Type checking must have been done before calling this function");
2666 Op =
Op->getOperand(0);
2667 VT =
Op->getValueType(0);
2676 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2680 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2681 Opd0 =
Op.getOperand(0);
2683 Imms = ShiftImm + Width - 1;
2711 Opd0 =
N->getOperand(0).getOperand(0);
2721 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2728 unsigned &Immr,
unsigned &Imms,
2729 bool BiggerPattern) {
2731 "N must be a SHR/SRA operation to call this function");
2733 EVT VT =
N->getValueType(0);
2738 assert((VT == MVT::i32 || VT == MVT::i64) &&
2739 "Type checking must have been done before calling this function");
2749 Opd0 =
N->getOperand(0).getOperand(0);
2750 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2756 Opd0 =
N->getOperand(0).getOperand(0);
2759 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2760 }
else if (BiggerPattern) {
2764 Opd0 =
N->getOperand(0);
2773 <<
": Found large shift immediate, this should not happen\n"));
2782 "bad amount in shift node!");
2783 int immr = SrlImm - ShlImm;
2788 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2790 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2794bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2797 EVT VT =
N->getValueType(0);
2798 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2799 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2810 unsigned Immr = ShiftImm;
2812 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2813 CurDAG->getTargetConstant(Imms, dl, VT)};
2814 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2819 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2820 unsigned NumberOfIgnoredLowBits = 0,
2821 bool BiggerPattern =
false) {
2822 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2825 switch (
N->getOpcode()) {
2827 if (!
N->isMachineOpcode())
2832 NumberOfIgnoredLowBits, BiggerPattern);
2841 unsigned NOpc =
N->getMachineOpcode();
2845 case AArch64::SBFMWri:
2846 case AArch64::UBFMWri:
2847 case AArch64::SBFMXri:
2848 case AArch64::UBFMXri:
2850 Opd0 =
N->getOperand(0);
2851 Immr =
N->getConstantOperandVal(1);
2852 Imms =
N->getConstantOperandVal(2);
2859bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2860 unsigned Opc, Immr, Imms;
2865 EVT VT =
N->getValueType(0);
2870 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2871 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2872 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2874 SDNode *
BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2875 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2881 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2882 CurDAG->getTargetConstant(Imms, dl, VT)};
2883 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2892 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2893 assert((VT == MVT::i32 || VT == MVT::i64) &&
2894 "i32 or i64 mask type expected!");
2898 APInt SignificantDstMask =
2902 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2903 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2936 APInt OpUsefulBits(UsefulBits);
2940 OpUsefulBits <<= MSB - Imm + 1;
2945 OpUsefulBits <<= Imm;
2947 OpUsefulBits <<= MSB + 1;
2950 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2956 UsefulBits &= OpUsefulBits;
2973 APInt Mask(UsefulBits);
2974 Mask.clearAllBits();
2982 Mask.lshrInPlace(ShiftAmt);
2988 Mask.lshrInPlace(ShiftAmt);
3004 APInt OpUsefulBits(UsefulBits);
3018 OpUsefulBits <<= Width;
3021 if (
Op.getOperand(1) == Orig) {
3023 Mask = ResultUsefulBits & OpUsefulBits;
3027 if (
Op.getOperand(0) == Orig)
3029 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3035 OpUsefulBits <<= Width;
3037 OpUsefulBits <<= LSB;
3039 if (
Op.getOperand(1) == Orig) {
3041 Mask = ResultUsefulBits & OpUsefulBits;
3042 Mask.lshrInPlace(LSB);
3045 if (
Op.getOperand(0) == Orig)
3046 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3063 case AArch64::ANDSWri:
3064 case AArch64::ANDSXri:
3065 case AArch64::ANDWri:
3066 case AArch64::ANDXri:
3070 case AArch64::UBFMWri:
3071 case AArch64::UBFMXri:
3074 case AArch64::ORRWrs:
3075 case AArch64::ORRXrs:
3080 case AArch64::BFMWri:
3081 case AArch64::BFMXri:
3084 case AArch64::STRBBui:
3085 case AArch64::STURBBi:
3091 case AArch64::STRHHui:
3092 case AArch64::STURHHi:
3105 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3107 UsefulBits =
APInt(Bitwidth, 0);
3116 UsersUsefulBits |= UsefulBitsForUse;
3121 UsefulBits &= UsersUsefulBits;
3131 EVT VT =
Op.getValueType();
3134 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3137 if (ShlAmount > 0) {
3140 UBFMOpc, dl, VT,
Op,
3145 assert(ShlAmount < 0 &&
"expected right shift");
3146 int ShrAmount = -ShlAmount;
3158 const uint64_t NonZeroBits,
3165 const uint64_t NonZeroBits,
3172 bool BiggerPattern,
SDValue &Src,
3173 int &DstLSB,
int &Width) {
3174 EVT VT =
Op.getValueType();
3183 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3187 switch (
Op.getOpcode()) {
3192 NonZeroBits, Src, DstLSB, Width);
3195 NonZeroBits, Src, DstLSB, Width);
3208 EVT VT =
Op.getValueType();
3209 assert((VT == MVT::i32 || VT == MVT::i64) &&
3210 "Caller guarantees VT is one of i32 or i64");
3223 assert((~AndImm & NonZeroBits) == 0 &&
3224 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3253 if (!BiggerPattern && !AndOp0.
hasOneUse())
3272 <<
"Found large Width in bit-field-positioning -- this indicates no "
3273 "proper combining / constant folding was performed\n");
3282 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3297 "Op.getNode() should be a SHL node to call this function");
3299 "Op.getNode() should shift ShlImm to call this function");
3306 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3330 EVT VT =
Op.getValueType();
3331 assert((VT == MVT::i32 || VT == MVT::i64) &&
3332 "Caller guarantees that type is i32 or i64");
3339 if (!BiggerPattern && !
Op.hasOneUse())
3348 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3356 assert(VT == MVT::i32 || VT == MVT::i64);
3367 EVT VT =
N->getValueType(0);
3368 if (VT != MVT::i32 && VT != MVT::i64)
3386 if (!
And.hasOneUse() ||
3396 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3403 if ((OrImm & NotKnownZero) != 0) {
3415 unsigned ImmS = Width - 1;
3421 bool IsBFI = LSB != 0;
3426 unsigned OrChunks = 0, BFIChunks = 0;
3427 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3428 if (((OrImm >> Shift) & 0xFFFF) != 0)
3430 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3433 if (BFIChunks > OrChunks)
3439 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3447 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3456 if (!Dst.hasOneUse())
3459 EVT VT = Dst.getValueType();
3460 assert((VT == MVT::i32 || VT == MVT::i64) &&
3461 "Caller should guarantee that VT is one of i32 or i64");
3489 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3490 unsigned MaskWidth =
3493 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3499 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3500 ShiftedOperand =
SDValue(UBFMNode, 0);
3529 const bool BiggerPattern) {
3530 EVT VT =
N->getValueType(0);
3531 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3532 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3533 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3534 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3535 assert((VT == MVT::i32 || VT == MVT::i64) &&
3536 "Expect result type to be i32 or i64 since N is combinable to BFM");
3543 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3546 if (BiggerPattern) {
3569 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3631 EVT VT =
N->getValueType(0);
3632 if (VT != MVT::i32 && VT != MVT::i64)
3640 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3641 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3661 for (
int I = 0;
I < 4; ++
I) {
3664 unsigned ImmR, ImmS;
3665 bool BiggerPattern =
I / 2;
3666 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3668 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3674 NumberOfIgnoredLowBits, BiggerPattern)) {
3677 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3678 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3683 Width = ImmS - ImmR + 1;
3694 Src, DstLSB, Width)) {
3702 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3712 APInt BitsToBeInserted =
3715 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3739 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3772 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3774 if (Src->hasOneUse() &&
3777 Src = Src->getOperand(0);
3787 unsigned ImmS = Width - 1;
3793 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3801bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3810 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3823bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3827 EVT VT =
N->getValueType(0);
3828 if (VT != MVT::i32 && VT != MVT::i64)
3834 Op0, DstLSB, Width))
3840 unsigned ImmS = Width - 1;
3843 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3844 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3845 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3846 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3852bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3853 EVT VT =
N->getValueType(0);
3856 switch (
N->getOpcode()) {
3858 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3861 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3864 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3867 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3875 if (VT == MVT::i32) {
3878 }
else if (VT == MVT::i64) {
3884 SDValue ShiftAmt =
N->getOperand(1);
3904 (Add0Imm %
Size == 0)) {
3910 if (SubVT == MVT::i32) {
3911 NegOpc = AArch64::SUBWrr;
3912 ZeroReg = AArch64::WZR;
3914 assert(SubVT == MVT::i64);
3915 NegOpc = AArch64::SUBXrr;
3916 ZeroReg = AArch64::XZR;
3919 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3920 MachineSDNode *Neg =
3921 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3922 NewShiftAmt =
SDValue(Neg, 0);
3930 if (SubVT == MVT::i32) {
3931 NotOpc = AArch64::ORNWrr;
3932 ZeroReg = AArch64::WZR;
3934 assert(SubVT == MVT::i64);
3935 NotOpc = AArch64::ORNXrr;
3936 ZeroReg = AArch64::XZR;
3939 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3940 MachineSDNode *
Not =
3941 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3942 NewShiftAmt =
SDValue(Not, 0);
3963 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3964 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3965 MachineSDNode *
Ext = CurDAG->getMachineNode(
3966 AArch64::SUBREG_TO_REG,
DL, VT,
3967 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3968 NewShiftAmt =
SDValue(Ext, 0);
3972 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3979 bool isReciprocal) {
3982 FVal = CN->getValueAPF();
3985 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4014 if (!IsExact || !IntVal.isPowerOf2())
4016 unsigned FBits = IntVal.logBase2();
4020 if (FBits == 0 || FBits > RegWidth)
return false;
4026bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4027 unsigned RegWidth) {
4032bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4034 unsigned RegWidth) {
4044 RegString.
split(Fields,
':');
4046 if (Fields.
size() == 1)
4050 &&
"Invalid number of fields in read register string");
4053 bool AllIntFields =
true;
4057 AllIntFields &= !
Field.getAsInteger(10, IntField);
4058 Ops.push_back(IntField);
4062 "Unexpected non-integer value in special register string.");
4067 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4068 (
Ops[3] << 3) | (
Ops[4]);
4075bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4077 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4080 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4082 unsigned Opcode64Bit = AArch64::MRS;
4087 const auto *TheReg =
4088 AArch64SysReg::lookupSysRegByName(RegString->getString());
4089 if (TheReg && TheReg->Readable &&
4090 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4091 Imm = TheReg->Encoding;
4097 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4098 Opcode64Bit = AArch64::ADR;
4106 SDValue InChain =
N->getOperand(0);
4107 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4108 if (!ReadIs128Bit) {
4109 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4110 {SysRegImm, InChain});
4112 SDNode *MRRS = CurDAG->getMachineNode(
4114 {MVT::Untyped , MVT::Other },
4115 {SysRegImm, InChain});
4119 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4121 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4127 ReplaceUses(
SDValue(
N, 2), OutChain);
4136bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4138 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4141 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4143 if (!WriteIs128Bit) {
4149 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4152 "Expected a constant integer expression.");
4153 unsigned Reg = PMapper->Encoding;
4154 uint64_t Immed =
N->getConstantOperandVal(2);
4155 CurDAG->SelectNodeTo(
4156 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4157 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4163 if (trySelectPState(
4164 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4165 AArch64::MSRpstateImm4))
4167 if (trySelectPState(
4168 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4169 AArch64::MSRpstateImm1))
4178 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4179 if (TheReg && TheReg->Writeable &&
4180 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4181 Imm = TheReg->Encoding;
4190 if (!WriteIs128Bit) {
4191 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4192 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4193 N->getOperand(2), InChain);
4197 SDNode *Pair = CurDAG->getMachineNode(
4198 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4199 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4202 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4204 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4206 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4207 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4215bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4220 if (Subtarget->hasLSE())
return false;
4222 if (MemTy == MVT::i8)
4223 Opcode = AArch64::CMP_SWAP_8;
4224 else if (MemTy == MVT::i16)
4225 Opcode = AArch64::CMP_SWAP_16;
4226 else if (MemTy == MVT::i32)
4227 Opcode = AArch64::CMP_SWAP_32;
4228 else if (MemTy == MVT::i64)
4229 Opcode = AArch64::CMP_SWAP_64;
4233 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4234 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4236 SDNode *CmpSwap = CurDAG->getMachineNode(
4238 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4245 CurDAG->RemoveDeadNode(
N);
4250bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4251 SDValue &Shift,
bool Negate) {
4265 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4272 if ((Val & ~0xff) == 0) {
4273 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4278 if ((Val & ~0xff00) == 0) {
4279 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4291bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4315 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4316 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4323 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4324 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4328 if (Val <= 65280 && Val % 256 == 0) {
4329 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4330 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4341bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4351 int32_t ImmVal, ShiftVal;
4356 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4357 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4361bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4363 int64_t ImmVal = CNode->getSExtValue();
4365 if (ImmVal >= -128 && ImmVal < 128) {
4366 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4373bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4375 uint64_t ImmVal = CNode->getZExtValue();
4385 ImmVal &= 0xFFFFFFFF;
4394 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4401bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4404 uint64_t ImmVal = CNode->getZExtValue();
4414 ImmVal |= ImmVal << 8;
4415 ImmVal |= ImmVal << 16;
4416 ImmVal |= ImmVal << 32;
4420 ImmVal |= ImmVal << 16;
4421 ImmVal |= ImmVal << 32;
4424 ImmVal &= 0xFFFFFFFF;
4425 ImmVal |= ImmVal << 32;
4435 Imm = CurDAG->getTargetConstant(encoding,
DL, MVT::i64);
4447bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4448 uint64_t
High,
bool AllowSaturation,
4451 uint64_t ImmVal = CN->getZExtValue();
4458 if (ImmVal >
High) {
4459 if (!AllowSaturation)
4464 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4471bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4485 const TargetLowering *TLI = getTargetLowering();
4488 SDValue FiOp = CurDAG->getTargetFrameIndex(
4490 int TagOffset =
N->getConstantOperandVal(3);
4492 SDNode *Out = CurDAG->getMachineNode(
4493 AArch64::TAGPstack,
DL, MVT::i64,
4494 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4495 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4496 ReplaceNode(
N, Out);
4500void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4502 "llvm.aarch64.tagp third argument must be an immediate");
4503 if (trySelectStackSlotTagP(
N))
4510 int TagOffset =
N->getConstantOperandVal(3);
4511 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4512 {
N->getOperand(1),
N->getOperand(2)});
4513 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4514 {
SDValue(N1, 0),
N->getOperand(2)});
4515 SDNode *N3 = CurDAG->getMachineNode(
4516 AArch64::ADDG,
DL, MVT::i64,
4517 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4518 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4522bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4526 if (
N->getConstantOperandVal(2) != 0)
4528 if (!
N->getOperand(0).isUndef())
4532 EVT VT =
N->getValueType(0);
4533 EVT InVT =
N->getOperand(1).getValueType();
4544 "Expected to insert into a packed scalable vector!");
4547 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4548 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4549 N->getOperand(1), RC));
4553bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4557 if (
N->getConstantOperandVal(1) != 0)
4561 EVT VT =
N->getValueType(0);
4562 EVT InVT =
N->getOperand(0).getValueType();
4573 "Expected to extract from a packed scalable vector!");
4576 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4577 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4578 N->getOperand(0), RC));
4582bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4588 EVT VT =
N->getValueType(0);
4601 (Subtarget->hasSVE2() ||
4602 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4603 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4606 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4610 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4611 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4612 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4619 bool IsXOROperand =
true;
4621 IsXOROperand =
false;
4627 APInt ShlAmt, ShrAmt;
4635 if (!IsXOROperand) {
4637 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4640 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4641 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4642 VT, Zero, MOVIV, ZSub);
4653 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4654 AArch64::XAR_ZZZI_D})) {
4655 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4680 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4690 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4698 bool IsXOROperand =
true;
4700 IsXOROperand =
false;
4703 R1 =
XOR.getOperand(0);
4704 R2 =
XOR.getOperand(1);
4714 if (ShAmt + HsAmt != VTSizeInBits)
4717 if (!IsXOROperand) {
4720 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4729 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4735 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4736 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4738 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4741 if (
R2.getValueType() == VT)
4742 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4750 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4755 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4761 SDNode *XAR =
nullptr;
4765 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4766 AArch64::XAR_ZZZI_D}))
4767 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4769 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4772 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4778 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4779 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4782 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4783 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4789 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4793 ReplaceNode(
N, XAR);
4797void AArch64DAGToDAGISel::Select(SDNode *Node) {
4799 if (
Node->isMachineOpcode()) {
4801 Node->setNodeId(-1);
4806 EVT VT =
Node->getValueType(0);
4808 switch (
Node->getOpcode()) {
4812 case ISD::ATOMIC_CMP_SWAP:
4813 if (SelectCMP_SWAP(Node))
4818 case AArch64ISD::MRRS:
4819 if (tryReadRegister(Node))
4824 case AArch64ISD::MSRR:
4825 if (tryWriteRegister(Node))
4832 if (tryIndexedLoad(Node))
4841 if (tryBitfieldExtractOp(Node))
4843 if (tryBitfieldInsertInZeroOp(Node))
4848 if (tryShiftAmountMod(Node))
4853 if (tryBitfieldExtractOpFromSExt(Node))
4858 if (tryBitfieldInsertOp(Node))
4860 if (trySelectXAR(Node))
4865 if (trySelectCastScalableToFixedLengthVector(Node))
4871 if (trySelectCastFixedLengthToScalableVector(Node))
4880 if (ConstNode->
isZero()) {
4881 if (VT == MVT::i32) {
4883 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4884 ReplaceNode(Node,
New.getNode());
4886 }
else if (VT == MVT::i64) {
4888 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4889 ReplaceNode(Node,
New.getNode());
4900 const TargetLowering *TLI = getTargetLowering();
4901 SDValue TFI = CurDAG->getTargetFrameIndex(
4904 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4905 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4906 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4910 unsigned IntNo =
Node->getConstantOperandVal(1);
4914 case Intrinsic::aarch64_gcsss: {
4918 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4920 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4921 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4922 MVT::Other, Zero,
SDValue(SS1, 0));
4923 ReplaceNode(Node, SS2);
4926 case Intrinsic::aarch64_ldaxp:
4927 case Intrinsic::aarch64_ldxp: {
4929 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4934 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4935 MVT::Other, MemAddr, Chain);
4938 MachineMemOperand *MemOp =
4941 ReplaceNode(Node, Ld);
4944 case Intrinsic::aarch64_stlxp:
4945 case Intrinsic::aarch64_stxp: {
4947 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4955 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4957 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4959 MachineMemOperand *MemOp =
4963 ReplaceNode(Node, St);
4966 case Intrinsic::aarch64_neon_ld1x2:
4967 if (VT == MVT::v8i8) {
4968 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4970 }
else if (VT == MVT::v16i8) {
4971 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4973 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4974 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4976 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4977 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4979 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4980 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4982 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4983 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4985 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4986 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4988 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4989 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
4993 case Intrinsic::aarch64_neon_ld1x3:
4994 if (VT == MVT::v8i8) {
4995 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
4997 }
else if (VT == MVT::v16i8) {
4998 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5000 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5001 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5003 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5004 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5006 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5007 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5009 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5010 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5012 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5013 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5015 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5016 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5020 case Intrinsic::aarch64_neon_ld1x4:
5021 if (VT == MVT::v8i8) {
5022 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5024 }
else if (VT == MVT::v16i8) {
5025 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5027 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5028 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5030 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5031 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5033 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5034 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5036 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5037 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5039 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5040 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5042 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5043 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5047 case Intrinsic::aarch64_neon_ld2:
5048 if (VT == MVT::v8i8) {
5049 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5051 }
else if (VT == MVT::v16i8) {
5052 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5054 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5055 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5057 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5058 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5060 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5061 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5063 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5064 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5066 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5067 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5069 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5070 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5074 case Intrinsic::aarch64_neon_ld3:
5075 if (VT == MVT::v8i8) {
5076 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5078 }
else if (VT == MVT::v16i8) {
5079 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5081 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5082 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5084 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5085 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5087 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5088 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5090 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5091 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5093 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5094 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5096 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5097 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5101 case Intrinsic::aarch64_neon_ld4:
5102 if (VT == MVT::v8i8) {
5103 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5105 }
else if (VT == MVT::v16i8) {
5106 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5108 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5109 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5111 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5112 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5114 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5115 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5117 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5118 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5120 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5121 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5123 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5124 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5128 case Intrinsic::aarch64_neon_ld2r:
5129 if (VT == MVT::v8i8) {
5130 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5132 }
else if (VT == MVT::v16i8) {
5133 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5135 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5136 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5138 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5139 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5141 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5142 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5144 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5145 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5147 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5148 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5150 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5151 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5155 case Intrinsic::aarch64_neon_ld3r:
5156 if (VT == MVT::v8i8) {
5157 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5159 }
else if (VT == MVT::v16i8) {
5160 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5162 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5163 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5165 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5166 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5168 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5169 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5171 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5172 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5174 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5175 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5177 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5178 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5182 case Intrinsic::aarch64_neon_ld4r:
5183 if (VT == MVT::v8i8) {
5184 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5186 }
else if (VT == MVT::v16i8) {
5187 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5189 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5190 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5192 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5193 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5195 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5196 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5198 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5199 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5201 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5202 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5204 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5205 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5209 case Intrinsic::aarch64_neon_ld2lane:
5210 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5211 SelectLoadLane(Node, 2, AArch64::LD2i8);
5213 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5214 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5215 SelectLoadLane(Node, 2, AArch64::LD2i16);
5217 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5219 SelectLoadLane(Node, 2, AArch64::LD2i32);
5221 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5223 SelectLoadLane(Node, 2, AArch64::LD2i64);
5227 case Intrinsic::aarch64_neon_ld3lane:
5228 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5229 SelectLoadLane(Node, 3, AArch64::LD3i8);
5231 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5232 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5233 SelectLoadLane(Node, 3, AArch64::LD3i16);
5235 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5237 SelectLoadLane(Node, 3, AArch64::LD3i32);
5239 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5241 SelectLoadLane(Node, 3, AArch64::LD3i64);
5245 case Intrinsic::aarch64_neon_ld4lane:
5246 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5247 SelectLoadLane(Node, 4, AArch64::LD4i8);
5249 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5250 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5251 SelectLoadLane(Node, 4, AArch64::LD4i16);
5253 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5255 SelectLoadLane(Node, 4, AArch64::LD4i32);
5257 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5259 SelectLoadLane(Node, 4, AArch64::LD4i64);
5263 case Intrinsic::aarch64_ld64b:
5264 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5266 case Intrinsic::aarch64_sve_ld2q_sret: {
5267 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5270 case Intrinsic::aarch64_sve_ld3q_sret: {
5271 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5274 case Intrinsic::aarch64_sve_ld4q_sret: {
5275 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5278 case Intrinsic::aarch64_sve_ld2_sret: {
5279 if (VT == MVT::nxv16i8) {
5280 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5283 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5284 VT == MVT::nxv8bf16) {
5285 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5288 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5289 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5292 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5293 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5299 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5300 if (VT == MVT::nxv16i8) {
5301 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5302 SelectContiguousMultiVectorLoad(
5303 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5304 else if (Subtarget->hasSVE2p1())
5305 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5310 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5311 VT == MVT::nxv8bf16) {
5312 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5313 SelectContiguousMultiVectorLoad(
5314 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5315 else if (Subtarget->hasSVE2p1())
5316 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5321 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5322 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5323 SelectContiguousMultiVectorLoad(
5324 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5325 else if (Subtarget->hasSVE2p1())
5326 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5331 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5332 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5333 SelectContiguousMultiVectorLoad(
5334 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5335 else if (Subtarget->hasSVE2p1())
5336 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5344 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5345 if (VT == MVT::nxv16i8) {
5346 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5347 SelectContiguousMultiVectorLoad(
5348 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5349 else if (Subtarget->hasSVE2p1())
5350 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5355 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5356 VT == MVT::nxv8bf16) {
5357 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5358 SelectContiguousMultiVectorLoad(
5359 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5360 else if (Subtarget->hasSVE2p1())
5361 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5366 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5367 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5368 SelectContiguousMultiVectorLoad(
5369 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5370 else if (Subtarget->hasSVE2p1())
5371 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5376 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5377 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5378 SelectContiguousMultiVectorLoad(
5379 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5380 else if (Subtarget->hasSVE2p1())
5381 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5389 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5390 if (VT == MVT::nxv16i8) {
5391 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5392 SelectContiguousMultiVectorLoad(Node, 2, 0,
5393 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5394 AArch64::LDNT1B_2Z_PSEUDO);
5395 else if (Subtarget->hasSVE2p1())
5396 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5397 AArch64::LDNT1B_2Z);
5401 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5402 VT == MVT::nxv8bf16) {
5403 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5404 SelectContiguousMultiVectorLoad(Node, 2, 1,
5405 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5406 AArch64::LDNT1H_2Z_PSEUDO);
5407 else if (Subtarget->hasSVE2p1())
5408 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5409 AArch64::LDNT1H_2Z);
5413 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5414 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5415 SelectContiguousMultiVectorLoad(Node, 2, 2,
5416 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5417 AArch64::LDNT1W_2Z_PSEUDO);
5418 else if (Subtarget->hasSVE2p1())
5419 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5420 AArch64::LDNT1W_2Z);
5424 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5425 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5426 SelectContiguousMultiVectorLoad(Node, 2, 3,
5427 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5428 AArch64::LDNT1D_2Z_PSEUDO);
5429 else if (Subtarget->hasSVE2p1())
5430 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5431 AArch64::LDNT1D_2Z);
5438 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5439 if (VT == MVT::nxv16i8) {
5440 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5441 SelectContiguousMultiVectorLoad(Node, 4, 0,
5442 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5443 AArch64::LDNT1B_4Z_PSEUDO);
5444 else if (Subtarget->hasSVE2p1())
5445 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5446 AArch64::LDNT1B_4Z);
5450 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5451 VT == MVT::nxv8bf16) {
5452 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5453 SelectContiguousMultiVectorLoad(Node, 4, 1,
5454 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5455 AArch64::LDNT1H_4Z_PSEUDO);
5456 else if (Subtarget->hasSVE2p1())
5457 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5458 AArch64::LDNT1H_4Z);
5462 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5463 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5464 SelectContiguousMultiVectorLoad(Node, 4, 2,
5465 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5466 AArch64::LDNT1W_4Z_PSEUDO);
5467 else if (Subtarget->hasSVE2p1())
5468 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5469 AArch64::LDNT1W_4Z);
5473 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5474 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5475 SelectContiguousMultiVectorLoad(Node, 4, 3,
5476 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5477 AArch64::LDNT1D_4Z_PSEUDO);
5478 else if (Subtarget->hasSVE2p1())
5479 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5480 AArch64::LDNT1D_4Z);
5487 case Intrinsic::aarch64_sve_ld3_sret: {
5488 if (VT == MVT::nxv16i8) {
5489 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5492 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5493 VT == MVT::nxv8bf16) {
5494 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5497 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5498 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5501 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5502 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5508 case Intrinsic::aarch64_sve_ld4_sret: {
5509 if (VT == MVT::nxv16i8) {
5510 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5513 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5514 VT == MVT::nxv8bf16) {
5515 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5518 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5519 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5522 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5523 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5529 case Intrinsic::aarch64_sme_read_hor_vg2: {
5530 if (VT == MVT::nxv16i8) {
5531 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5532 AArch64::MOVA_2ZMXI_H_B);
5534 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5535 VT == MVT::nxv8bf16) {
5536 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5537 AArch64::MOVA_2ZMXI_H_H);
5539 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5540 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5541 AArch64::MOVA_2ZMXI_H_S);
5543 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5544 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5545 AArch64::MOVA_2ZMXI_H_D);
5550 case Intrinsic::aarch64_sme_read_ver_vg2: {
5551 if (VT == MVT::nxv16i8) {
5552 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5553 AArch64::MOVA_2ZMXI_V_B);
5555 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5556 VT == MVT::nxv8bf16) {
5557 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5558 AArch64::MOVA_2ZMXI_V_H);
5560 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5561 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5562 AArch64::MOVA_2ZMXI_V_S);
5564 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5565 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5566 AArch64::MOVA_2ZMXI_V_D);
5571 case Intrinsic::aarch64_sme_read_hor_vg4: {
5572 if (VT == MVT::nxv16i8) {
5573 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5574 AArch64::MOVA_4ZMXI_H_B);
5576 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5577 VT == MVT::nxv8bf16) {
5578 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5579 AArch64::MOVA_4ZMXI_H_H);
5581 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5582 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5583 AArch64::MOVA_4ZMXI_H_S);
5585 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5586 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5587 AArch64::MOVA_4ZMXI_H_D);
5592 case Intrinsic::aarch64_sme_read_ver_vg4: {
5593 if (VT == MVT::nxv16i8) {
5594 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5595 AArch64::MOVA_4ZMXI_V_B);
5597 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5598 VT == MVT::nxv8bf16) {
5599 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5600 AArch64::MOVA_4ZMXI_V_H);
5602 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5603 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5604 AArch64::MOVA_4ZMXI_V_S);
5606 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5607 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5608 AArch64::MOVA_4ZMXI_V_D);
5613 case Intrinsic::aarch64_sme_read_vg1x2: {
5614 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5615 AArch64::MOVA_VG2_2ZMXI);
5618 case Intrinsic::aarch64_sme_read_vg1x4: {
5619 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5620 AArch64::MOVA_VG4_4ZMXI);
5623 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5624 if (VT == MVT::nxv16i8) {
5625 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5627 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5628 VT == MVT::nxv8bf16) {
5629 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5631 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5632 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5634 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5635 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5640 case Intrinsic::aarch64_sme_readz_vert_x2: {
5641 if (VT == MVT::nxv16i8) {
5642 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5644 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5645 VT == MVT::nxv8bf16) {
5646 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5648 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5649 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5651 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5652 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5657 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5658 if (VT == MVT::nxv16i8) {
5659 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5661 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5662 VT == MVT::nxv8bf16) {
5663 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5665 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5666 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5668 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5669 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5674 case Intrinsic::aarch64_sme_readz_vert_x4: {
5675 if (VT == MVT::nxv16i8) {
5676 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5678 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5679 VT == MVT::nxv8bf16) {
5680 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5682 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5683 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5685 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5686 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5691 case Intrinsic::aarch64_sme_readz_x2: {
5692 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5696 case Intrinsic::aarch64_sme_readz_x4: {
5697 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5701 case Intrinsic::swift_async_context_addr: {
5704 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5706 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5707 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5708 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5710 ReplaceUses(
SDValue(Node, 0), Res);
5712 CurDAG->RemoveDeadNode(Node);
5714 auto &MF = CurDAG->getMachineFunction();
5715 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5716 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5719 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5721 Node->getValueType(0),
5722 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5723 AArch64::LUTI2_4ZTZI_S}))
5725 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5728 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5730 Node->getValueType(0),
5731 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5733 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5736 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5738 Node->getValueType(0),
5739 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5740 AArch64::LUTI2_2ZTZI_S}))
5742 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5745 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5747 Node->getValueType(0),
5748 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5749 AArch64::LUTI4_2ZTZI_S}))
5751 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5754 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5755 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5758 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5760 Node->getValueType(0),
5761 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5762 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5764 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5766 Node->getValueType(0),
5767 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5768 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5770 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5772 Node->getValueType(0),
5773 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5774 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5776 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5778 Node->getValueType(0),
5779 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5780 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5785 unsigned IntNo =
Node->getConstantOperandVal(0);
5789 case Intrinsic::aarch64_tagp:
5793 case Intrinsic::ptrauth_auth:
5794 SelectPtrauthAuth(Node);
5797 case Intrinsic::ptrauth_resign:
5798 SelectPtrauthResign(Node);
5801 case Intrinsic::aarch64_neon_tbl2:
5802 SelectTable(Node, 2,
5803 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5806 case Intrinsic::aarch64_neon_tbl3:
5807 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5808 : AArch64::TBLv16i8Three,
5811 case Intrinsic::aarch64_neon_tbl4:
5812 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5813 : AArch64::TBLv16i8Four,
5816 case Intrinsic::aarch64_neon_tbx2:
5817 SelectTable(Node, 2,
5818 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5821 case Intrinsic::aarch64_neon_tbx3:
5822 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5823 : AArch64::TBXv16i8Three,
5826 case Intrinsic::aarch64_neon_tbx4:
5827 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5828 : AArch64::TBXv16i8Four,
5831 case Intrinsic::aarch64_sve_srshl_single_x2:
5833 Node->getValueType(0),
5834 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5835 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5836 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5838 case Intrinsic::aarch64_sve_srshl_single_x4:
5840 Node->getValueType(0),
5841 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5842 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5843 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5845 case Intrinsic::aarch64_sve_urshl_single_x2:
5847 Node->getValueType(0),
5848 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5849 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5850 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5852 case Intrinsic::aarch64_sve_urshl_single_x4:
5854 Node->getValueType(0),
5855 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5856 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5857 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5859 case Intrinsic::aarch64_sve_srshl_x2:
5861 Node->getValueType(0),
5862 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5863 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5864 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5866 case Intrinsic::aarch64_sve_srshl_x4:
5868 Node->getValueType(0),
5869 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5870 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5871 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5873 case Intrinsic::aarch64_sve_urshl_x2:
5875 Node->getValueType(0),
5876 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5877 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5878 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5880 case Intrinsic::aarch64_sve_urshl_x4:
5882 Node->getValueType(0),
5883 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5884 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5885 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5887 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5889 Node->getValueType(0),
5890 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5891 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5892 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5894 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5896 Node->getValueType(0),
5897 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5898 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5899 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5901 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5903 Node->getValueType(0),
5904 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5905 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5906 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5908 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5910 Node->getValueType(0),
5911 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5912 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5913 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5915 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5917 Node->getValueType(0),
5918 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5919 AArch64::FSCALE_2ZZ_D}))
5920 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5922 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5924 Node->getValueType(0),
5925 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5926 AArch64::FSCALE_4ZZ_D}))
5927 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5929 case Intrinsic::aarch64_sme_fp8_scale_x2:
5931 Node->getValueType(0),
5932 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5933 AArch64::FSCALE_2Z2Z_D}))
5934 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5936 case Intrinsic::aarch64_sme_fp8_scale_x4:
5938 Node->getValueType(0),
5939 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5940 AArch64::FSCALE_4Z4Z_D}))
5941 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5943 case Intrinsic::aarch64_sve_whilege_x2:
5945 Node->getValueType(0),
5946 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5947 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5948 SelectWhilePair(Node,
Op);
5950 case Intrinsic::aarch64_sve_whilegt_x2:
5952 Node->getValueType(0),
5953 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5954 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5955 SelectWhilePair(Node,
Op);
5957 case Intrinsic::aarch64_sve_whilehi_x2:
5959 Node->getValueType(0),
5960 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5961 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5962 SelectWhilePair(Node,
Op);
5964 case Intrinsic::aarch64_sve_whilehs_x2:
5966 Node->getValueType(0),
5967 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5968 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5969 SelectWhilePair(Node,
Op);
5971 case Intrinsic::aarch64_sve_whilele_x2:
5973 Node->getValueType(0),
5974 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5975 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5976 SelectWhilePair(Node,
Op);
5978 case Intrinsic::aarch64_sve_whilelo_x2:
5980 Node->getValueType(0),
5981 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5982 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5983 SelectWhilePair(Node,
Op);
5985 case Intrinsic::aarch64_sve_whilels_x2:
5987 Node->getValueType(0),
5988 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5989 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5990 SelectWhilePair(Node,
Op);
5992 case Intrinsic::aarch64_sve_whilelt_x2:
5994 Node->getValueType(0),
5995 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
5996 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
5997 SelectWhilePair(Node,
Op);
5999 case Intrinsic::aarch64_sve_smax_single_x2:
6001 Node->getValueType(0),
6002 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6003 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6004 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6006 case Intrinsic::aarch64_sve_umax_single_x2:
6008 Node->getValueType(0),
6009 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6010 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6011 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6013 case Intrinsic::aarch64_sve_fmax_single_x2:
6015 Node->getValueType(0),
6016 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6017 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6018 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6020 case Intrinsic::aarch64_sve_smax_single_x4:
6022 Node->getValueType(0),
6023 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6024 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6025 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6027 case Intrinsic::aarch64_sve_umax_single_x4:
6029 Node->getValueType(0),
6030 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6031 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6032 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6034 case Intrinsic::aarch64_sve_fmax_single_x4:
6036 Node->getValueType(0),
6037 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6038 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6039 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6041 case Intrinsic::aarch64_sve_smin_single_x2:
6043 Node->getValueType(0),
6044 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6045 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6046 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6048 case Intrinsic::aarch64_sve_umin_single_x2:
6050 Node->getValueType(0),
6051 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6052 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6053 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6055 case Intrinsic::aarch64_sve_fmin_single_x2:
6057 Node->getValueType(0),
6058 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6059 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6060 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6062 case Intrinsic::aarch64_sve_smin_single_x4:
6064 Node->getValueType(0),
6065 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6066 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6067 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6069 case Intrinsic::aarch64_sve_umin_single_x4:
6071 Node->getValueType(0),
6072 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6073 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6074 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6076 case Intrinsic::aarch64_sve_fmin_single_x4:
6078 Node->getValueType(0),
6079 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6080 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6081 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6083 case Intrinsic::aarch64_sve_smax_x2:
6085 Node->getValueType(0),
6086 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6087 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6088 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6090 case Intrinsic::aarch64_sve_umax_x2:
6092 Node->getValueType(0),
6093 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6094 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6095 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6097 case Intrinsic::aarch64_sve_fmax_x2:
6099 Node->getValueType(0),
6100 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6101 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6102 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6104 case Intrinsic::aarch64_sve_smax_x4:
6106 Node->getValueType(0),
6107 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6108 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6109 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6111 case Intrinsic::aarch64_sve_umax_x4:
6113 Node->getValueType(0),
6114 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6115 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6116 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6118 case Intrinsic::aarch64_sve_fmax_x4:
6120 Node->getValueType(0),
6121 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6122 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6123 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6125 case Intrinsic::aarch64_sme_famax_x2:
6127 Node->getValueType(0),
6128 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6129 AArch64::FAMAX_2Z2Z_D}))
6130 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6132 case Intrinsic::aarch64_sme_famax_x4:
6134 Node->getValueType(0),
6135 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6136 AArch64::FAMAX_4Z4Z_D}))
6137 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6139 case Intrinsic::aarch64_sme_famin_x2:
6141 Node->getValueType(0),
6142 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6143 AArch64::FAMIN_2Z2Z_D}))
6144 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6146 case Intrinsic::aarch64_sme_famin_x4:
6148 Node->getValueType(0),
6149 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6150 AArch64::FAMIN_4Z4Z_D}))
6151 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6153 case Intrinsic::aarch64_sve_smin_x2:
6155 Node->getValueType(0),
6156 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6157 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6158 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6160 case Intrinsic::aarch64_sve_umin_x2:
6162 Node->getValueType(0),
6163 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6164 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6165 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6167 case Intrinsic::aarch64_sve_fmin_x2:
6169 Node->getValueType(0),
6170 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6171 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6172 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6174 case Intrinsic::aarch64_sve_smin_x4:
6176 Node->getValueType(0),
6177 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6178 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6179 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6181 case Intrinsic::aarch64_sve_umin_x4:
6183 Node->getValueType(0),
6184 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6185 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6186 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6188 case Intrinsic::aarch64_sve_fmin_x4:
6190 Node->getValueType(0),
6191 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6192 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6193 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6195 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6197 Node->getValueType(0),
6198 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6199 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6200 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6202 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6204 Node->getValueType(0),
6205 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6206 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6207 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6209 case Intrinsic::aarch64_sve_fminnm_single_x2:
6211 Node->getValueType(0),
6212 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6213 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6214 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6216 case Intrinsic::aarch64_sve_fminnm_single_x4:
6218 Node->getValueType(0),
6219 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6220 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6221 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6223 case Intrinsic::aarch64_sve_fmaxnm_x2:
6225 Node->getValueType(0),
6226 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6227 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6228 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6230 case Intrinsic::aarch64_sve_fmaxnm_x4:
6232 Node->getValueType(0),
6233 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6234 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6235 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6237 case Intrinsic::aarch64_sve_fminnm_x2:
6239 Node->getValueType(0),
6240 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6241 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6244 case Intrinsic::aarch64_sve_fminnm_x4:
6246 Node->getValueType(0),
6247 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6248 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6251 case Intrinsic::aarch64_sve_fcvtzs_x2:
6252 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6254 case Intrinsic::aarch64_sve_scvtf_x2:
6255 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6257 case Intrinsic::aarch64_sve_fcvtzu_x2:
6258 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6260 case Intrinsic::aarch64_sve_ucvtf_x2:
6261 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6263 case Intrinsic::aarch64_sve_fcvtzs_x4:
6264 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6266 case Intrinsic::aarch64_sve_scvtf_x4:
6267 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6269 case Intrinsic::aarch64_sve_fcvtzu_x4:
6270 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6272 case Intrinsic::aarch64_sve_ucvtf_x4:
6273 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6275 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6276 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6278 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6279 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6281 case Intrinsic::aarch64_sve_sclamp_single_x2:
6283 Node->getValueType(0),
6284 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6285 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6286 SelectClamp(Node, 2,
Op);
6288 case Intrinsic::aarch64_sve_uclamp_single_x2:
6290 Node->getValueType(0),
6291 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6292 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6293 SelectClamp(Node, 2,
Op);
6295 case Intrinsic::aarch64_sve_fclamp_single_x2:
6297 Node->getValueType(0),
6298 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6299 AArch64::FCLAMP_VG2_2Z2Z_D}))
6300 SelectClamp(Node, 2,
Op);
6302 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6303 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6305 case Intrinsic::aarch64_sve_sclamp_single_x4:
6307 Node->getValueType(0),
6308 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6309 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6310 SelectClamp(Node, 4,
Op);
6312 case Intrinsic::aarch64_sve_uclamp_single_x4:
6314 Node->getValueType(0),
6315 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6316 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6317 SelectClamp(Node, 4,
Op);
6319 case Intrinsic::aarch64_sve_fclamp_single_x4:
6321 Node->getValueType(0),
6322 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6323 AArch64::FCLAMP_VG4_4Z4Z_D}))
6324 SelectClamp(Node, 4,
Op);
6326 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6327 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6329 case Intrinsic::aarch64_sve_add_single_x2:
6331 Node->getValueType(0),
6332 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6333 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6334 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6336 case Intrinsic::aarch64_sve_add_single_x4:
6338 Node->getValueType(0),
6339 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6340 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6341 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6343 case Intrinsic::aarch64_sve_zip_x2:
6345 Node->getValueType(0),
6346 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6347 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6348 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6350 case Intrinsic::aarch64_sve_zipq_x2:
6351 SelectUnaryMultiIntrinsic(Node, 2,
false,
6352 AArch64::ZIP_VG2_2ZZZ_Q);
6354 case Intrinsic::aarch64_sve_zip_x4:
6356 Node->getValueType(0),
6357 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6358 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6359 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6361 case Intrinsic::aarch64_sve_zipq_x4:
6362 SelectUnaryMultiIntrinsic(Node, 4,
true,
6363 AArch64::ZIP_VG4_4Z4Z_Q);
6365 case Intrinsic::aarch64_sve_uzp_x2:
6367 Node->getValueType(0),
6368 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6369 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6370 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6372 case Intrinsic::aarch64_sve_uzpq_x2:
6373 SelectUnaryMultiIntrinsic(Node, 2,
false,
6374 AArch64::UZP_VG2_2ZZZ_Q);
6376 case Intrinsic::aarch64_sve_uzp_x4:
6378 Node->getValueType(0),
6379 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6380 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6381 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6383 case Intrinsic::aarch64_sve_uzpq_x4:
6384 SelectUnaryMultiIntrinsic(Node, 4,
true,
6385 AArch64::UZP_VG4_4Z4Z_Q);
6387 case Intrinsic::aarch64_sve_sel_x2:
6389 Node->getValueType(0),
6390 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6391 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6392 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6394 case Intrinsic::aarch64_sve_sel_x4:
6396 Node->getValueType(0),
6397 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6398 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6399 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6401 case Intrinsic::aarch64_sve_frinta_x2:
6402 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6404 case Intrinsic::aarch64_sve_frinta_x4:
6405 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6407 case Intrinsic::aarch64_sve_frintm_x2:
6408 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6410 case Intrinsic::aarch64_sve_frintm_x4:
6411 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6413 case Intrinsic::aarch64_sve_frintn_x2:
6414 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6416 case Intrinsic::aarch64_sve_frintn_x4:
6417 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6419 case Intrinsic::aarch64_sve_frintp_x2:
6420 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6422 case Intrinsic::aarch64_sve_frintp_x4:
6423 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6425 case Intrinsic::aarch64_sve_sunpk_x2:
6427 Node->getValueType(0),
6428 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6429 AArch64::SUNPK_VG2_2ZZ_D}))
6430 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6432 case Intrinsic::aarch64_sve_uunpk_x2:
6434 Node->getValueType(0),
6435 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6436 AArch64::UUNPK_VG2_2ZZ_D}))
6437 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6439 case Intrinsic::aarch64_sve_sunpk_x4:
6441 Node->getValueType(0),
6442 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6443 AArch64::SUNPK_VG4_4Z2Z_D}))
6444 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6446 case Intrinsic::aarch64_sve_uunpk_x4:
6448 Node->getValueType(0),
6449 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6450 AArch64::UUNPK_VG4_4Z2Z_D}))
6451 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6453 case Intrinsic::aarch64_sve_pext_x2: {
6455 Node->getValueType(0),
6456 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6457 AArch64::PEXT_2PCI_D}))
6458 SelectPExtPair(Node,
Op);
6465 unsigned IntNo =
Node->getConstantOperandVal(1);
6466 if (
Node->getNumOperands() >= 3)
6467 VT =
Node->getOperand(2)->getValueType(0);
6471 case Intrinsic::aarch64_neon_st1x2: {
6472 if (VT == MVT::v8i8) {
6473 SelectStore(Node, 2, AArch64::ST1Twov8b);
6475 }
else if (VT == MVT::v16i8) {
6476 SelectStore(Node, 2, AArch64::ST1Twov16b);
6478 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6479 VT == MVT::v4bf16) {
6480 SelectStore(Node, 2, AArch64::ST1Twov4h);
6482 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6483 VT == MVT::v8bf16) {
6484 SelectStore(Node, 2, AArch64::ST1Twov8h);
6486 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6487 SelectStore(Node, 2, AArch64::ST1Twov2s);
6489 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6490 SelectStore(Node, 2, AArch64::ST1Twov4s);
6492 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6493 SelectStore(Node, 2, AArch64::ST1Twov2d);
6495 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6496 SelectStore(Node, 2, AArch64::ST1Twov1d);
6501 case Intrinsic::aarch64_neon_st1x3: {
6502 if (VT == MVT::v8i8) {
6503 SelectStore(Node, 3, AArch64::ST1Threev8b);
6505 }
else if (VT == MVT::v16i8) {
6506 SelectStore(Node, 3, AArch64::ST1Threev16b);
6508 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6509 VT == MVT::v4bf16) {
6510 SelectStore(Node, 3, AArch64::ST1Threev4h);
6512 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6513 VT == MVT::v8bf16) {
6514 SelectStore(Node, 3, AArch64::ST1Threev8h);
6516 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6517 SelectStore(Node, 3, AArch64::ST1Threev2s);
6519 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6520 SelectStore(Node, 3, AArch64::ST1Threev4s);
6522 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6523 SelectStore(Node, 3, AArch64::ST1Threev2d);
6525 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6526 SelectStore(Node, 3, AArch64::ST1Threev1d);
6531 case Intrinsic::aarch64_neon_st1x4: {
6532 if (VT == MVT::v8i8) {
6533 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6535 }
else if (VT == MVT::v16i8) {
6536 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6538 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6539 VT == MVT::v4bf16) {
6540 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6542 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6543 VT == MVT::v8bf16) {
6544 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6546 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6547 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6549 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6550 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6552 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6553 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6555 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6556 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6561 case Intrinsic::aarch64_neon_st2: {
6562 if (VT == MVT::v8i8) {
6563 SelectStore(Node, 2, AArch64::ST2Twov8b);
6565 }
else if (VT == MVT::v16i8) {
6566 SelectStore(Node, 2, AArch64::ST2Twov16b);
6568 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6569 VT == MVT::v4bf16) {
6570 SelectStore(Node, 2, AArch64::ST2Twov4h);
6572 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6573 VT == MVT::v8bf16) {
6574 SelectStore(Node, 2, AArch64::ST2Twov8h);
6576 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6577 SelectStore(Node, 2, AArch64::ST2Twov2s);
6579 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6580 SelectStore(Node, 2, AArch64::ST2Twov4s);
6582 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6583 SelectStore(Node, 2, AArch64::ST2Twov2d);
6585 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6586 SelectStore(Node, 2, AArch64::ST1Twov1d);
6591 case Intrinsic::aarch64_neon_st3: {
6592 if (VT == MVT::v8i8) {
6593 SelectStore(Node, 3, AArch64::ST3Threev8b);
6595 }
else if (VT == MVT::v16i8) {
6596 SelectStore(Node, 3, AArch64::ST3Threev16b);
6598 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6599 VT == MVT::v4bf16) {
6600 SelectStore(Node, 3, AArch64::ST3Threev4h);
6602 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6603 VT == MVT::v8bf16) {
6604 SelectStore(Node, 3, AArch64::ST3Threev8h);
6606 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6607 SelectStore(Node, 3, AArch64::ST3Threev2s);
6609 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6610 SelectStore(Node, 3, AArch64::ST3Threev4s);
6612 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6613 SelectStore(Node, 3, AArch64::ST3Threev2d);
6615 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6616 SelectStore(Node, 3, AArch64::ST1Threev1d);
6621 case Intrinsic::aarch64_neon_st4: {
6622 if (VT == MVT::v8i8) {
6623 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6625 }
else if (VT == MVT::v16i8) {
6626 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6628 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6629 VT == MVT::v4bf16) {
6630 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6632 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6633 VT == MVT::v8bf16) {
6634 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6636 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6637 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6639 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6640 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6642 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6643 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6645 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6646 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6651 case Intrinsic::aarch64_neon_st2lane: {
6652 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6653 SelectStoreLane(Node, 2, AArch64::ST2i8);
6655 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6656 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6657 SelectStoreLane(Node, 2, AArch64::ST2i16);
6659 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6661 SelectStoreLane(Node, 2, AArch64::ST2i32);
6663 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6665 SelectStoreLane(Node, 2, AArch64::ST2i64);
6670 case Intrinsic::aarch64_neon_st3lane: {
6671 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6672 SelectStoreLane(Node, 3, AArch64::ST3i8);
6674 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6675 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6676 SelectStoreLane(Node, 3, AArch64::ST3i16);
6678 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6680 SelectStoreLane(Node, 3, AArch64::ST3i32);
6682 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6684 SelectStoreLane(Node, 3, AArch64::ST3i64);
6689 case Intrinsic::aarch64_neon_st4lane: {
6690 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6691 SelectStoreLane(Node, 4, AArch64::ST4i8);
6693 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6694 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6695 SelectStoreLane(Node, 4, AArch64::ST4i16);
6697 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6699 SelectStoreLane(Node, 4, AArch64::ST4i32);
6701 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6703 SelectStoreLane(Node, 4, AArch64::ST4i64);
6708 case Intrinsic::aarch64_sve_st2q: {
6709 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6712 case Intrinsic::aarch64_sve_st3q: {
6713 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6716 case Intrinsic::aarch64_sve_st4q: {
6717 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6720 case Intrinsic::aarch64_sve_st2: {
6721 if (VT == MVT::nxv16i8) {
6722 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6724 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6725 VT == MVT::nxv8bf16) {
6726 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6728 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6729 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6731 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6732 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6737 case Intrinsic::aarch64_sve_st3: {
6738 if (VT == MVT::nxv16i8) {
6739 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6741 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6742 VT == MVT::nxv8bf16) {
6743 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6745 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6746 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6748 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6749 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6754 case Intrinsic::aarch64_sve_st4: {
6755 if (VT == MVT::nxv16i8) {
6756 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6758 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6759 VT == MVT::nxv8bf16) {
6760 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6762 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6763 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6765 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6766 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6774 case AArch64ISD::LD2post: {
6775 if (VT == MVT::v8i8) {
6776 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6778 }
else if (VT == MVT::v16i8) {
6779 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6781 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6782 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6784 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6785 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6787 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6788 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6790 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6791 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6793 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6794 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6796 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6797 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6802 case AArch64ISD::LD3post: {
6803 if (VT == MVT::v8i8) {
6804 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6806 }
else if (VT == MVT::v16i8) {
6807 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6809 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6810 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6812 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6813 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6815 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6816 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6818 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6819 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6821 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6822 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6824 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6825 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6830 case AArch64ISD::LD4post: {
6831 if (VT == MVT::v8i8) {
6832 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6834 }
else if (VT == MVT::v16i8) {
6835 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6837 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6838 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6840 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6841 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6843 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6844 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6846 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6847 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6849 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6850 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6852 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6853 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6858 case AArch64ISD::LD1x2post: {
6859 if (VT == MVT::v8i8) {
6860 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6862 }
else if (VT == MVT::v16i8) {
6863 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6865 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6866 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6868 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6869 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6871 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6872 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6874 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6875 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6877 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6878 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6880 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6881 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6886 case AArch64ISD::LD1x3post: {
6887 if (VT == MVT::v8i8) {
6888 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6890 }
else if (VT == MVT::v16i8) {
6891 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6893 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6894 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6896 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6897 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6899 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6900 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6902 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6903 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6905 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6906 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6908 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6909 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6914 case AArch64ISD::LD1x4post: {
6915 if (VT == MVT::v8i8) {
6916 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6918 }
else if (VT == MVT::v16i8) {
6919 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6921 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6922 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6924 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6925 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6927 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6928 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6930 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6931 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6933 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6934 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6936 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6937 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6942 case AArch64ISD::LD1DUPpost: {
6943 if (VT == MVT::v8i8) {
6944 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6946 }
else if (VT == MVT::v16i8) {
6947 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6949 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6950 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6952 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6953 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6955 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6956 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6958 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6959 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
6961 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6962 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
6964 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6965 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
6970 case AArch64ISD::LD2DUPpost: {
6971 if (VT == MVT::v8i8) {
6972 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
6974 }
else if (VT == MVT::v16i8) {
6975 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
6977 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6978 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
6980 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6981 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
6983 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6984 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
6986 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6987 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
6989 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6990 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
6992 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6993 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
6998 case AArch64ISD::LD3DUPpost: {
6999 if (VT == MVT::v8i8) {
7000 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7002 }
else if (VT == MVT::v16i8) {
7003 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7005 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7006 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7008 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7009 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7011 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7012 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7014 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7015 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7017 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7018 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7020 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7021 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7026 case AArch64ISD::LD4DUPpost: {
7027 if (VT == MVT::v8i8) {
7028 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7030 }
else if (VT == MVT::v16i8) {
7031 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7033 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7034 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7036 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7037 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7039 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7040 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7042 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7043 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7045 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7046 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7048 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7049 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7054 case AArch64ISD::LD1LANEpost: {
7055 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7056 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7058 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7059 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7060 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7062 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7064 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7066 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7068 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7073 case AArch64ISD::LD2LANEpost: {
7074 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7075 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7077 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7078 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7079 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7081 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7083 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7085 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7087 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7092 case AArch64ISD::LD3LANEpost: {
7093 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7094 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7096 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7097 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7098 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7100 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7102 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7104 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7106 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7111 case AArch64ISD::LD4LANEpost: {
7112 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7113 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7115 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7116 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7117 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7119 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7121 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7123 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7125 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7130 case AArch64ISD::ST2post: {
7131 VT =
Node->getOperand(1).getValueType();
7132 if (VT == MVT::v8i8) {
7133 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7135 }
else if (VT == MVT::v16i8) {
7136 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7138 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7139 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7141 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7142 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7144 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7145 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7147 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7148 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7150 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7151 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7153 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7154 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7159 case AArch64ISD::ST3post: {
7160 VT =
Node->getOperand(1).getValueType();
7161 if (VT == MVT::v8i8) {
7162 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7164 }
else if (VT == MVT::v16i8) {
7165 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7167 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7168 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7170 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7171 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7173 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7174 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7176 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7177 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7179 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7180 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7182 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7183 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7188 case AArch64ISD::ST4post: {
7189 VT =
Node->getOperand(1).getValueType();
7190 if (VT == MVT::v8i8) {
7191 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7193 }
else if (VT == MVT::v16i8) {
7194 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7196 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7197 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7199 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7200 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7202 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7203 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7205 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7206 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7208 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7209 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7211 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7212 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7217 case AArch64ISD::ST1x2post: {
7218 VT =
Node->getOperand(1).getValueType();
7219 if (VT == MVT::v8i8) {
7220 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7222 }
else if (VT == MVT::v16i8) {
7223 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7225 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7226 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7228 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7229 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7231 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7232 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7234 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7235 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7237 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7238 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7240 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7241 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7246 case AArch64ISD::ST1x3post: {
7247 VT =
Node->getOperand(1).getValueType();
7248 if (VT == MVT::v8i8) {
7249 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7251 }
else if (VT == MVT::v16i8) {
7252 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7254 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7255 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7257 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7258 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7260 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7261 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7263 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7264 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7266 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7267 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7269 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7270 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7275 case AArch64ISD::ST1x4post: {
7276 VT =
Node->getOperand(1).getValueType();
7277 if (VT == MVT::v8i8) {
7278 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7280 }
else if (VT == MVT::v16i8) {
7281 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7283 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7284 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7286 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7287 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7289 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7290 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7292 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7293 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7295 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7296 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7298 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7299 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7304 case AArch64ISD::ST2LANEpost: {
7305 VT =
Node->getOperand(1).getValueType();
7306 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7307 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7309 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7310 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7311 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7313 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7315 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7317 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7319 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7324 case AArch64ISD::ST3LANEpost: {
7325 VT =
Node->getOperand(1).getValueType();
7326 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7327 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7329 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7330 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7331 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7333 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7335 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7337 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7339 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7344 case AArch64ISD::ST4LANEpost: {
7345 VT =
Node->getOperand(1).getValueType();
7346 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7347 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7349 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7350 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7351 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7353 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7355 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7357 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7359 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7374 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7386 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7390 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7391 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7406 return MemIntr->getMemoryVT();
7413 DataVT = Load->getValueType(0);
7415 DataVT = Load->getValueType(0);
7417 DataVT = Store->getValue().getValueType();
7419 DataVT = Store->getValue().getValueType();
7426 const unsigned Opcode = Root->
getOpcode();
7430 case AArch64ISD::LD1_MERGE_ZERO:
7431 case AArch64ISD::LD1S_MERGE_ZERO:
7432 case AArch64ISD::LDNF1_MERGE_ZERO:
7433 case AArch64ISD::LDNF1S_MERGE_ZERO:
7435 case AArch64ISD::ST1_PRED:
7447 case Intrinsic::aarch64_sme_ldr:
7448 case Intrinsic::aarch64_sme_str:
7449 return MVT::nxv16i8;
7450 case Intrinsic::aarch64_sve_prf:
7455 case Intrinsic::aarch64_sve_ld2_sret:
7456 case Intrinsic::aarch64_sve_ld2q_sret:
7459 case Intrinsic::aarch64_sve_st2q:
7462 case Intrinsic::aarch64_sve_ld3_sret:
7463 case Intrinsic::aarch64_sve_ld3q_sret:
7466 case Intrinsic::aarch64_sve_st3q:
7469 case Intrinsic::aarch64_sve_ld4_sret:
7470 case Intrinsic::aarch64_sve_ld4q_sret:
7473 case Intrinsic::aarch64_sve_st4q:
7476 case Intrinsic::aarch64_sve_ld1udq:
7477 case Intrinsic::aarch64_sve_st1dq:
7478 return EVT(MVT::nxv1i64);
7479 case Intrinsic::aarch64_sve_ld1uwq:
7480 case Intrinsic::aarch64_sve_st1wq:
7481 return EVT(MVT::nxv1i32);
7488template <
int64_t Min,
int64_t Max>
7489bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7493 const DataLayout &
DL = CurDAG->getDataLayout();
7494 const MachineFrameInfo &MFI = MF->getFrameInfo();
7502 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7516 int64_t MulImm = std::numeric_limits<int64_t>::max();
7517 if (VScale.
getOpcode() == ISD::VSCALE) {
7520 int64_t ByteOffset =
C->getSExtValue();
7521 const auto KnownVScale =
7524 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7527 MulImm = ByteOffset / KnownVScale;
7534 if ((MulImm % MemWidthBytes) != 0)
7537 int64_t
Offset = MulImm / MemWidthBytes;
7541 Base =
N.getOperand(0);
7550 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7556bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7575 int64_t ImmOff =
C->getSExtValue();
7576 unsigned Size = 1 << Scale;
7585 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7587 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7598 if (
C->getZExtValue() == Scale) {
7607bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7608 const AArch64TargetLowering *TLI =
7609 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7614bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7615 EVT VT =
N.getValueType();
7619bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7624 int64_t ImmOff =
C->getSExtValue();
7625 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7626 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7631 if (
SDValue C = MatchConstantOffset(
N)) {
7632 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7638 if (CurDAG->isBaseWithConstantOffset(
N)) {
7639 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7640 Base =
N.getOperand(0);
7648 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7652bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7672 uint64_t LowerBound = 0, UpperBound = 64;
7690 if (CN->getAPIntValue().uge(LowerBound) &&
7691 CN->getAPIntValue().ult(UpperBound)) {
7693 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.