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);
517 template <
bool MatchCBB>
527 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
531char AArch64DAGToDAGISelLegacy::ID = 0;
539 Imm =
C->getZExtValue();
556 return N->getOpcode() ==
Opc &&
567 return Imm == ImmExpected;
571bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
573 std::vector<SDValue> &OutOps) {
574 switch(ConstraintID) {
577 case InlineAsm::ConstraintCode::m:
578 case InlineAsm::ConstraintCode::o:
579 case InlineAsm::ConstraintCode::Q:
583 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
585 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
587 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
588 dl,
Op.getValueType(),
590 OutOps.push_back(NewOp);
609 uint64_t Immed =
N.getNode()->getAsZExtVal();
612 if (Immed >> 12 == 0) {
614 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
622 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
623 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
640 uint64_t Immed =
N.getNode()->getAsZExtVal();
648 if (
N.getValueType() == MVT::i32)
649 Immed = ~((uint32_t)Immed) + 1;
651 Immed = ~Immed + 1ULL;
652 if (Immed & 0xFFFFFFFFFF000000ULL)
655 Immed &= 0xFFFFFFULL;
656 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
663 switch (
N.getOpcode()) {
689 unsigned ShiftVal = CSD->getZExtValue();
707bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
710 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
715 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
739 EVT VT =
N.getValueType();
740 if (VT != MVT::i32 && VT != MVT::i64)
743 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
749 unsigned LHSOpcode =
LHS->getOpcode();
763 unsigned LowZBits, MaskLen;
767 unsigned BitWidth =
N.getValueSizeInBits();
774 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
777 NewShiftC = LowZBits - ShiftAmtC;
778 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
784 NewShiftC = LowZBits + ShiftAmtC;
797 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
799 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
803 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
805 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
806 NewShiftAmt, BitWidthMinus1),
809 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
823 SrcVT =
N.getOperand(0).getValueType();
825 if (!IsLoadStore && SrcVT == MVT::i8)
827 else if (!IsLoadStore && SrcVT == MVT::i16)
829 else if (SrcVT == MVT::i32)
831 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
836 EVT SrcVT =
N.getOperand(0).getValueType();
837 if (!IsLoadStore && SrcVT == MVT::i8)
839 else if (!IsLoadStore && SrcVT == MVT::i16)
841 else if (SrcVT == MVT::i32)
843 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
871bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
874 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
879 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
880 V.getConstantOperandVal(1) <= 4 &&
893bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
895 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
905 unsigned BitSize =
N.getValueSizeInBits();
906 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
909 Reg =
N.getOperand(0);
910 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
911 return isWorthFoldingALU(
N,
true);
922 if (
N.getValueType() == MVT::i32)
930template<
signed Low,
signed High,
signed Scale>
936 if ((MulImm % std::abs(Scale)) == 0) {
937 int64_t RDVLImm = MulImm / Scale;
938 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
939 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
948template <
signed Low,
signed High>
949bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
954 if (MulImm >=
Low && MulImm <=
High) {
955 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
966 unsigned ShiftVal = 0;
981 Reg =
N.getOperand(0).getOperand(0);
987 Reg =
N.getOperand(0);
992 unsigned Opc =
N.getOpcode();
1010 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1012 return isWorthFoldingALU(
N);
1019 unsigned ShiftVal = 0;
1033 Reg =
N.getOperand(0);
1034 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1036 return isWorthFoldingALU(
N);
1045 for (
auto *
User :
N->users()) {
1046 if (
User->getOpcode() != ISD::LOAD &&
User->getOpcode() != ISD::STORE &&
1047 User->getOpcode() != ISD::ATOMIC_LOAD &&
1048 User->getOpcode() != ISD::ATOMIC_STORE)
1072bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1073 unsigned BW,
unsigned Size,
1077 const DataLayout &
DL = CurDAG->getDataLayout();
1078 const TargetLowering *TLI = getTargetLowering();
1082 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1088 if (CurDAG->isBaseWithConstantOffset(
N)) {
1091 int64_t RHSC =
RHS->getSExtValue();
1093 int64_t
Range = 0x1LL << (BW - 1);
1095 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1096 RHSC < (
Range << Scale)) {
1097 Base =
N.getOperand(0);
1102 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1107 uint64_t RHSC =
RHS->getZExtValue();
1109 uint64_t
Range = 0x1ULL << BW;
1111 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1112 Base =
N.getOperand(0);
1117 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1128 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1135bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1138 const DataLayout &
DL = CurDAG->getDataLayout();
1139 const TargetLowering *TLI = getTargetLowering();
1143 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1148 GlobalAddressSDNode *GAN =
1150 Base =
N.getOperand(0);
1160 if (CurDAG->isBaseWithConstantOffset(
N)) {
1162 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1165 Base =
N.getOperand(0);
1170 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1178 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1186 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1195bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1198 if (!CurDAG->isBaseWithConstantOffset(
N))
1201 int64_t RHSC =
RHS->getSExtValue();
1202 if (RHSC >= -256 && RHSC < 256) {
1203 Base =
N.getOperand(0);
1206 const TargetLowering *TLI = getTargetLowering();
1207 Base = CurDAG->getTargetFrameIndex(
1210 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1220 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1227bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1247 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1253 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1256 return isWorthFoldingAddr(
N,
Size);
1259bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1277 const SDNode *
Node =
N.getNode();
1278 for (SDNode *UI :
Node->users()) {
1284 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1287 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1290 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1295 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1298 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1303 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1307 if (IsExtendedRegisterWorthFolding &&
1314 if (isWorthFoldingAddr(
LHS,
Size))
1319 if (IsExtendedRegisterWorthFolding &&
1326 if (isWorthFoldingAddr(
RHS,
Size))
1338 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1341 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1343 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1344 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1348bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1361 const SDNode *
Node =
N.getNode();
1362 for (SDNode *UI :
Node->users()) {
1379 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1389 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1396 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1399 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1402 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1407 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1410 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1417 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1418 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1424 static const unsigned RegClassIDs[] = {
1425 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1426 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1427 AArch64::dsub2, AArch64::dsub3};
1433 static const unsigned RegClassIDs[] = {
1434 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1435 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1436 AArch64::qsub2, AArch64::qsub3};
1442 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1443 AArch64::ZPR3RegClassID,
1444 AArch64::ZPR4RegClassID};
1445 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1446 AArch64::zsub2, AArch64::zsub3};
1456 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1457 AArch64::ZPR4Mul4RegClassID};
1458 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1459 AArch64::zsub2, AArch64::zsub3};
1464 const unsigned RegClassIDs[],
1465 const unsigned SubRegs[]) {
1468 if (Regs.
size() == 1)
1479 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1482 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1483 Ops.push_back(Regs[i]);
1484 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1488 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1492void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1495 EVT VT =
N->getValueType(0);
1497 unsigned ExtOff = isExt;
1500 unsigned Vec0Off = ExtOff + 1;
1506 Ops.push_back(
N->getOperand(1));
1507 Ops.push_back(RegSeq);
1508 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1509 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1512static std::tuple<SDValue, SDValue>
1533 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1538 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1540 return std::make_tuple(
1545void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1550 SDValue AUTDisc =
N->getOperand(3);
1553 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1555 SDValue AUTAddrDisc, AUTConstDisc;
1556 std::tie(AUTConstDisc, AUTAddrDisc) =
1560 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1562 if (
N->getNumOperands() > 4)
1563 Ops.push_back(
N->getOperand(4));
1566 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1567 ReplaceNode(
N, AUT);
1569 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1570 AArch64::X16, Val,
SDValue());
1573 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1574 ReplaceNode(
N, AUT);
1578void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1590 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1591 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1593 SDValue AUTAddrDisc, AUTConstDisc;
1594 std::tie(AUTConstDisc, AUTAddrDisc) =
1597 SDValue PACAddrDisc, PACConstDisc;
1598 std::tie(PACConstDisc, PACAddrDisc) =
1601 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1602 AArch64::X16, Val,
SDValue());
1604 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1605 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1607 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1608 ReplaceNode(
N, AUTPAC);
1611bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1613 if (
LD->isUnindexed())
1615 EVT VT =
LD->getMemoryVT();
1616 EVT DstVT =
N->getValueType(0);
1620 int OffsetVal = (int)
OffsetOp->getZExtValue();
1625 unsigned Opcode = 0;
1628 bool InsertTo64 =
false;
1630 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1631 else if (VT == MVT::i32) {
1633 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1635 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1637 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1643 }
else if (VT == MVT::i16) {
1645 if (DstVT == MVT::i64)
1646 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1648 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1650 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1651 InsertTo64 = DstVT == MVT::i64;
1656 }
else if (VT == MVT::i8) {
1658 if (DstVT == MVT::i64)
1659 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1661 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1663 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1664 InsertTo64 = DstVT == MVT::i64;
1669 }
else if (VT == MVT::f16) {
1670 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1671 }
else if (VT == MVT::bf16) {
1672 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1673 }
else if (VT == MVT::f32) {
1674 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1675 }
else if (VT == MVT::f64 ||
1677 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1679 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1681 if (IsPre || OffsetVal != 8)
1685 Opcode = AArch64::LD1Onev8b_POST;
1688 Opcode = AArch64::LD1Onev4h_POST;
1691 Opcode = AArch64::LD1Onev2s_POST;
1694 Opcode = AArch64::LD1Onev1d_POST;
1700 if (IsPre || OffsetVal != 16)
1704 Opcode = AArch64::LD1Onev16b_POST;
1707 Opcode = AArch64::LD1Onev8h_POST;
1710 Opcode = AArch64::LD1Onev4s_POST;
1713 Opcode = AArch64::LD1Onev2d_POST;
1725 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1726 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1728 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1738 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1740 SDValue(CurDAG->getMachineNode(
1741 AArch64::SUBREG_TO_REG, dl, MVT::i64,
1742 CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1747 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1750 CurDAG->RemoveDeadNode(
N);
1754void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1755 unsigned SubRegIdx) {
1757 EVT VT =
N->getValueType(0);
1763 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1765 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1767 for (
unsigned i = 0; i < NumVecs; ++i)
1769 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1776 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1780 CurDAG->RemoveDeadNode(
N);
1783void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1784 unsigned Opc,
unsigned SubRegIdx) {
1786 EVT VT =
N->getValueType(0);
1793 const EVT ResTys[] = {MVT::i64,
1794 MVT::Untyped, MVT::Other};
1796 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1804 ReplaceUses(
SDValue(
N, 0), SuperReg);
1806 for (
unsigned i = 0; i < NumVecs; ++i)
1808 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1812 CurDAG->RemoveDeadNode(
N);
1818std::tuple<unsigned, SDValue, SDValue>
1819AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1825 SDValue NewOffset = OldOffset;
1827 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1828 N, OldBase, NewBase, NewOffset);
1832 const bool IsRegReg =
1833 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1836 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
1849template <SelectTypeKind Kind>
1861 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
1866 if (EltVT != MVT::i1)
1870 if (EltVT == MVT::bf16)
1872 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
1902void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
1905 if (
Imm->getZExtValue() > 1)
1909 EVT VT =
N->getValueType(0);
1911 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1914 for (
unsigned I = 0;
I < 2; ++
I)
1915 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1916 AArch64::psub0 +
I,
DL, VT, SuperReg));
1918 CurDAG->RemoveDeadNode(
N);
1921void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
1923 EVT VT =
N->getValueType(0);
1927 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1930 for (
unsigned I = 0;
I < 2; ++
I)
1931 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1932 AArch64::psub0 +
I,
DL, VT, SuperReg));
1934 CurDAG->RemoveDeadNode(
N);
1937void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
1939 EVT VT =
N->getValueType(0);
1943 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
1945 for (
unsigned i = 0; i < NumVecs; ++i)
1946 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1947 AArch64::zsub0 + i,
DL, VT, SuperReg));
1949 CurDAG->RemoveDeadNode(
N);
1952void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
1955 EVT VT =
N->getValueType(0);
1957 Ops.push_back(
N->getOperand(0));
1960 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
1963 for (
unsigned i = 0; i < NumVecs; ++i)
1964 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1965 AArch64::zsub0 + i,
DL, VT, SuperReg));
1968 unsigned ChainIdx = NumVecs;
1970 CurDAG->RemoveDeadNode(
N);
1973void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
1978 assert(Opcode != 0 &&
"Unexpected opcode");
1981 EVT VT =
N->getValueType(0);
1982 unsigned FirstVecIdx = HasPred ? 2 : 1;
1984 auto GetMultiVecOperand = [=](
unsigned StartIdx) {
1986 return createZMulTuple(Regs);
1989 SDValue Zdn = GetMultiVecOperand(FirstVecIdx);
1993 Zm = GetMultiVecOperand(NumVecs + FirstVecIdx);
1999 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
2000 N->getOperand(1), Zdn, Zm);
2002 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped, Zdn, Zm);
2004 for (
unsigned i = 0; i < NumVecs; ++i)
2005 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2006 AArch64::zsub0 + i,
DL, VT, SuperReg));
2008 CurDAG->RemoveDeadNode(
N);
2011void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2012 unsigned Scale,
unsigned Opc_ri,
2013 unsigned Opc_rr,
bool IsIntr) {
2014 assert(Scale < 5 &&
"Invalid scaling value.");
2016 EVT VT =
N->getValueType(0);
2023 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2024 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2030 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2032 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2034 for (
unsigned i = 0; i < NumVecs; ++i)
2035 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2036 AArch64::zsub0 + i,
DL, VT, SuperReg));
2039 unsigned ChainIdx = NumVecs;
2041 CurDAG->RemoveDeadNode(
N);
2044void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2049 assert(Scale < 4 &&
"Invalid scaling value.");
2051 EVT VT =
N->getValueType(0);
2059 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2065 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2067 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2069 for (
unsigned i = 0; i < NumVecs; ++i)
2070 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2071 AArch64::zsub0 + i,
DL, VT, SuperReg));
2074 unsigned ChainIdx = NumVecs;
2076 CurDAG->RemoveDeadNode(
N);
2079void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2081 if (
N->getValueType(0) != MVT::nxv4f32)
2083 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2086void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2087 unsigned NumOutVecs,
2091 if (
Imm->getZExtValue() > MaxImm)
2095 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2101 EVT VT =
Node->getValueType(0);
2104 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2107 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2108 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2109 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2112 unsigned ChainIdx = NumOutVecs;
2114 CurDAG->RemoveDeadNode(Node);
2117void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2118 unsigned NumOutVecs,
2121 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2126 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2130 EVT VT =
Node->getValueType(0);
2133 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2136 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2137 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2138 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2141 unsigned ChainIdx = NumOutVecs;
2143 CurDAG->RemoveDeadNode(Node);
2146void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2149 EVT VT =
N->getValueType(0);
2152 SDValue Zd = createZMulTuple(Regs);
2153 SDValue Zn =
N->getOperand(1 + NumVecs);
2160 for (
unsigned i = 0; i < NumVecs; ++i)
2161 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2162 AArch64::zsub0 + i,
DL, VT, SuperReg));
2164 CurDAG->RemoveDeadNode(
N);
2194template <
unsigned MaxIdx,
unsigned Scale>
2195void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2196 unsigned BaseReg,
unsigned Op) {
2197 unsigned TileNum = 0;
2198 if (BaseReg != AArch64::ZA)
2199 TileNum =
N->getConstantOperandVal(2);
2205 if (BaseReg == AArch64::ZA)
2210 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2216 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2218 EVT VT =
N->getValueType(0);
2219 for (
unsigned I = 0;
I < NumVecs; ++
I)
2221 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2224 unsigned ChainIdx = NumVecs;
2226 CurDAG->RemoveDeadNode(
N);
2229void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2230 unsigned Op,
unsigned MaxIdx,
2231 unsigned Scale,
unsigned BaseReg) {
2236 if (BaseReg != AArch64::ZA)
2240 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2247 if (BaseReg != AArch64::ZA )
2248 Ops.push_back(
N->getOperand(2));
2251 Ops.push_back(
N->getOperand(0));
2252 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2254 EVT VT =
N->getValueType(0);
2255 for (
unsigned I = 0;
I < NumVecs; ++
I)
2257 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2261 unsigned ChainIdx = NumVecs;
2263 CurDAG->RemoveDeadNode(
N);
2266void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2267 unsigned NumOutVecs,
2271 EVT VT =
N->getValueType(0);
2272 unsigned NumInVecs =
N->getNumOperands() - 1;
2276 assert((NumInVecs == 2 || NumInVecs == 4) &&
2277 "Don't know how to handle multi-register input!");
2279 Ops.push_back(createZMulTuple(Regs));
2282 for (
unsigned I = 0;
I < NumInVecs;
I++)
2283 Ops.push_back(
N->getOperand(1 +
I));
2286 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2289 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2290 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2291 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2292 CurDAG->RemoveDeadNode(
N);
2295void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2298 EVT VT =
N->getOperand(2)->getValueType(0);
2306 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2315void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2316 unsigned Scale,
unsigned Opc_rr,
2322 SDValue RegSeq = createZTuple(Regs);
2328 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2329 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2335 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2343 const DataLayout &
DL = CurDAG->getDataLayout();
2344 const TargetLowering *TLI = getTargetLowering();
2348 int FI = FINode->getIndex();
2350 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2357void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2360 EVT VT =
N->getOperand(2)->getValueType(0);
2361 const EVT ResTys[] = {MVT::i64,
2373 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2413void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2416 EVT VT =
N->getValueType(0);
2428 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2430 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2432 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2434 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2438 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2439 AArch64::qsub2, AArch64::qsub3 };
2440 for (
unsigned i = 0; i < NumVecs; ++i) {
2441 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2448 CurDAG->RemoveDeadNode(
N);
2451void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2454 EVT VT =
N->getValueType(0);
2466 const EVT ResTys[] = {MVT::i64,
2469 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2472 CurDAG->getTargetConstant(LaneNo, dl,
2477 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2489 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2490 AArch64::qsub2, AArch64::qsub3 };
2491 for (
unsigned i = 0; i < NumVecs; ++i) {
2492 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2502 CurDAG->RemoveDeadNode(
N);
2505void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2508 EVT VT =
N->getOperand(2)->getValueType(0);
2520 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2522 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2524 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2533void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2536 EVT VT =
N->getOperand(2)->getValueType(0);
2548 const EVT ResTys[] = {MVT::i64,
2551 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2553 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2557 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2568 unsigned &LSB,
unsigned &MSB,
2569 unsigned NumberOfIgnoredLowBits,
2570 bool BiggerPattern) {
2572 "N must be a AND operation to call this function");
2574 EVT VT =
N->getValueType(0);
2579 assert((VT == MVT::i32 || VT == MVT::i64) &&
2580 "Type checking must have been done before calling this function");
2594 const SDNode *Op0 =
N->getOperand(0).getNode();
2601 if (AndImm & (AndImm + 1))
2604 bool ClampMSB =
false;
2624 ClampMSB = (VT == MVT::i32);
2625 }
else if (BiggerPattern) {
2631 Opd0 =
N->getOperand(0);
2637 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2640 <<
": Found large shift immediate, this should not happen\n"));
2654 MSB = MSB > 31 ? 31 : MSB;
2656 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2661 SDValue &Opd0,
unsigned &Immr,
2665 EVT VT =
N->getValueType(0);
2667 assert((VT == MVT::i32 || VT == MVT::i64) &&
2668 "Type checking must have been done before calling this function");
2672 Op =
Op->getOperand(0);
2673 VT =
Op->getValueType(0);
2682 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2686 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2687 Opd0 =
Op.getOperand(0);
2689 Imms = ShiftImm + Width - 1;
2717 Opd0 =
N->getOperand(0).getOperand(0);
2727 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2734 unsigned &Immr,
unsigned &Imms,
2735 bool BiggerPattern) {
2737 "N must be a SHR/SRA operation to call this function");
2739 EVT VT =
N->getValueType(0);
2744 assert((VT == MVT::i32 || VT == MVT::i64) &&
2745 "Type checking must have been done before calling this function");
2755 Opd0 =
N->getOperand(0).getOperand(0);
2756 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2762 Opd0 =
N->getOperand(0).getOperand(0);
2765 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2766 }
else if (BiggerPattern) {
2770 Opd0 =
N->getOperand(0);
2779 <<
": Found large shift immediate, this should not happen\n"));
2788 "bad amount in shift node!");
2789 int immr = SrlImm - ShlImm;
2794 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2796 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2800bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2803 EVT VT =
N->getValueType(0);
2804 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2805 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2816 unsigned Immr = ShiftImm;
2818 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2819 CurDAG->getTargetConstant(Imms, dl, VT)};
2820 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2825 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2826 unsigned NumberOfIgnoredLowBits = 0,
2827 bool BiggerPattern =
false) {
2828 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2831 switch (
N->getOpcode()) {
2833 if (!
N->isMachineOpcode())
2838 NumberOfIgnoredLowBits, BiggerPattern);
2847 unsigned NOpc =
N->getMachineOpcode();
2851 case AArch64::SBFMWri:
2852 case AArch64::UBFMWri:
2853 case AArch64::SBFMXri:
2854 case AArch64::UBFMXri:
2856 Opd0 =
N->getOperand(0);
2857 Immr =
N->getConstantOperandVal(1);
2858 Imms =
N->getConstantOperandVal(2);
2865bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2866 unsigned Opc, Immr, Imms;
2871 EVT VT =
N->getValueType(0);
2876 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2877 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2878 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2880 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2881 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2887 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2888 CurDAG->getTargetConstant(Imms, dl, VT)};
2889 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2898 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2899 assert((VT == MVT::i32 || VT == MVT::i64) &&
2900 "i32 or i64 mask type expected!");
2904 APInt SignificantDstMask =
2908 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2909 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2942 APInt OpUsefulBits(UsefulBits);
2946 OpUsefulBits <<= MSB - Imm + 1;
2951 OpUsefulBits <<= Imm;
2953 OpUsefulBits <<= MSB + 1;
2956 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2962 UsefulBits &= OpUsefulBits;
2979 APInt Mask(UsefulBits);
2980 Mask.clearAllBits();
2988 Mask.lshrInPlace(ShiftAmt);
2994 Mask.lshrInPlace(ShiftAmt);
3010 APInt OpUsefulBits(UsefulBits);
3024 OpUsefulBits <<= Width;
3027 if (
Op.getOperand(1) == Orig) {
3029 Mask = ResultUsefulBits & OpUsefulBits;
3033 if (
Op.getOperand(0) == Orig)
3035 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3041 OpUsefulBits <<= Width;
3043 OpUsefulBits <<= LSB;
3045 if (
Op.getOperand(1) == Orig) {
3047 Mask = ResultUsefulBits & OpUsefulBits;
3048 Mask.lshrInPlace(LSB);
3051 if (
Op.getOperand(0) == Orig)
3052 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3069 case AArch64::ANDSWri:
3070 case AArch64::ANDSXri:
3071 case AArch64::ANDWri:
3072 case AArch64::ANDXri:
3076 case AArch64::UBFMWri:
3077 case AArch64::UBFMXri:
3080 case AArch64::ORRWrs:
3081 case AArch64::ORRXrs:
3086 case AArch64::BFMWri:
3087 case AArch64::BFMXri:
3090 case AArch64::STRBBui:
3091 case AArch64::STURBBi:
3097 case AArch64::STRHHui:
3098 case AArch64::STURHHi:
3111 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3113 UsefulBits =
APInt(Bitwidth, 0);
3122 UsersUsefulBits |= UsefulBitsForUse;
3127 UsefulBits &= UsersUsefulBits;
3137 EVT VT =
Op.getValueType();
3140 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3143 if (ShlAmount > 0) {
3146 UBFMOpc, dl, VT,
Op,
3151 assert(ShlAmount < 0 &&
"expected right shift");
3152 int ShrAmount = -ShlAmount;
3164 const uint64_t NonZeroBits,
3171 const uint64_t NonZeroBits,
3178 bool BiggerPattern,
SDValue &Src,
3179 int &DstLSB,
int &Width) {
3180 EVT VT =
Op.getValueType();
3189 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3193 switch (
Op.getOpcode()) {
3198 NonZeroBits, Src, DstLSB, Width);
3201 NonZeroBits, Src, DstLSB, Width);
3214 EVT VT =
Op.getValueType();
3215 assert((VT == MVT::i32 || VT == MVT::i64) &&
3216 "Caller guarantees VT is one of i32 or i64");
3229 assert((~AndImm & NonZeroBits) == 0 &&
3230 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3259 if (!BiggerPattern && !AndOp0.
hasOneUse())
3278 <<
"Found large Width in bit-field-positioning -- this indicates no "
3279 "proper combining / constant folding was performed\n");
3288 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3303 "Op.getNode() should be a SHL node to call this function");
3305 "Op.getNode() should shift ShlImm to call this function");
3312 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3336 EVT VT =
Op.getValueType();
3337 assert((VT == MVT::i32 || VT == MVT::i64) &&
3338 "Caller guarantees that type is i32 or i64");
3345 if (!BiggerPattern && !
Op.hasOneUse())
3354 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3362 assert(VT == MVT::i32 || VT == MVT::i64);
3373 EVT VT =
N->getValueType(0);
3374 if (VT != MVT::i32 && VT != MVT::i64)
3392 if (!
And.hasOneUse() ||
3402 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3409 if ((OrImm & NotKnownZero) != 0) {
3421 unsigned ImmS = Width - 1;
3427 bool IsBFI = LSB != 0;
3432 unsigned OrChunks = 0, BFIChunks = 0;
3433 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3434 if (((OrImm >> Shift) & 0xFFFF) != 0)
3436 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3439 if (BFIChunks > OrChunks)
3445 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3453 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3462 if (!Dst.hasOneUse())
3465 EVT VT = Dst.getValueType();
3466 assert((VT == MVT::i32 || VT == MVT::i64) &&
3467 "Caller should guarantee that VT is one of i32 or i64");
3495 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3496 unsigned MaskWidth =
3499 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3505 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3506 ShiftedOperand =
SDValue(UBFMNode, 0);
3535 const bool BiggerPattern) {
3536 EVT VT =
N->getValueType(0);
3537 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3538 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3539 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3540 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3541 assert((VT == MVT::i32 || VT == MVT::i64) &&
3542 "Expect result type to be i32 or i64 since N is combinable to BFM");
3549 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3552 if (BiggerPattern) {
3575 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3637 EVT VT =
N->getValueType(0);
3638 if (VT != MVT::i32 && VT != MVT::i64)
3646 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3647 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3667 for (
int I = 0;
I < 4; ++
I) {
3670 unsigned ImmR, ImmS;
3671 bool BiggerPattern =
I / 2;
3672 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3674 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3680 NumberOfIgnoredLowBits, BiggerPattern)) {
3683 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3684 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3689 Width = ImmS - ImmR + 1;
3700 Src, DstLSB, Width)) {
3708 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3718 APInt BitsToBeInserted =
3721 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3745 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3778 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3780 if (Src->hasOneUse() &&
3783 Src = Src->getOperand(0);
3793 unsigned ImmS = Width - 1;
3799 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3807bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3816 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3829bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3833 EVT VT =
N->getValueType(0);
3834 if (VT != MVT::i32 && VT != MVT::i64)
3840 Op0, DstLSB, Width))
3846 unsigned ImmS = Width - 1;
3849 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3850 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3851 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3852 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3858bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3859 EVT VT =
N->getValueType(0);
3862 switch (
N->getOpcode()) {
3864 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3867 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3870 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3873 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3881 if (VT == MVT::i32) {
3884 }
else if (VT == MVT::i64) {
3890 SDValue ShiftAmt =
N->getOperand(1);
3910 (Add0Imm %
Size == 0)) {
3916 if (SubVT == MVT::i32) {
3917 NegOpc = AArch64::SUBWrr;
3918 ZeroReg = AArch64::WZR;
3920 assert(SubVT == MVT::i64);
3921 NegOpc = AArch64::SUBXrr;
3922 ZeroReg = AArch64::XZR;
3925 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3926 MachineSDNode *Neg =
3927 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3928 NewShiftAmt =
SDValue(Neg, 0);
3936 if (SubVT == MVT::i32) {
3937 NotOpc = AArch64::ORNWrr;
3938 ZeroReg = AArch64::WZR;
3940 assert(SubVT == MVT::i64);
3941 NotOpc = AArch64::ORNXrr;
3942 ZeroReg = AArch64::XZR;
3945 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3946 MachineSDNode *
Not =
3947 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3948 NewShiftAmt =
SDValue(Not, 0);
3969 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3970 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3971 MachineSDNode *Ext = CurDAG->getMachineNode(
3972 AArch64::SUBREG_TO_REG,
DL, VT,
3973 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3974 NewShiftAmt =
SDValue(Ext, 0);
3978 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3985 bool isReciprocal) {
3988 FVal = CN->getValueAPF();
3991 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4020 if (!IsExact || !IntVal.isPowerOf2())
4022 unsigned FBits = IntVal.logBase2();
4026 if (FBits == 0 || FBits > RegWidth)
return false;
4032bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4033 unsigned RegWidth) {
4038bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4040 unsigned RegWidth) {
4050 RegString.
split(Fields,
':');
4052 if (Fields.
size() == 1)
4056 &&
"Invalid number of fields in read register string");
4059 bool AllIntFields =
true;
4063 AllIntFields &= !
Field.getAsInteger(10, IntField);
4064 Ops.push_back(IntField);
4068 "Unexpected non-integer value in special register string.");
4073 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4074 (
Ops[3] << 3) | (
Ops[4]);
4081bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4083 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4086 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4088 unsigned Opcode64Bit = AArch64::MRS;
4093 const auto *TheReg =
4094 AArch64SysReg::lookupSysRegByName(RegString->getString());
4095 if (TheReg && TheReg->Readable &&
4096 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4097 Imm = TheReg->Encoding;
4103 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4104 Opcode64Bit = AArch64::ADR;
4112 SDValue InChain =
N->getOperand(0);
4113 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4114 if (!ReadIs128Bit) {
4115 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4116 {SysRegImm, InChain});
4118 SDNode *MRRS = CurDAG->getMachineNode(
4120 {MVT::Untyped , MVT::Other },
4121 {SysRegImm, InChain});
4125 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4127 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4133 ReplaceUses(
SDValue(
N, 2), OutChain);
4142bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4144 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4147 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4149 if (!WriteIs128Bit) {
4155 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4158 "Expected a constant integer expression.");
4159 unsigned Reg = PMapper->Encoding;
4160 uint64_t Immed =
N->getConstantOperandVal(2);
4161 CurDAG->SelectNodeTo(
4162 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4163 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4169 if (trySelectPState(
4170 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4171 AArch64::MSRpstateImm4))
4173 if (trySelectPState(
4174 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4175 AArch64::MSRpstateImm1))
4184 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4185 if (TheReg && TheReg->Writeable &&
4186 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4187 Imm = TheReg->Encoding;
4196 if (!WriteIs128Bit) {
4197 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4198 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4199 N->getOperand(2), InChain);
4203 SDNode *Pair = CurDAG->getMachineNode(
4204 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4205 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4208 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4210 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4212 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4213 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4221bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4226 if (Subtarget->hasLSE())
return false;
4228 if (MemTy == MVT::i8)
4229 Opcode = AArch64::CMP_SWAP_8;
4230 else if (MemTy == MVT::i16)
4231 Opcode = AArch64::CMP_SWAP_16;
4232 else if (MemTy == MVT::i32)
4233 Opcode = AArch64::CMP_SWAP_32;
4234 else if (MemTy == MVT::i64)
4235 Opcode = AArch64::CMP_SWAP_64;
4239 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4240 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4242 SDNode *CmpSwap = CurDAG->getMachineNode(
4244 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4251 CurDAG->RemoveDeadNode(
N);
4256bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4257 SDValue &Shift,
bool Negate) {
4271 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4278 if ((Val & ~0xff) == 0) {
4279 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4284 if ((Val & ~0xff00) == 0) {
4285 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4297bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4321 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4322 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4329 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4330 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4334 if (Val <= 65280 && Val % 256 == 0) {
4335 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4336 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4347bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4357 int32_t ImmVal, ShiftVal;
4362 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4363 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4367bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4369 int64_t ImmVal = CNode->getSExtValue();
4371 if (ImmVal >= -128 && ImmVal < 128) {
4372 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4379bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4381 uint64_t ImmVal = CNode->getZExtValue();
4391 ImmVal &= 0xFFFFFFFF;
4400 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4407bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4411 ImmVal = CI->getZExtValue();
4413 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4424 ImmVal |= ImmVal << 8;
4425 ImmVal |= ImmVal << 16;
4426 ImmVal |= ImmVal << 32;
4430 ImmVal |= ImmVal << 16;
4431 ImmVal |= ImmVal << 32;
4434 ImmVal &= 0xFFFFFFFF;
4435 ImmVal |= ImmVal << 32;
4447 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4456bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4457 uint64_t
High,
bool AllowSaturation,
4460 uint64_t ImmVal = CN->getZExtValue();
4467 if (ImmVal >
High) {
4468 if (!AllowSaturation)
4473 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4480bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4494 const TargetLowering *TLI = getTargetLowering();
4497 SDValue FiOp = CurDAG->getTargetFrameIndex(
4499 int TagOffset =
N->getConstantOperandVal(3);
4501 SDNode *Out = CurDAG->getMachineNode(
4502 AArch64::TAGPstack,
DL, MVT::i64,
4503 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4504 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4505 ReplaceNode(
N, Out);
4509void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4511 "llvm.aarch64.tagp third argument must be an immediate");
4512 if (trySelectStackSlotTagP(
N))
4519 int TagOffset =
N->getConstantOperandVal(3);
4520 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4521 {
N->getOperand(1),
N->getOperand(2)});
4522 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4523 {
SDValue(N1, 0),
N->getOperand(2)});
4524 SDNode *N3 = CurDAG->getMachineNode(
4525 AArch64::ADDG,
DL, MVT::i64,
4526 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4527 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4531bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4535 if (
N->getConstantOperandVal(2) != 0)
4537 if (!
N->getOperand(0).isUndef())
4541 EVT VT =
N->getValueType(0);
4542 EVT InVT =
N->getOperand(1).getValueType();
4553 "Expected to insert into a packed scalable vector!");
4556 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4557 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4558 N->getOperand(1), RC));
4562bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4566 if (
N->getConstantOperandVal(1) != 0)
4570 EVT VT =
N->getValueType(0);
4571 EVT InVT =
N->getOperand(0).getValueType();
4582 "Expected to extract from a packed scalable vector!");
4585 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4586 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4587 N->getOperand(0), RC));
4591bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4597 EVT VT =
N->getValueType(0);
4610 (Subtarget->hasSVE2() ||
4611 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4612 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4615 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4619 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4620 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4621 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4628 bool IsXOROperand =
true;
4630 IsXOROperand =
false;
4636 APInt ShlAmt, ShrAmt;
4644 if (!IsXOROperand) {
4646 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4649 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4650 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4651 VT, Zero, MOVIV, ZSub);
4662 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4663 AArch64::XAR_ZZZI_D})) {
4664 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4689 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4699 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4707 bool IsXOROperand =
true;
4709 IsXOROperand =
false;
4712 R1 =
XOR.getOperand(0);
4713 R2 =
XOR.getOperand(1);
4723 if (ShAmt + HsAmt != VTSizeInBits)
4726 if (!IsXOROperand) {
4729 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4738 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4744 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4745 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4747 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4750 if (
R2.getValueType() == VT)
4751 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4759 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4764 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4770 SDNode *XAR =
nullptr;
4774 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4775 AArch64::XAR_ZZZI_D}))
4776 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4778 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4781 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4787 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4788 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4791 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4792 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4798 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4802 ReplaceNode(
N, XAR);
4806void AArch64DAGToDAGISel::Select(SDNode *Node) {
4808 if (
Node->isMachineOpcode()) {
4810 Node->setNodeId(-1);
4815 EVT VT =
Node->getValueType(0);
4817 switch (
Node->getOpcode()) {
4821 case ISD::ATOMIC_CMP_SWAP:
4822 if (SelectCMP_SWAP(Node))
4827 case AArch64ISD::MRRS:
4828 if (tryReadRegister(Node))
4833 case AArch64ISD::MSRR:
4834 if (tryWriteRegister(Node))
4841 if (tryIndexedLoad(Node))
4850 if (tryBitfieldExtractOp(Node))
4852 if (tryBitfieldInsertInZeroOp(Node))
4857 if (tryShiftAmountMod(Node))
4862 if (tryBitfieldExtractOpFromSExt(Node))
4867 if (tryBitfieldInsertOp(Node))
4869 if (trySelectXAR(Node))
4874 if (trySelectCastScalableToFixedLengthVector(Node))
4880 if (trySelectCastFixedLengthToScalableVector(Node))
4889 if (ConstNode->
isZero()) {
4890 if (VT == MVT::i32) {
4892 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4893 ReplaceNode(Node,
New.getNode());
4895 }
else if (VT == MVT::i64) {
4897 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4898 ReplaceNode(Node,
New.getNode());
4909 const TargetLowering *TLI = getTargetLowering();
4910 SDValue TFI = CurDAG->getTargetFrameIndex(
4913 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4914 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4915 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4919 unsigned IntNo =
Node->getConstantOperandVal(1);
4923 case Intrinsic::aarch64_gcsss: {
4927 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4929 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4930 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4931 MVT::Other, Zero,
SDValue(SS1, 0));
4932 ReplaceNode(Node, SS2);
4935 case Intrinsic::aarch64_ldaxp:
4936 case Intrinsic::aarch64_ldxp: {
4938 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4943 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4944 MVT::Other, MemAddr, Chain);
4947 MachineMemOperand *MemOp =
4950 ReplaceNode(Node, Ld);
4953 case Intrinsic::aarch64_stlxp:
4954 case Intrinsic::aarch64_stxp: {
4956 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4964 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4966 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4968 MachineMemOperand *MemOp =
4972 ReplaceNode(Node, St);
4975 case Intrinsic::aarch64_neon_ld1x2:
4976 if (VT == MVT::v8i8) {
4977 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4979 }
else if (VT == MVT::v16i8) {
4980 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4982 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4983 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4985 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4986 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4988 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4989 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4991 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4992 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4994 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4995 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4997 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4998 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5002 case Intrinsic::aarch64_neon_ld1x3:
5003 if (VT == MVT::v8i8) {
5004 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5006 }
else if (VT == MVT::v16i8) {
5007 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5009 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5010 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5012 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5013 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5015 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5016 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5018 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5019 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5021 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5022 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5024 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5025 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5029 case Intrinsic::aarch64_neon_ld1x4:
5030 if (VT == MVT::v8i8) {
5031 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5033 }
else if (VT == MVT::v16i8) {
5034 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5036 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5037 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5039 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5040 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5042 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5043 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5045 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5046 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5048 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5049 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5051 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5052 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5056 case Intrinsic::aarch64_neon_ld2:
5057 if (VT == MVT::v8i8) {
5058 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5060 }
else if (VT == MVT::v16i8) {
5061 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5063 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5064 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5066 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5067 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5069 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5070 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5072 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5073 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5075 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5076 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5078 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5079 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5083 case Intrinsic::aarch64_neon_ld3:
5084 if (VT == MVT::v8i8) {
5085 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5087 }
else if (VT == MVT::v16i8) {
5088 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5090 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5091 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5093 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5094 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5096 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5097 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5099 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5100 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5102 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5103 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5105 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5106 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5110 case Intrinsic::aarch64_neon_ld4:
5111 if (VT == MVT::v8i8) {
5112 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5114 }
else if (VT == MVT::v16i8) {
5115 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5117 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5118 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5120 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5121 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5123 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5124 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5126 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5127 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5129 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5130 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5132 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5133 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5137 case Intrinsic::aarch64_neon_ld2r:
5138 if (VT == MVT::v8i8) {
5139 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5141 }
else if (VT == MVT::v16i8) {
5142 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5144 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5145 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5147 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5148 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5150 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5151 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5153 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5154 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5156 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5157 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5159 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5160 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5164 case Intrinsic::aarch64_neon_ld3r:
5165 if (VT == MVT::v8i8) {
5166 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5168 }
else if (VT == MVT::v16i8) {
5169 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5171 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5172 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5174 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5175 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5177 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5178 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5180 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5181 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5183 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5184 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5186 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5187 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5191 case Intrinsic::aarch64_neon_ld4r:
5192 if (VT == MVT::v8i8) {
5193 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5195 }
else if (VT == MVT::v16i8) {
5196 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5198 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5199 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5201 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5202 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5204 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5205 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5207 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5208 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5210 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5211 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5213 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5214 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5218 case Intrinsic::aarch64_neon_ld2lane:
5219 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5220 SelectLoadLane(Node, 2, AArch64::LD2i8);
5222 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5223 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5224 SelectLoadLane(Node, 2, AArch64::LD2i16);
5226 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5228 SelectLoadLane(Node, 2, AArch64::LD2i32);
5230 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5232 SelectLoadLane(Node, 2, AArch64::LD2i64);
5236 case Intrinsic::aarch64_neon_ld3lane:
5237 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5238 SelectLoadLane(Node, 3, AArch64::LD3i8);
5240 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5241 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5242 SelectLoadLane(Node, 3, AArch64::LD3i16);
5244 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5246 SelectLoadLane(Node, 3, AArch64::LD3i32);
5248 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5250 SelectLoadLane(Node, 3, AArch64::LD3i64);
5254 case Intrinsic::aarch64_neon_ld4lane:
5255 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5256 SelectLoadLane(Node, 4, AArch64::LD4i8);
5258 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5259 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5260 SelectLoadLane(Node, 4, AArch64::LD4i16);
5262 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5264 SelectLoadLane(Node, 4, AArch64::LD4i32);
5266 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5268 SelectLoadLane(Node, 4, AArch64::LD4i64);
5272 case Intrinsic::aarch64_ld64b:
5273 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5275 case Intrinsic::aarch64_sve_ld2q_sret: {
5276 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5279 case Intrinsic::aarch64_sve_ld3q_sret: {
5280 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5283 case Intrinsic::aarch64_sve_ld4q_sret: {
5284 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5287 case Intrinsic::aarch64_sve_ld2_sret: {
5288 if (VT == MVT::nxv16i8) {
5289 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5292 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5293 VT == MVT::nxv8bf16) {
5294 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5297 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5298 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5301 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5302 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5308 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5309 if (VT == MVT::nxv16i8) {
5310 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5311 SelectContiguousMultiVectorLoad(
5312 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5313 else if (Subtarget->hasSVE2p1())
5314 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5319 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5320 VT == MVT::nxv8bf16) {
5321 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5322 SelectContiguousMultiVectorLoad(
5323 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5324 else if (Subtarget->hasSVE2p1())
5325 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5330 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5331 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5332 SelectContiguousMultiVectorLoad(
5333 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5334 else if (Subtarget->hasSVE2p1())
5335 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5340 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5341 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5342 SelectContiguousMultiVectorLoad(
5343 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5344 else if (Subtarget->hasSVE2p1())
5345 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5353 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5354 if (VT == MVT::nxv16i8) {
5355 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5356 SelectContiguousMultiVectorLoad(
5357 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5358 else if (Subtarget->hasSVE2p1())
5359 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5364 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5365 VT == MVT::nxv8bf16) {
5366 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5367 SelectContiguousMultiVectorLoad(
5368 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5369 else if (Subtarget->hasSVE2p1())
5370 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5375 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5376 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5377 SelectContiguousMultiVectorLoad(
5378 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5379 else if (Subtarget->hasSVE2p1())
5380 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5385 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5386 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5387 SelectContiguousMultiVectorLoad(
5388 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5389 else if (Subtarget->hasSVE2p1())
5390 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5398 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5399 if (VT == MVT::nxv16i8) {
5400 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5401 SelectContiguousMultiVectorLoad(Node, 2, 0,
5402 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5403 AArch64::LDNT1B_2Z_PSEUDO);
5404 else if (Subtarget->hasSVE2p1())
5405 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5406 AArch64::LDNT1B_2Z);
5410 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5411 VT == MVT::nxv8bf16) {
5412 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5413 SelectContiguousMultiVectorLoad(Node, 2, 1,
5414 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5415 AArch64::LDNT1H_2Z_PSEUDO);
5416 else if (Subtarget->hasSVE2p1())
5417 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5418 AArch64::LDNT1H_2Z);
5422 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5423 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5424 SelectContiguousMultiVectorLoad(Node, 2, 2,
5425 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5426 AArch64::LDNT1W_2Z_PSEUDO);
5427 else if (Subtarget->hasSVE2p1())
5428 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5429 AArch64::LDNT1W_2Z);
5433 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5434 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5435 SelectContiguousMultiVectorLoad(Node, 2, 3,
5436 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5437 AArch64::LDNT1D_2Z_PSEUDO);
5438 else if (Subtarget->hasSVE2p1())
5439 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5440 AArch64::LDNT1D_2Z);
5447 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5448 if (VT == MVT::nxv16i8) {
5449 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5450 SelectContiguousMultiVectorLoad(Node, 4, 0,
5451 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5452 AArch64::LDNT1B_4Z_PSEUDO);
5453 else if (Subtarget->hasSVE2p1())
5454 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5455 AArch64::LDNT1B_4Z);
5459 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5460 VT == MVT::nxv8bf16) {
5461 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5462 SelectContiguousMultiVectorLoad(Node, 4, 1,
5463 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5464 AArch64::LDNT1H_4Z_PSEUDO);
5465 else if (Subtarget->hasSVE2p1())
5466 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5467 AArch64::LDNT1H_4Z);
5471 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5472 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5473 SelectContiguousMultiVectorLoad(Node, 4, 2,
5474 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5475 AArch64::LDNT1W_4Z_PSEUDO);
5476 else if (Subtarget->hasSVE2p1())
5477 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5478 AArch64::LDNT1W_4Z);
5482 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5483 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5484 SelectContiguousMultiVectorLoad(Node, 4, 3,
5485 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5486 AArch64::LDNT1D_4Z_PSEUDO);
5487 else if (Subtarget->hasSVE2p1())
5488 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5489 AArch64::LDNT1D_4Z);
5496 case Intrinsic::aarch64_sve_ld3_sret: {
5497 if (VT == MVT::nxv16i8) {
5498 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5501 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5502 VT == MVT::nxv8bf16) {
5503 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5506 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5507 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5510 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5511 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5517 case Intrinsic::aarch64_sve_ld4_sret: {
5518 if (VT == MVT::nxv16i8) {
5519 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5522 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5523 VT == MVT::nxv8bf16) {
5524 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5527 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5528 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5531 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5532 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5538 case Intrinsic::aarch64_sme_read_hor_vg2: {
5539 if (VT == MVT::nxv16i8) {
5540 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5541 AArch64::MOVA_2ZMXI_H_B);
5543 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5544 VT == MVT::nxv8bf16) {
5545 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5546 AArch64::MOVA_2ZMXI_H_H);
5548 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5549 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5550 AArch64::MOVA_2ZMXI_H_S);
5552 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5553 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5554 AArch64::MOVA_2ZMXI_H_D);
5559 case Intrinsic::aarch64_sme_read_ver_vg2: {
5560 if (VT == MVT::nxv16i8) {
5561 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5562 AArch64::MOVA_2ZMXI_V_B);
5564 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5565 VT == MVT::nxv8bf16) {
5566 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5567 AArch64::MOVA_2ZMXI_V_H);
5569 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5570 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5571 AArch64::MOVA_2ZMXI_V_S);
5573 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5574 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5575 AArch64::MOVA_2ZMXI_V_D);
5580 case Intrinsic::aarch64_sme_read_hor_vg4: {
5581 if (VT == MVT::nxv16i8) {
5582 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5583 AArch64::MOVA_4ZMXI_H_B);
5585 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5586 VT == MVT::nxv8bf16) {
5587 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5588 AArch64::MOVA_4ZMXI_H_H);
5590 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5591 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5592 AArch64::MOVA_4ZMXI_H_S);
5594 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5595 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5596 AArch64::MOVA_4ZMXI_H_D);
5601 case Intrinsic::aarch64_sme_read_ver_vg4: {
5602 if (VT == MVT::nxv16i8) {
5603 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5604 AArch64::MOVA_4ZMXI_V_B);
5606 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5607 VT == MVT::nxv8bf16) {
5608 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5609 AArch64::MOVA_4ZMXI_V_H);
5611 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5612 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5613 AArch64::MOVA_4ZMXI_V_S);
5615 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5616 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5617 AArch64::MOVA_4ZMXI_V_D);
5622 case Intrinsic::aarch64_sme_read_vg1x2: {
5623 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5624 AArch64::MOVA_VG2_2ZMXI);
5627 case Intrinsic::aarch64_sme_read_vg1x4: {
5628 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5629 AArch64::MOVA_VG4_4ZMXI);
5632 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5633 if (VT == MVT::nxv16i8) {
5634 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5636 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5637 VT == MVT::nxv8bf16) {
5638 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5640 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5641 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5643 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5644 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5649 case Intrinsic::aarch64_sme_readz_vert_x2: {
5650 if (VT == MVT::nxv16i8) {
5651 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5653 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5654 VT == MVT::nxv8bf16) {
5655 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5657 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5658 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5660 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5661 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5666 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5667 if (VT == MVT::nxv16i8) {
5668 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5670 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5671 VT == MVT::nxv8bf16) {
5672 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5674 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5675 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5677 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5678 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5683 case Intrinsic::aarch64_sme_readz_vert_x4: {
5684 if (VT == MVT::nxv16i8) {
5685 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5687 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5688 VT == MVT::nxv8bf16) {
5689 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5691 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5692 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5694 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5695 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5700 case Intrinsic::aarch64_sme_readz_x2: {
5701 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5705 case Intrinsic::aarch64_sme_readz_x4: {
5706 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5710 case Intrinsic::swift_async_context_addr: {
5713 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5715 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5716 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5717 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5719 ReplaceUses(
SDValue(Node, 0), Res);
5721 CurDAG->RemoveDeadNode(Node);
5723 auto &MF = CurDAG->getMachineFunction();
5724 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5725 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5728 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5730 Node->getValueType(0),
5731 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5732 AArch64::LUTI2_4ZTZI_S}))
5734 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5737 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5739 Node->getValueType(0),
5740 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5742 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5745 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5747 Node->getValueType(0),
5748 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5749 AArch64::LUTI2_2ZTZI_S}))
5751 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5754 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5756 Node->getValueType(0),
5757 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5758 AArch64::LUTI4_2ZTZI_S}))
5760 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5763 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5764 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5767 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5769 Node->getValueType(0),
5770 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5771 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5773 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5775 Node->getValueType(0),
5776 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5777 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5779 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5781 Node->getValueType(0),
5782 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5783 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5785 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5787 Node->getValueType(0),
5788 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5789 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5794 unsigned IntNo =
Node->getConstantOperandVal(0);
5798 case Intrinsic::aarch64_tagp:
5802 case Intrinsic::ptrauth_auth:
5803 SelectPtrauthAuth(Node);
5806 case Intrinsic::ptrauth_resign:
5807 SelectPtrauthResign(Node);
5810 case Intrinsic::aarch64_neon_tbl2:
5811 SelectTable(Node, 2,
5812 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5815 case Intrinsic::aarch64_neon_tbl3:
5816 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5817 : AArch64::TBLv16i8Three,
5820 case Intrinsic::aarch64_neon_tbl4:
5821 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5822 : AArch64::TBLv16i8Four,
5825 case Intrinsic::aarch64_neon_tbx2:
5826 SelectTable(Node, 2,
5827 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5830 case Intrinsic::aarch64_neon_tbx3:
5831 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5832 : AArch64::TBXv16i8Three,
5835 case Intrinsic::aarch64_neon_tbx4:
5836 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5837 : AArch64::TBXv16i8Four,
5840 case Intrinsic::aarch64_sve_srshl_single_x2:
5842 Node->getValueType(0),
5843 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5844 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5845 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5847 case Intrinsic::aarch64_sve_srshl_single_x4:
5849 Node->getValueType(0),
5850 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5851 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5852 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5854 case Intrinsic::aarch64_sve_urshl_single_x2:
5856 Node->getValueType(0),
5857 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5858 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5859 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5861 case Intrinsic::aarch64_sve_urshl_single_x4:
5863 Node->getValueType(0),
5864 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5865 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5866 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5868 case Intrinsic::aarch64_sve_srshl_x2:
5870 Node->getValueType(0),
5871 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5872 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5873 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5875 case Intrinsic::aarch64_sve_srshl_x4:
5877 Node->getValueType(0),
5878 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5879 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5880 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5882 case Intrinsic::aarch64_sve_urshl_x2:
5884 Node->getValueType(0),
5885 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5886 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5887 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5889 case Intrinsic::aarch64_sve_urshl_x4:
5891 Node->getValueType(0),
5892 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5893 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5894 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5896 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5898 Node->getValueType(0),
5899 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5900 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5901 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5903 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5905 Node->getValueType(0),
5906 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5907 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5908 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5910 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5912 Node->getValueType(0),
5913 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5914 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5915 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5917 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5919 Node->getValueType(0),
5920 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5921 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5922 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5924 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5926 Node->getValueType(0),
5927 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5928 AArch64::FSCALE_2ZZ_D}))
5929 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5931 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5933 Node->getValueType(0),
5934 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5935 AArch64::FSCALE_4ZZ_D}))
5936 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5938 case Intrinsic::aarch64_sme_fp8_scale_x2:
5940 Node->getValueType(0),
5941 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5942 AArch64::FSCALE_2Z2Z_D}))
5943 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5945 case Intrinsic::aarch64_sme_fp8_scale_x4:
5947 Node->getValueType(0),
5948 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5949 AArch64::FSCALE_4Z4Z_D}))
5950 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5952 case Intrinsic::aarch64_sve_whilege_x2:
5954 Node->getValueType(0),
5955 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5956 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5957 SelectWhilePair(Node,
Op);
5959 case Intrinsic::aarch64_sve_whilegt_x2:
5961 Node->getValueType(0),
5962 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5963 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5964 SelectWhilePair(Node,
Op);
5966 case Intrinsic::aarch64_sve_whilehi_x2:
5968 Node->getValueType(0),
5969 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5970 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5971 SelectWhilePair(Node,
Op);
5973 case Intrinsic::aarch64_sve_whilehs_x2:
5975 Node->getValueType(0),
5976 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5977 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5978 SelectWhilePair(Node,
Op);
5980 case Intrinsic::aarch64_sve_whilele_x2:
5982 Node->getValueType(0),
5983 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5984 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5985 SelectWhilePair(Node,
Op);
5987 case Intrinsic::aarch64_sve_whilelo_x2:
5989 Node->getValueType(0),
5990 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5991 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5992 SelectWhilePair(Node,
Op);
5994 case Intrinsic::aarch64_sve_whilels_x2:
5996 Node->getValueType(0),
5997 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5998 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5999 SelectWhilePair(Node,
Op);
6001 case Intrinsic::aarch64_sve_whilelt_x2:
6003 Node->getValueType(0),
6004 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6005 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6006 SelectWhilePair(Node,
Op);
6008 case Intrinsic::aarch64_sve_smax_single_x2:
6010 Node->getValueType(0),
6011 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6012 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6013 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6015 case Intrinsic::aarch64_sve_umax_single_x2:
6017 Node->getValueType(0),
6018 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6019 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6020 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6022 case Intrinsic::aarch64_sve_fmax_single_x2:
6024 Node->getValueType(0),
6025 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6026 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6027 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6029 case Intrinsic::aarch64_sve_smax_single_x4:
6031 Node->getValueType(0),
6032 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6033 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6034 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6036 case Intrinsic::aarch64_sve_umax_single_x4:
6038 Node->getValueType(0),
6039 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6040 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6041 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6043 case Intrinsic::aarch64_sve_fmax_single_x4:
6045 Node->getValueType(0),
6046 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6047 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6048 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6050 case Intrinsic::aarch64_sve_smin_single_x2:
6052 Node->getValueType(0),
6053 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6054 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6055 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6057 case Intrinsic::aarch64_sve_umin_single_x2:
6059 Node->getValueType(0),
6060 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6061 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6062 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6064 case Intrinsic::aarch64_sve_fmin_single_x2:
6066 Node->getValueType(0),
6067 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6068 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6069 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6071 case Intrinsic::aarch64_sve_smin_single_x4:
6073 Node->getValueType(0),
6074 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6075 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6076 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6078 case Intrinsic::aarch64_sve_umin_single_x4:
6080 Node->getValueType(0),
6081 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6082 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6083 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6085 case Intrinsic::aarch64_sve_fmin_single_x4:
6087 Node->getValueType(0),
6088 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6089 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6090 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6092 case Intrinsic::aarch64_sve_smax_x2:
6094 Node->getValueType(0),
6095 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6096 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6097 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6099 case Intrinsic::aarch64_sve_umax_x2:
6101 Node->getValueType(0),
6102 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6103 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6104 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6106 case Intrinsic::aarch64_sve_fmax_x2:
6108 Node->getValueType(0),
6109 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6110 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6111 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6113 case Intrinsic::aarch64_sve_smax_x4:
6115 Node->getValueType(0),
6116 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6117 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6118 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6120 case Intrinsic::aarch64_sve_umax_x4:
6122 Node->getValueType(0),
6123 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6124 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6125 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6127 case Intrinsic::aarch64_sve_fmax_x4:
6129 Node->getValueType(0),
6130 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6131 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6132 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6134 case Intrinsic::aarch64_sme_famax_x2:
6136 Node->getValueType(0),
6137 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6138 AArch64::FAMAX_2Z2Z_D}))
6139 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6141 case Intrinsic::aarch64_sme_famax_x4:
6143 Node->getValueType(0),
6144 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6145 AArch64::FAMAX_4Z4Z_D}))
6146 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6148 case Intrinsic::aarch64_sme_famin_x2:
6150 Node->getValueType(0),
6151 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6152 AArch64::FAMIN_2Z2Z_D}))
6153 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6155 case Intrinsic::aarch64_sme_famin_x4:
6157 Node->getValueType(0),
6158 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6159 AArch64::FAMIN_4Z4Z_D}))
6160 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6162 case Intrinsic::aarch64_sve_smin_x2:
6164 Node->getValueType(0),
6165 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6166 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6167 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6169 case Intrinsic::aarch64_sve_umin_x2:
6171 Node->getValueType(0),
6172 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6173 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6174 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6176 case Intrinsic::aarch64_sve_fmin_x2:
6178 Node->getValueType(0),
6179 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6180 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6181 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6183 case Intrinsic::aarch64_sve_smin_x4:
6185 Node->getValueType(0),
6186 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6187 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6188 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6190 case Intrinsic::aarch64_sve_umin_x4:
6192 Node->getValueType(0),
6193 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6194 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6195 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6197 case Intrinsic::aarch64_sve_fmin_x4:
6199 Node->getValueType(0),
6200 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6201 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6202 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6204 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6206 Node->getValueType(0),
6207 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6208 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6209 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6211 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6213 Node->getValueType(0),
6214 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6215 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6216 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6218 case Intrinsic::aarch64_sve_fminnm_single_x2:
6220 Node->getValueType(0),
6221 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6222 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6223 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6225 case Intrinsic::aarch64_sve_fminnm_single_x4:
6227 Node->getValueType(0),
6228 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6229 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6230 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6232 case Intrinsic::aarch64_sve_fscale_single_x4:
6233 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6235 case Intrinsic::aarch64_sve_fscale_single_x2:
6236 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6238 case Intrinsic::aarch64_sve_fmul_single_x4:
6240 Node->getValueType(0),
6241 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6242 AArch64::FMUL_4ZZ_D}))
6243 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6245 case Intrinsic::aarch64_sve_fmul_single_x2:
6247 Node->getValueType(0),
6248 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6249 AArch64::FMUL_2ZZ_D}))
6250 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6252 case Intrinsic::aarch64_sve_fmaxnm_x2:
6254 Node->getValueType(0),
6255 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6256 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6257 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6259 case Intrinsic::aarch64_sve_fmaxnm_x4:
6261 Node->getValueType(0),
6262 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6263 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6264 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6266 case Intrinsic::aarch64_sve_fminnm_x2:
6268 Node->getValueType(0),
6269 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6270 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6271 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6273 case Intrinsic::aarch64_sve_fminnm_x4:
6275 Node->getValueType(0),
6276 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6277 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6278 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6280 case Intrinsic::aarch64_sve_fscale_x4:
6281 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6283 case Intrinsic::aarch64_sve_fscale_x2:
6284 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6286 case Intrinsic::aarch64_sve_fmul_x4:
6288 Node->getValueType(0),
6289 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6290 AArch64::FMUL_4Z4Z_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6293 case Intrinsic::aarch64_sve_fmul_x2:
6295 Node->getValueType(0),
6296 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6297 AArch64::FMUL_2Z2Z_D}))
6298 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6300 case Intrinsic::aarch64_sve_fcvtzs_x2:
6301 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6303 case Intrinsic::aarch64_sve_scvtf_x2:
6304 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6306 case Intrinsic::aarch64_sve_fcvtzu_x2:
6307 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6309 case Intrinsic::aarch64_sve_ucvtf_x2:
6310 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6312 case Intrinsic::aarch64_sve_fcvtzs_x4:
6313 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6315 case Intrinsic::aarch64_sve_scvtf_x4:
6316 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6318 case Intrinsic::aarch64_sve_fcvtzu_x4:
6319 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6321 case Intrinsic::aarch64_sve_ucvtf_x4:
6322 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6324 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6325 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6327 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6328 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6330 case Intrinsic::aarch64_sve_sclamp_single_x2:
6332 Node->getValueType(0),
6333 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6334 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6335 SelectClamp(Node, 2,
Op);
6337 case Intrinsic::aarch64_sve_uclamp_single_x2:
6339 Node->getValueType(0),
6340 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6341 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6342 SelectClamp(Node, 2,
Op);
6344 case Intrinsic::aarch64_sve_fclamp_single_x2:
6346 Node->getValueType(0),
6347 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6348 AArch64::FCLAMP_VG2_2Z2Z_D}))
6349 SelectClamp(Node, 2,
Op);
6351 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6352 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6354 case Intrinsic::aarch64_sve_sclamp_single_x4:
6356 Node->getValueType(0),
6357 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6358 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6359 SelectClamp(Node, 4,
Op);
6361 case Intrinsic::aarch64_sve_uclamp_single_x4:
6363 Node->getValueType(0),
6364 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6365 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6366 SelectClamp(Node, 4,
Op);
6368 case Intrinsic::aarch64_sve_fclamp_single_x4:
6370 Node->getValueType(0),
6371 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6372 AArch64::FCLAMP_VG4_4Z4Z_D}))
6373 SelectClamp(Node, 4,
Op);
6375 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6376 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6378 case Intrinsic::aarch64_sve_add_single_x2:
6380 Node->getValueType(0),
6381 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6382 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6383 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6385 case Intrinsic::aarch64_sve_add_single_x4:
6387 Node->getValueType(0),
6388 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6389 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6390 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6392 case Intrinsic::aarch64_sve_zip_x2:
6394 Node->getValueType(0),
6395 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6396 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6397 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6399 case Intrinsic::aarch64_sve_zipq_x2:
6400 SelectUnaryMultiIntrinsic(Node, 2,
false,
6401 AArch64::ZIP_VG2_2ZZZ_Q);
6403 case Intrinsic::aarch64_sve_zip_x4:
6405 Node->getValueType(0),
6406 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6407 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6408 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6410 case Intrinsic::aarch64_sve_zipq_x4:
6411 SelectUnaryMultiIntrinsic(Node, 4,
true,
6412 AArch64::ZIP_VG4_4Z4Z_Q);
6414 case Intrinsic::aarch64_sve_uzp_x2:
6416 Node->getValueType(0),
6417 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6418 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6419 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6421 case Intrinsic::aarch64_sve_uzpq_x2:
6422 SelectUnaryMultiIntrinsic(Node, 2,
false,
6423 AArch64::UZP_VG2_2ZZZ_Q);
6425 case Intrinsic::aarch64_sve_uzp_x4:
6427 Node->getValueType(0),
6428 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6429 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6430 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6432 case Intrinsic::aarch64_sve_uzpq_x4:
6433 SelectUnaryMultiIntrinsic(Node, 4,
true,
6434 AArch64::UZP_VG4_4Z4Z_Q);
6436 case Intrinsic::aarch64_sve_sel_x2:
6438 Node->getValueType(0),
6439 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6440 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6441 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6443 case Intrinsic::aarch64_sve_sel_x4:
6445 Node->getValueType(0),
6446 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6447 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6448 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6450 case Intrinsic::aarch64_sve_frinta_x2:
6451 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6453 case Intrinsic::aarch64_sve_frinta_x4:
6454 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6456 case Intrinsic::aarch64_sve_frintm_x2:
6457 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6459 case Intrinsic::aarch64_sve_frintm_x4:
6460 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6462 case Intrinsic::aarch64_sve_frintn_x2:
6463 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6465 case Intrinsic::aarch64_sve_frintn_x4:
6466 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6468 case Intrinsic::aarch64_sve_frintp_x2:
6469 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6471 case Intrinsic::aarch64_sve_frintp_x4:
6472 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6474 case Intrinsic::aarch64_sve_sunpk_x2:
6476 Node->getValueType(0),
6477 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6478 AArch64::SUNPK_VG2_2ZZ_D}))
6479 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6481 case Intrinsic::aarch64_sve_uunpk_x2:
6483 Node->getValueType(0),
6484 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6485 AArch64::UUNPK_VG2_2ZZ_D}))
6486 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6488 case Intrinsic::aarch64_sve_sunpk_x4:
6490 Node->getValueType(0),
6491 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6492 AArch64::SUNPK_VG4_4Z2Z_D}))
6493 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6495 case Intrinsic::aarch64_sve_uunpk_x4:
6497 Node->getValueType(0),
6498 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6499 AArch64::UUNPK_VG4_4Z2Z_D}))
6500 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6502 case Intrinsic::aarch64_sve_pext_x2: {
6504 Node->getValueType(0),
6505 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6506 AArch64::PEXT_2PCI_D}))
6507 SelectPExtPair(Node,
Op);
6514 unsigned IntNo =
Node->getConstantOperandVal(1);
6515 if (
Node->getNumOperands() >= 3)
6516 VT =
Node->getOperand(2)->getValueType(0);
6520 case Intrinsic::aarch64_neon_st1x2: {
6521 if (VT == MVT::v8i8) {
6522 SelectStore(Node, 2, AArch64::ST1Twov8b);
6524 }
else if (VT == MVT::v16i8) {
6525 SelectStore(Node, 2, AArch64::ST1Twov16b);
6527 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6528 VT == MVT::v4bf16) {
6529 SelectStore(Node, 2, AArch64::ST1Twov4h);
6531 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6532 VT == MVT::v8bf16) {
6533 SelectStore(Node, 2, AArch64::ST1Twov8h);
6535 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6536 SelectStore(Node, 2, AArch64::ST1Twov2s);
6538 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6539 SelectStore(Node, 2, AArch64::ST1Twov4s);
6541 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6542 SelectStore(Node, 2, AArch64::ST1Twov2d);
6544 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6545 SelectStore(Node, 2, AArch64::ST1Twov1d);
6550 case Intrinsic::aarch64_neon_st1x3: {
6551 if (VT == MVT::v8i8) {
6552 SelectStore(Node, 3, AArch64::ST1Threev8b);
6554 }
else if (VT == MVT::v16i8) {
6555 SelectStore(Node, 3, AArch64::ST1Threev16b);
6557 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6558 VT == MVT::v4bf16) {
6559 SelectStore(Node, 3, AArch64::ST1Threev4h);
6561 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6562 VT == MVT::v8bf16) {
6563 SelectStore(Node, 3, AArch64::ST1Threev8h);
6565 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6566 SelectStore(Node, 3, AArch64::ST1Threev2s);
6568 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6569 SelectStore(Node, 3, AArch64::ST1Threev4s);
6571 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6572 SelectStore(Node, 3, AArch64::ST1Threev2d);
6574 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6575 SelectStore(Node, 3, AArch64::ST1Threev1d);
6580 case Intrinsic::aarch64_neon_st1x4: {
6581 if (VT == MVT::v8i8) {
6582 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6584 }
else if (VT == MVT::v16i8) {
6585 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6587 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6588 VT == MVT::v4bf16) {
6589 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6591 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6592 VT == MVT::v8bf16) {
6593 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6595 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6596 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6598 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6599 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6601 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6602 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6604 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6605 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6610 case Intrinsic::aarch64_neon_st2: {
6611 if (VT == MVT::v8i8) {
6612 SelectStore(Node, 2, AArch64::ST2Twov8b);
6614 }
else if (VT == MVT::v16i8) {
6615 SelectStore(Node, 2, AArch64::ST2Twov16b);
6617 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6618 VT == MVT::v4bf16) {
6619 SelectStore(Node, 2, AArch64::ST2Twov4h);
6621 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6622 VT == MVT::v8bf16) {
6623 SelectStore(Node, 2, AArch64::ST2Twov8h);
6625 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6626 SelectStore(Node, 2, AArch64::ST2Twov2s);
6628 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6629 SelectStore(Node, 2, AArch64::ST2Twov4s);
6631 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6632 SelectStore(Node, 2, AArch64::ST2Twov2d);
6634 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6635 SelectStore(Node, 2, AArch64::ST1Twov1d);
6640 case Intrinsic::aarch64_neon_st3: {
6641 if (VT == MVT::v8i8) {
6642 SelectStore(Node, 3, AArch64::ST3Threev8b);
6644 }
else if (VT == MVT::v16i8) {
6645 SelectStore(Node, 3, AArch64::ST3Threev16b);
6647 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6648 VT == MVT::v4bf16) {
6649 SelectStore(Node, 3, AArch64::ST3Threev4h);
6651 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6652 VT == MVT::v8bf16) {
6653 SelectStore(Node, 3, AArch64::ST3Threev8h);
6655 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6656 SelectStore(Node, 3, AArch64::ST3Threev2s);
6658 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6659 SelectStore(Node, 3, AArch64::ST3Threev4s);
6661 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6662 SelectStore(Node, 3, AArch64::ST3Threev2d);
6664 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6665 SelectStore(Node, 3, AArch64::ST1Threev1d);
6670 case Intrinsic::aarch64_neon_st4: {
6671 if (VT == MVT::v8i8) {
6672 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6674 }
else if (VT == MVT::v16i8) {
6675 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6677 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6678 VT == MVT::v4bf16) {
6679 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6681 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6682 VT == MVT::v8bf16) {
6683 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6685 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6686 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6688 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6689 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6691 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6692 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6694 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6695 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6700 case Intrinsic::aarch64_neon_st2lane: {
6701 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6702 SelectStoreLane(Node, 2, AArch64::ST2i8);
6704 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6705 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6706 SelectStoreLane(Node, 2, AArch64::ST2i16);
6708 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6710 SelectStoreLane(Node, 2, AArch64::ST2i32);
6712 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6714 SelectStoreLane(Node, 2, AArch64::ST2i64);
6719 case Intrinsic::aarch64_neon_st3lane: {
6720 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6721 SelectStoreLane(Node, 3, AArch64::ST3i8);
6723 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6724 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6725 SelectStoreLane(Node, 3, AArch64::ST3i16);
6727 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6729 SelectStoreLane(Node, 3, AArch64::ST3i32);
6731 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6733 SelectStoreLane(Node, 3, AArch64::ST3i64);
6738 case Intrinsic::aarch64_neon_st4lane: {
6739 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6740 SelectStoreLane(Node, 4, AArch64::ST4i8);
6742 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6743 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6744 SelectStoreLane(Node, 4, AArch64::ST4i16);
6746 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6748 SelectStoreLane(Node, 4, AArch64::ST4i32);
6750 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6752 SelectStoreLane(Node, 4, AArch64::ST4i64);
6757 case Intrinsic::aarch64_sve_st2q: {
6758 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6761 case Intrinsic::aarch64_sve_st3q: {
6762 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6765 case Intrinsic::aarch64_sve_st4q: {
6766 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6769 case Intrinsic::aarch64_sve_st2: {
6770 if (VT == MVT::nxv16i8) {
6771 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6773 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6774 VT == MVT::nxv8bf16) {
6775 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6777 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6778 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6780 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6781 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6786 case Intrinsic::aarch64_sve_st3: {
6787 if (VT == MVT::nxv16i8) {
6788 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6790 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6791 VT == MVT::nxv8bf16) {
6792 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6794 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6795 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6797 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6798 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6803 case Intrinsic::aarch64_sve_st4: {
6804 if (VT == MVT::nxv16i8) {
6805 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6807 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6808 VT == MVT::nxv8bf16) {
6809 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6811 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6812 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6814 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6815 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6823 case AArch64ISD::LD2post: {
6824 if (VT == MVT::v8i8) {
6825 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6827 }
else if (VT == MVT::v16i8) {
6828 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6830 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6831 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6833 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6834 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6836 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6837 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6839 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6840 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6842 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6843 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6845 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6846 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6851 case AArch64ISD::LD3post: {
6852 if (VT == MVT::v8i8) {
6853 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6855 }
else if (VT == MVT::v16i8) {
6856 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6858 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6859 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6861 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6862 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6864 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6865 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6867 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6868 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6870 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6871 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6873 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6874 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6879 case AArch64ISD::LD4post: {
6880 if (VT == MVT::v8i8) {
6881 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6883 }
else if (VT == MVT::v16i8) {
6884 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6886 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6887 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6889 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6890 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6892 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6893 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6895 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6896 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6898 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6899 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6901 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6902 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6907 case AArch64ISD::LD1x2post: {
6908 if (VT == MVT::v8i8) {
6909 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6911 }
else if (VT == MVT::v16i8) {
6912 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6914 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6915 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6917 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6918 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6920 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6921 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6923 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6924 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6926 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6927 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6929 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6930 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6935 case AArch64ISD::LD1x3post: {
6936 if (VT == MVT::v8i8) {
6937 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6939 }
else if (VT == MVT::v16i8) {
6940 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6942 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6943 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6945 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6946 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6948 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6949 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6951 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6952 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6954 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6955 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6957 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6958 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6963 case AArch64ISD::LD1x4post: {
6964 if (VT == MVT::v8i8) {
6965 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6967 }
else if (VT == MVT::v16i8) {
6968 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6970 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6971 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6973 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6974 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6976 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6977 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6979 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6980 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6982 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6983 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6985 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6986 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6991 case AArch64ISD::LD1DUPpost: {
6992 if (VT == MVT::v8i8) {
6993 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6995 }
else if (VT == MVT::v16i8) {
6996 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6998 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6999 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7001 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7002 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7004 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7005 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7007 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7008 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7010 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7011 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7013 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7014 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7019 case AArch64ISD::LD2DUPpost: {
7020 if (VT == MVT::v8i8) {
7021 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7023 }
else if (VT == MVT::v16i8) {
7024 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7026 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7027 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7029 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7030 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7032 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7033 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7035 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7036 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7038 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7039 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7041 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7042 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7047 case AArch64ISD::LD3DUPpost: {
7048 if (VT == MVT::v8i8) {
7049 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7051 }
else if (VT == MVT::v16i8) {
7052 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7054 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7055 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7057 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7058 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7060 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7061 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7063 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7064 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7066 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7067 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7069 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7070 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7075 case AArch64ISD::LD4DUPpost: {
7076 if (VT == MVT::v8i8) {
7077 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7079 }
else if (VT == MVT::v16i8) {
7080 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7082 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7083 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7085 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7086 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7088 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7089 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7091 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7092 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7094 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7095 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7097 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7098 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7103 case AArch64ISD::LD1LANEpost: {
7104 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7105 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7107 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7108 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7109 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7111 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7113 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7115 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7117 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7122 case AArch64ISD::LD2LANEpost: {
7123 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7124 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7126 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7127 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7128 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7130 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7132 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7134 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7136 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7141 case AArch64ISD::LD3LANEpost: {
7142 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7143 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7145 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7146 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7147 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7149 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7151 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7153 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7155 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7160 case AArch64ISD::LD4LANEpost: {
7161 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7162 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7164 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7165 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7166 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7168 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7170 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7172 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7174 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7179 case AArch64ISD::ST2post: {
7180 VT =
Node->getOperand(1).getValueType();
7181 if (VT == MVT::v8i8) {
7182 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7184 }
else if (VT == MVT::v16i8) {
7185 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7187 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7188 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7190 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7191 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7193 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7194 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7196 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7197 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7199 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7200 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7202 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7203 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7208 case AArch64ISD::ST3post: {
7209 VT =
Node->getOperand(1).getValueType();
7210 if (VT == MVT::v8i8) {
7211 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7213 }
else if (VT == MVT::v16i8) {
7214 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7216 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7217 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7219 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7220 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7222 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7223 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7225 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7226 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7228 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7229 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7231 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7232 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7237 case AArch64ISD::ST4post: {
7238 VT =
Node->getOperand(1).getValueType();
7239 if (VT == MVT::v8i8) {
7240 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7242 }
else if (VT == MVT::v16i8) {
7243 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7245 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7246 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7248 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7249 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7251 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7252 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7254 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7255 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7257 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7258 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7260 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7261 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7266 case AArch64ISD::ST1x2post: {
7267 VT =
Node->getOperand(1).getValueType();
7268 if (VT == MVT::v8i8) {
7269 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7271 }
else if (VT == MVT::v16i8) {
7272 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7274 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7275 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7277 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7278 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7280 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7281 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7283 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7284 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7286 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7287 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7289 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7290 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7295 case AArch64ISD::ST1x3post: {
7296 VT =
Node->getOperand(1).getValueType();
7297 if (VT == MVT::v8i8) {
7298 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7300 }
else if (VT == MVT::v16i8) {
7301 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7303 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7304 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7306 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7307 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7309 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7310 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7312 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7313 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7315 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7316 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7318 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7319 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7324 case AArch64ISD::ST1x4post: {
7325 VT =
Node->getOperand(1).getValueType();
7326 if (VT == MVT::v8i8) {
7327 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7329 }
else if (VT == MVT::v16i8) {
7330 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7332 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7333 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7335 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7336 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7338 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7339 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7341 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7342 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7344 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7345 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7347 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7348 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7353 case AArch64ISD::ST2LANEpost: {
7354 VT =
Node->getOperand(1).getValueType();
7355 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7356 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7358 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7359 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7360 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7362 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7364 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7366 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7368 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7373 case AArch64ISD::ST3LANEpost: {
7374 VT =
Node->getOperand(1).getValueType();
7375 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7376 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7378 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7379 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7380 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7382 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7384 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7386 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7388 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7393 case AArch64ISD::ST4LANEpost: {
7394 VT =
Node->getOperand(1).getValueType();
7395 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7396 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7398 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7399 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7400 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7402 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7404 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7406 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7408 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7423 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7435 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7439 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7440 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7455 return MemIntr->getMemoryVT();
7462 DataVT = Load->getValueType(0);
7464 DataVT = Load->getValueType(0);
7466 DataVT = Store->getValue().getValueType();
7468 DataVT = Store->getValue().getValueType();
7475 const unsigned Opcode = Root->
getOpcode();
7479 case AArch64ISD::LD1_MERGE_ZERO:
7480 case AArch64ISD::LD1S_MERGE_ZERO:
7481 case AArch64ISD::LDNF1_MERGE_ZERO:
7482 case AArch64ISD::LDNF1S_MERGE_ZERO:
7484 case AArch64ISD::ST1_PRED:
7496 case Intrinsic::aarch64_sme_ldr:
7497 case Intrinsic::aarch64_sme_str:
7498 return MVT::nxv16i8;
7499 case Intrinsic::aarch64_sve_prf:
7504 case Intrinsic::aarch64_sve_ld2_sret:
7505 case Intrinsic::aarch64_sve_ld2q_sret:
7508 case Intrinsic::aarch64_sve_st2q:
7511 case Intrinsic::aarch64_sve_ld3_sret:
7512 case Intrinsic::aarch64_sve_ld3q_sret:
7515 case Intrinsic::aarch64_sve_st3q:
7518 case Intrinsic::aarch64_sve_ld4_sret:
7519 case Intrinsic::aarch64_sve_ld4q_sret:
7522 case Intrinsic::aarch64_sve_st4q:
7525 case Intrinsic::aarch64_sve_ld1udq:
7526 case Intrinsic::aarch64_sve_st1dq:
7527 return EVT(MVT::nxv1i64);
7528 case Intrinsic::aarch64_sve_ld1uwq:
7529 case Intrinsic::aarch64_sve_st1wq:
7530 return EVT(MVT::nxv1i32);
7537template <
int64_t Min,
int64_t Max>
7538bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7542 const DataLayout &
DL = CurDAG->getDataLayout();
7543 const MachineFrameInfo &MFI = MF->getFrameInfo();
7551 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7565 int64_t MulImm = std::numeric_limits<int64_t>::max();
7566 if (VScale.
getOpcode() == ISD::VSCALE) {
7569 int64_t ByteOffset =
C->getSExtValue();
7570 const auto KnownVScale =
7573 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7576 MulImm = ByteOffset / KnownVScale;
7583 if ((MulImm % MemWidthBytes) != 0)
7586 int64_t
Offset = MulImm / MemWidthBytes;
7590 Base =
N.getOperand(0);
7599 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7605bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7624 int64_t ImmOff =
C->getSExtValue();
7625 unsigned Size = 1 << Scale;
7634 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7636 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7647 if (
C->getZExtValue() == Scale) {
7656bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7657 const AArch64TargetLowering *TLI =
7658 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7663bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7664 EVT VT =
N.getValueType();
7668bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7673 int64_t ImmOff =
C->getSExtValue();
7674 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7675 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7680 if (
SDValue C = MatchConstantOffset(
N)) {
7681 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7687 if (CurDAG->isBaseWithConstantOffset(
N)) {
7688 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7689 Base =
N.getOperand(0);
7697 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7701bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7721 uint64_t LowerBound = 0, UpperBound = 64;
7739 if (CN->getAPIntValue().uge(LowerBound) &&
7740 CN->getAPIntValue().ult(UpperBound)) {
7742 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7750template <
bool MatchCBB>
7757 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7759 Reg =
N.getOperand(0);
7761 SDLoc(
N), MVT::i32);
7769 Reg =
N.getOperand(0);
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
shuff Hexagon Optimize Shuffle Vector
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
static constexpr roundingMode rmTowardZero
LLVM_ABI 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)
bool hasScalableStackID(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 ...
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
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 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.