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()) {
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 SDUse *OpsIter =
N->op_begin() + 1;
1985 auto GetMultiVecOperand = [&]() {
1988 return createZMulTuple(Regs);
1992 Ops.push_back(*OpsIter++);
1994 Ops.push_back(GetMultiVecOperand());
1996 Ops.push_back(GetMultiVecOperand());
1998 Ops.push_back(*OpsIter++);
2001 Ops.append(OpsIter,
N->op_end());
2003 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2005 for (
unsigned i = 0; i < NumVecs; ++i)
2006 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2007 AArch64::zsub0 + i,
DL, VT, SuperReg));
2009 CurDAG->RemoveDeadNode(
N);
2012void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2013 unsigned Scale,
unsigned Opc_ri,
2014 unsigned Opc_rr,
bool IsIntr) {
2015 assert(Scale < 5 &&
"Invalid scaling value.");
2017 EVT VT =
N->getValueType(0);
2024 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2025 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2031 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2033 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2035 for (
unsigned i = 0; i < NumVecs; ++i)
2036 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2037 AArch64::zsub0 + i,
DL, VT, SuperReg));
2040 unsigned ChainIdx = NumVecs;
2042 CurDAG->RemoveDeadNode(
N);
2045void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2050 assert(Scale < 4 &&
"Invalid scaling value.");
2052 EVT VT =
N->getValueType(0);
2060 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2066 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2068 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2070 for (
unsigned i = 0; i < NumVecs; ++i)
2071 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2072 AArch64::zsub0 + i,
DL, VT, SuperReg));
2075 unsigned ChainIdx = NumVecs;
2077 CurDAG->RemoveDeadNode(
N);
2080void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2082 if (
N->getValueType(0) != MVT::nxv4f32)
2084 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2087void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2088 unsigned NumOutVecs,
2092 if (
Imm->getZExtValue() > MaxImm)
2096 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2102 EVT VT =
Node->getValueType(0);
2105 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2108 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2109 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2110 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2113 unsigned ChainIdx = NumOutVecs;
2115 CurDAG->RemoveDeadNode(Node);
2118void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2119 unsigned NumOutVecs,
2122 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2127 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2131 EVT VT =
Node->getValueType(0);
2134 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2137 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2138 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2139 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2142 unsigned ChainIdx = NumOutVecs;
2144 CurDAG->RemoveDeadNode(Node);
2147void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2150 EVT VT =
N->getValueType(0);
2153 SDValue Zd = createZMulTuple(Regs);
2154 SDValue Zn =
N->getOperand(1 + NumVecs);
2155 SDValue Zm =
N->getOperand(2 + NumVecs);
2161 for (
unsigned i = 0; i < NumVecs; ++i)
2162 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2163 AArch64::zsub0 + i,
DL, VT, SuperReg));
2165 CurDAG->RemoveDeadNode(
N);
2195template <
unsigned MaxIdx,
unsigned Scale>
2196void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2197 unsigned BaseReg,
unsigned Op) {
2198 unsigned TileNum = 0;
2199 if (BaseReg != AArch64::ZA)
2200 TileNum =
N->getConstantOperandVal(2);
2206 if (BaseReg == AArch64::ZA)
2211 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2217 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2219 EVT VT =
N->getValueType(0);
2220 for (
unsigned I = 0;
I < NumVecs; ++
I)
2222 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2225 unsigned ChainIdx = NumVecs;
2227 CurDAG->RemoveDeadNode(
N);
2230void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2231 unsigned Op,
unsigned MaxIdx,
2232 unsigned Scale,
unsigned BaseReg) {
2237 if (BaseReg != AArch64::ZA)
2241 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2248 if (BaseReg != AArch64::ZA )
2249 Ops.push_back(
N->getOperand(2));
2252 Ops.push_back(
N->getOperand(0));
2253 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2255 EVT VT =
N->getValueType(0);
2256 for (
unsigned I = 0;
I < NumVecs; ++
I)
2258 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2262 unsigned ChainIdx = NumVecs;
2264 CurDAG->RemoveDeadNode(
N);
2267void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2268 unsigned NumOutVecs,
2272 EVT VT =
N->getValueType(0);
2273 unsigned NumInVecs =
N->getNumOperands() - 1;
2277 assert((NumInVecs == 2 || NumInVecs == 4) &&
2278 "Don't know how to handle multi-register input!");
2280 Ops.push_back(createZMulTuple(Regs));
2283 for (
unsigned I = 0;
I < NumInVecs;
I++)
2284 Ops.push_back(
N->getOperand(1 +
I));
2287 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2290 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2291 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2292 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2293 CurDAG->RemoveDeadNode(
N);
2296void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2299 EVT VT =
N->getOperand(2)->getValueType(0);
2307 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2316void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2317 unsigned Scale,
unsigned Opc_rr,
2323 SDValue RegSeq = createZTuple(Regs);
2329 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2330 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2336 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2344 const DataLayout &
DL = CurDAG->getDataLayout();
2345 const TargetLowering *TLI = getTargetLowering();
2349 int FI = FINode->getIndex();
2351 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2358void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2361 EVT VT =
N->getOperand(2)->getValueType(0);
2362 const EVT ResTys[] = {MVT::i64,
2374 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2414void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2417 EVT VT =
N->getValueType(0);
2429 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2431 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2433 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2435 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2439 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2440 AArch64::qsub2, AArch64::qsub3 };
2441 for (
unsigned i = 0; i < NumVecs; ++i) {
2442 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2449 CurDAG->RemoveDeadNode(
N);
2452void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2455 EVT VT =
N->getValueType(0);
2467 const EVT ResTys[] = {MVT::i64,
2470 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2473 CurDAG->getTargetConstant(LaneNo, dl,
2478 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2490 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2491 AArch64::qsub2, AArch64::qsub3 };
2492 for (
unsigned i = 0; i < NumVecs; ++i) {
2493 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2503 CurDAG->RemoveDeadNode(
N);
2506void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2509 EVT VT =
N->getOperand(2)->getValueType(0);
2521 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2523 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2525 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2534void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2537 EVT VT =
N->getOperand(2)->getValueType(0);
2549 const EVT ResTys[] = {MVT::i64,
2552 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2554 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2558 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2569 unsigned &LSB,
unsigned &MSB,
2570 unsigned NumberOfIgnoredLowBits,
2571 bool BiggerPattern) {
2573 "N must be a AND operation to call this function");
2575 EVT VT =
N->getValueType(0);
2580 assert((VT == MVT::i32 || VT == MVT::i64) &&
2581 "Type checking must have been done before calling this function");
2595 const SDNode *Op0 =
N->getOperand(0).getNode();
2602 if (AndImm & (AndImm + 1))
2605 bool ClampMSB =
false;
2625 ClampMSB = (VT == MVT::i32);
2626 }
else if (BiggerPattern) {
2632 Opd0 =
N->getOperand(0);
2638 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2641 <<
": Found large shift immediate, this should not happen\n"));
2655 MSB = MSB > 31 ? 31 : MSB;
2657 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2662 SDValue &Opd0,
unsigned &Immr,
2666 EVT VT =
N->getValueType(0);
2668 assert((VT == MVT::i32 || VT == MVT::i64) &&
2669 "Type checking must have been done before calling this function");
2673 Op =
Op->getOperand(0);
2674 VT =
Op->getValueType(0);
2683 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2687 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2688 Opd0 =
Op.getOperand(0);
2690 Imms = ShiftImm + Width - 1;
2718 Opd0 =
N->getOperand(0).getOperand(0);
2728 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2735 unsigned &Immr,
unsigned &Imms,
2736 bool BiggerPattern) {
2738 "N must be a SHR/SRA operation to call this function");
2740 EVT VT =
N->getValueType(0);
2745 assert((VT == MVT::i32 || VT == MVT::i64) &&
2746 "Type checking must have been done before calling this function");
2756 Opd0 =
N->getOperand(0).getOperand(0);
2757 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2763 Opd0 =
N->getOperand(0).getOperand(0);
2766 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2767 }
else if (BiggerPattern) {
2771 Opd0 =
N->getOperand(0);
2780 <<
": Found large shift immediate, this should not happen\n"));
2789 "bad amount in shift node!");
2790 int immr = SrlImm - ShlImm;
2795 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2797 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2801bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2804 EVT VT =
N->getValueType(0);
2805 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2806 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2817 unsigned Immr = ShiftImm;
2819 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2820 CurDAG->getTargetConstant(Imms, dl, VT)};
2821 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2826 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2827 unsigned NumberOfIgnoredLowBits = 0,
2828 bool BiggerPattern =
false) {
2829 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2832 switch (
N->getOpcode()) {
2834 if (!
N->isMachineOpcode())
2839 NumberOfIgnoredLowBits, BiggerPattern);
2848 unsigned NOpc =
N->getMachineOpcode();
2852 case AArch64::SBFMWri:
2853 case AArch64::UBFMWri:
2854 case AArch64::SBFMXri:
2855 case AArch64::UBFMXri:
2857 Opd0 =
N->getOperand(0);
2858 Immr =
N->getConstantOperandVal(1);
2859 Imms =
N->getConstantOperandVal(2);
2866bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2867 unsigned Opc, Immr, Imms;
2872 EVT VT =
N->getValueType(0);
2877 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2878 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2879 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2881 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2882 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2888 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2889 CurDAG->getTargetConstant(Imms, dl, VT)};
2890 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2899 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2900 assert((VT == MVT::i32 || VT == MVT::i64) &&
2901 "i32 or i64 mask type expected!");
2905 APInt SignificantDstMask =
2909 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2910 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2943 APInt OpUsefulBits(UsefulBits);
2947 OpUsefulBits <<= MSB - Imm + 1;
2952 OpUsefulBits <<= Imm;
2954 OpUsefulBits <<= MSB + 1;
2957 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2963 UsefulBits &= OpUsefulBits;
2980 APInt Mask(UsefulBits);
2981 Mask.clearAllBits();
2989 Mask.lshrInPlace(ShiftAmt);
2995 Mask.lshrInPlace(ShiftAmt);
3011 APInt OpUsefulBits(UsefulBits);
3025 OpUsefulBits <<= Width;
3028 if (
Op.getOperand(1) == Orig) {
3030 Mask = ResultUsefulBits & OpUsefulBits;
3034 if (
Op.getOperand(0) == Orig)
3036 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3042 OpUsefulBits <<= Width;
3044 OpUsefulBits <<= LSB;
3046 if (
Op.getOperand(1) == Orig) {
3048 Mask = ResultUsefulBits & OpUsefulBits;
3049 Mask.lshrInPlace(LSB);
3052 if (
Op.getOperand(0) == Orig)
3053 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3070 case AArch64::ANDSWri:
3071 case AArch64::ANDSXri:
3072 case AArch64::ANDWri:
3073 case AArch64::ANDXri:
3077 case AArch64::UBFMWri:
3078 case AArch64::UBFMXri:
3081 case AArch64::ORRWrs:
3082 case AArch64::ORRXrs:
3087 case AArch64::BFMWri:
3088 case AArch64::BFMXri:
3091 case AArch64::STRBBui:
3092 case AArch64::STURBBi:
3098 case AArch64::STRHHui:
3099 case AArch64::STURHHi:
3112 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3114 UsefulBits =
APInt(Bitwidth, 0);
3123 UsersUsefulBits |= UsefulBitsForUse;
3128 UsefulBits &= UsersUsefulBits;
3138 EVT VT =
Op.getValueType();
3141 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3144 if (ShlAmount > 0) {
3147 UBFMOpc, dl, VT,
Op,
3152 assert(ShlAmount < 0 &&
"expected right shift");
3153 int ShrAmount = -ShlAmount;
3165 const uint64_t NonZeroBits,
3172 const uint64_t NonZeroBits,
3179 bool BiggerPattern,
SDValue &Src,
3180 int &DstLSB,
int &Width) {
3181 EVT VT =
Op.getValueType();
3190 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3194 switch (
Op.getOpcode()) {
3199 NonZeroBits, Src, DstLSB, Width);
3202 NonZeroBits, Src, DstLSB, Width);
3215 EVT VT =
Op.getValueType();
3216 assert((VT == MVT::i32 || VT == MVT::i64) &&
3217 "Caller guarantees VT is one of i32 or i64");
3230 assert((~AndImm & NonZeroBits) == 0 &&
3231 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3260 if (!BiggerPattern && !AndOp0.
hasOneUse())
3279 <<
"Found large Width in bit-field-positioning -- this indicates no "
3280 "proper combining / constant folding was performed\n");
3289 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3304 "Op.getNode() should be a SHL node to call this function");
3306 "Op.getNode() should shift ShlImm to call this function");
3313 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3337 EVT VT =
Op.getValueType();
3338 assert((VT == MVT::i32 || VT == MVT::i64) &&
3339 "Caller guarantees that type is i32 or i64");
3346 if (!BiggerPattern && !
Op.hasOneUse())
3355 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3363 assert(VT == MVT::i32 || VT == MVT::i64);
3374 EVT VT =
N->getValueType(0);
3375 if (VT != MVT::i32 && VT != MVT::i64)
3393 if (!
And.hasOneUse() ||
3403 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3410 if ((OrImm & NotKnownZero) != 0) {
3422 unsigned ImmS = Width - 1;
3428 bool IsBFI = LSB != 0;
3433 unsigned OrChunks = 0, BFIChunks = 0;
3434 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3435 if (((OrImm >> Shift) & 0xFFFF) != 0)
3437 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3440 if (BFIChunks > OrChunks)
3446 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3454 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3463 if (!Dst.hasOneUse())
3466 EVT VT = Dst.getValueType();
3467 assert((VT == MVT::i32 || VT == MVT::i64) &&
3468 "Caller should guarantee that VT is one of i32 or i64");
3496 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3497 unsigned MaskWidth =
3500 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3506 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3507 ShiftedOperand =
SDValue(UBFMNode, 0);
3536 const bool BiggerPattern) {
3537 EVT VT =
N->getValueType(0);
3538 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3539 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3540 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3541 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3542 assert((VT == MVT::i32 || VT == MVT::i64) &&
3543 "Expect result type to be i32 or i64 since N is combinable to BFM");
3550 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3553 if (BiggerPattern) {
3576 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3638 EVT VT =
N->getValueType(0);
3639 if (VT != MVT::i32 && VT != MVT::i64)
3647 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3648 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3668 for (
int I = 0;
I < 4; ++
I) {
3671 unsigned ImmR, ImmS;
3672 bool BiggerPattern =
I / 2;
3673 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3675 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3681 NumberOfIgnoredLowBits, BiggerPattern)) {
3684 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3685 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3690 Width = ImmS - ImmR + 1;
3701 Src, DstLSB, Width)) {
3709 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3719 APInt BitsToBeInserted =
3722 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3746 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3779 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3781 if (Src->hasOneUse() &&
3784 Src = Src->getOperand(0);
3794 unsigned ImmS = Width - 1;
3800 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3808bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3817 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3830bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3834 EVT VT =
N->getValueType(0);
3835 if (VT != MVT::i32 && VT != MVT::i64)
3841 Op0, DstLSB, Width))
3847 unsigned ImmS = Width - 1;
3850 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3851 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3852 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3853 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3859bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3860 EVT VT =
N->getValueType(0);
3863 switch (
N->getOpcode()) {
3865 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3868 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3871 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3874 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3882 if (VT == MVT::i32) {
3885 }
else if (VT == MVT::i64) {
3891 SDValue ShiftAmt =
N->getOperand(1);
3911 (Add0Imm %
Size == 0)) {
3917 if (SubVT == MVT::i32) {
3918 NegOpc = AArch64::SUBWrr;
3919 ZeroReg = AArch64::WZR;
3921 assert(SubVT == MVT::i64);
3922 NegOpc = AArch64::SUBXrr;
3923 ZeroReg = AArch64::XZR;
3926 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3927 MachineSDNode *Neg =
3928 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3929 NewShiftAmt =
SDValue(Neg, 0);
3937 if (SubVT == MVT::i32) {
3938 NotOpc = AArch64::ORNWrr;
3939 ZeroReg = AArch64::WZR;
3941 assert(SubVT == MVT::i64);
3942 NotOpc = AArch64::ORNXrr;
3943 ZeroReg = AArch64::XZR;
3946 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3947 MachineSDNode *
Not =
3948 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3949 NewShiftAmt =
SDValue(Not, 0);
3970 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3971 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3972 MachineSDNode *Ext = CurDAG->getMachineNode(
3973 AArch64::SUBREG_TO_REG,
DL, VT,
3974 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3975 NewShiftAmt =
SDValue(Ext, 0);
3979 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3986 bool isReciprocal) {
3989 FVal = CN->getValueAPF();
3992 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4021 if (!IsExact || !IntVal.isPowerOf2())
4023 unsigned FBits = IntVal.logBase2();
4027 if (FBits == 0 || FBits > RegWidth)
return false;
4033bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4034 unsigned RegWidth) {
4039bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4041 unsigned RegWidth) {
4051 RegString.
split(Fields,
':');
4053 if (Fields.
size() == 1)
4057 &&
"Invalid number of fields in read register string");
4060 bool AllIntFields =
true;
4064 AllIntFields &= !
Field.getAsInteger(10, IntField);
4065 Ops.push_back(IntField);
4069 "Unexpected non-integer value in special register string.");
4074 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4075 (
Ops[3] << 3) | (
Ops[4]);
4082bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4084 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4087 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4089 unsigned Opcode64Bit = AArch64::MRS;
4094 const auto *TheReg =
4095 AArch64SysReg::lookupSysRegByName(RegString->getString());
4096 if (TheReg && TheReg->Readable &&
4097 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4098 Imm = TheReg->Encoding;
4104 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4105 Opcode64Bit = AArch64::ADR;
4113 SDValue InChain =
N->getOperand(0);
4114 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4115 if (!ReadIs128Bit) {
4116 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4117 {SysRegImm, InChain});
4119 SDNode *MRRS = CurDAG->getMachineNode(
4121 {MVT::Untyped , MVT::Other },
4122 {SysRegImm, InChain});
4126 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4128 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4134 ReplaceUses(
SDValue(
N, 2), OutChain);
4143bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4145 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4148 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4150 if (!WriteIs128Bit) {
4156 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4159 "Expected a constant integer expression.");
4160 unsigned Reg = PMapper->Encoding;
4161 uint64_t Immed =
N->getConstantOperandVal(2);
4162 CurDAG->SelectNodeTo(
4163 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4164 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4170 if (trySelectPState(
4171 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4172 AArch64::MSRpstateImm4))
4174 if (trySelectPState(
4175 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4176 AArch64::MSRpstateImm1))
4185 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4186 if (TheReg && TheReg->Writeable &&
4187 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4188 Imm = TheReg->Encoding;
4197 if (!WriteIs128Bit) {
4198 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4199 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4200 N->getOperand(2), InChain);
4204 SDNode *Pair = CurDAG->getMachineNode(
4205 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4206 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4209 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4211 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4213 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4214 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4222bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4227 if (Subtarget->hasLSE())
return false;
4229 if (MemTy == MVT::i8)
4230 Opcode = AArch64::CMP_SWAP_8;
4231 else if (MemTy == MVT::i16)
4232 Opcode = AArch64::CMP_SWAP_16;
4233 else if (MemTy == MVT::i32)
4234 Opcode = AArch64::CMP_SWAP_32;
4235 else if (MemTy == MVT::i64)
4236 Opcode = AArch64::CMP_SWAP_64;
4240 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4241 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4243 SDNode *CmpSwap = CurDAG->getMachineNode(
4245 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4252 CurDAG->RemoveDeadNode(
N);
4257bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4258 SDValue &Shift,
bool Negate) {
4272 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4279 if ((Val & ~0xff) == 0) {
4280 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4285 if ((Val & ~0xff00) == 0) {
4286 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4298bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4322 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4323 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4330 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4331 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4335 if (Val <= 65280 && Val % 256 == 0) {
4336 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4337 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4348bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4358 int32_t ImmVal, ShiftVal;
4363 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4364 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4368bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4370 int64_t ImmVal = CNode->getSExtValue();
4372 if (ImmVal >= -128 && ImmVal < 128) {
4373 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4380bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4382 uint64_t ImmVal = CNode->getZExtValue();
4392 ImmVal &= 0xFFFFFFFF;
4401 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4408bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4412 ImmVal = CI->getZExtValue();
4414 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4425 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4434bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4435 uint64_t
High,
bool AllowSaturation,
4438 uint64_t ImmVal = CN->getZExtValue();
4445 if (ImmVal >
High) {
4446 if (!AllowSaturation)
4451 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4458bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4472 const TargetLowering *TLI = getTargetLowering();
4475 SDValue FiOp = CurDAG->getTargetFrameIndex(
4477 int TagOffset =
N->getConstantOperandVal(3);
4479 SDNode *Out = CurDAG->getMachineNode(
4480 AArch64::TAGPstack,
DL, MVT::i64,
4481 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4482 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4483 ReplaceNode(
N, Out);
4487void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4489 "llvm.aarch64.tagp third argument must be an immediate");
4490 if (trySelectStackSlotTagP(
N))
4497 int TagOffset =
N->getConstantOperandVal(3);
4498 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4499 {
N->getOperand(1),
N->getOperand(2)});
4500 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4501 {
SDValue(N1, 0),
N->getOperand(2)});
4502 SDNode *N3 = CurDAG->getMachineNode(
4503 AArch64::ADDG,
DL, MVT::i64,
4504 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4505 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4509bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4513 if (
N->getConstantOperandVal(2) != 0)
4515 if (!
N->getOperand(0).isUndef())
4519 EVT VT =
N->getValueType(0);
4520 EVT InVT =
N->getOperand(1).getValueType();
4531 "Expected to insert into a packed scalable vector!");
4534 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4535 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4536 N->getOperand(1), RC));
4540bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4544 if (
N->getConstantOperandVal(1) != 0)
4548 EVT VT =
N->getValueType(0);
4549 EVT InVT =
N->getOperand(0).getValueType();
4560 "Expected to extract from a packed scalable vector!");
4563 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4564 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4565 N->getOperand(0), RC));
4569bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4575 EVT VT =
N->getValueType(0);
4588 (Subtarget->hasSVE2() ||
4589 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4590 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4593 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4597 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4598 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4599 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4606 bool IsXOROperand =
true;
4608 IsXOROperand =
false;
4614 APInt ShlAmt, ShrAmt;
4622 if (!IsXOROperand) {
4624 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4627 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4628 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4629 VT, Zero, MOVIV, ZSub);
4640 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4641 AArch64::XAR_ZZZI_D})) {
4642 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4667 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4677 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4685 bool IsXOROperand =
true;
4687 IsXOROperand =
false;
4690 R1 =
XOR.getOperand(0);
4691 R2 =
XOR.getOperand(1);
4701 if (ShAmt + HsAmt != VTSizeInBits)
4704 if (!IsXOROperand) {
4707 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4716 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4722 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4723 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4725 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4728 if (
R2.getValueType() == VT)
4729 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4737 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4742 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4748 SDNode *XAR =
nullptr;
4752 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4753 AArch64::XAR_ZZZI_D}))
4754 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4756 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4759 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4765 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4766 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4769 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4770 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4776 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4780 ReplaceNode(
N, XAR);
4784void AArch64DAGToDAGISel::Select(SDNode *Node) {
4786 if (
Node->isMachineOpcode()) {
4788 Node->setNodeId(-1);
4793 EVT VT =
Node->getValueType(0);
4795 switch (
Node->getOpcode()) {
4800 if (SelectCMP_SWAP(Node))
4805 case AArch64ISD::MRRS:
4806 if (tryReadRegister(Node))
4811 case AArch64ISD::MSRR:
4812 if (tryWriteRegister(Node))
4819 if (tryIndexedLoad(Node))
4828 if (tryBitfieldExtractOp(Node))
4830 if (tryBitfieldInsertInZeroOp(Node))
4835 if (tryShiftAmountMod(Node))
4840 if (tryBitfieldExtractOpFromSExt(Node))
4845 if (tryBitfieldInsertOp(Node))
4847 if (trySelectXAR(Node))
4852 if (trySelectCastScalableToFixedLengthVector(Node))
4858 if (trySelectCastFixedLengthToScalableVector(Node))
4867 if (ConstNode->
isZero()) {
4868 if (VT == MVT::i32) {
4870 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4871 ReplaceNode(Node,
New.getNode());
4873 }
else if (VT == MVT::i64) {
4875 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4876 ReplaceNode(Node,
New.getNode());
4887 const TargetLowering *TLI = getTargetLowering();
4888 SDValue TFI = CurDAG->getTargetFrameIndex(
4891 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4892 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4893 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4897 unsigned IntNo =
Node->getConstantOperandVal(1);
4901 case Intrinsic::aarch64_gcsss: {
4905 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4907 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4908 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4909 MVT::Other, Zero,
SDValue(SS1, 0));
4910 ReplaceNode(Node, SS2);
4913 case Intrinsic::aarch64_ldaxp:
4914 case Intrinsic::aarch64_ldxp: {
4916 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4921 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4922 MVT::Other, MemAddr, Chain);
4925 MachineMemOperand *MemOp =
4928 ReplaceNode(Node, Ld);
4931 case Intrinsic::aarch64_stlxp:
4932 case Intrinsic::aarch64_stxp: {
4934 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4942 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4944 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4946 MachineMemOperand *MemOp =
4950 ReplaceNode(Node, St);
4953 case Intrinsic::aarch64_neon_ld1x2:
4954 if (VT == MVT::v8i8) {
4955 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4957 }
else if (VT == MVT::v16i8) {
4958 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4960 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4961 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4963 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4964 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4966 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4967 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4969 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4970 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4972 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4973 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4975 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4976 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
4980 case Intrinsic::aarch64_neon_ld1x3:
4981 if (VT == MVT::v8i8) {
4982 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
4984 }
else if (VT == MVT::v16i8) {
4985 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
4987 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4988 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
4990 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4991 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
4993 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4994 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
4996 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4997 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
4999 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5000 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5002 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5003 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5007 case Intrinsic::aarch64_neon_ld1x4:
5008 if (VT == MVT::v8i8) {
5009 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5011 }
else if (VT == MVT::v16i8) {
5012 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5014 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5015 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5017 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5018 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5020 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5021 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5023 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5024 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5026 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5027 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5029 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5030 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5034 case Intrinsic::aarch64_neon_ld2:
5035 if (VT == MVT::v8i8) {
5036 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5038 }
else if (VT == MVT::v16i8) {
5039 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5041 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5042 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5044 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5045 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5047 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5048 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5050 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5051 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5053 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5054 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5056 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5057 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5061 case Intrinsic::aarch64_neon_ld3:
5062 if (VT == MVT::v8i8) {
5063 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5065 }
else if (VT == MVT::v16i8) {
5066 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5068 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5069 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5071 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5072 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5074 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5075 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5077 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5078 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5080 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5081 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5083 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5084 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5088 case Intrinsic::aarch64_neon_ld4:
5089 if (VT == MVT::v8i8) {
5090 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5092 }
else if (VT == MVT::v16i8) {
5093 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5095 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5096 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5098 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5099 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5101 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5102 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5104 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5105 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5107 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5108 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5110 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5111 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5115 case Intrinsic::aarch64_neon_ld2r:
5116 if (VT == MVT::v8i8) {
5117 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5119 }
else if (VT == MVT::v16i8) {
5120 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5122 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5123 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5125 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5126 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5128 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5129 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5131 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5132 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5134 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5135 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5137 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5138 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5142 case Intrinsic::aarch64_neon_ld3r:
5143 if (VT == MVT::v8i8) {
5144 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5146 }
else if (VT == MVT::v16i8) {
5147 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5149 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5150 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5152 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5153 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5155 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5156 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5158 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5159 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5161 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5162 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5164 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5165 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5169 case Intrinsic::aarch64_neon_ld4r:
5170 if (VT == MVT::v8i8) {
5171 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5173 }
else if (VT == MVT::v16i8) {
5174 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5176 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5177 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5179 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5180 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5182 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5183 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5185 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5186 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5188 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5189 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5191 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5192 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5196 case Intrinsic::aarch64_neon_ld2lane:
5197 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5198 SelectLoadLane(Node, 2, AArch64::LD2i8);
5200 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5201 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5202 SelectLoadLane(Node, 2, AArch64::LD2i16);
5204 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5206 SelectLoadLane(Node, 2, AArch64::LD2i32);
5208 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5210 SelectLoadLane(Node, 2, AArch64::LD2i64);
5214 case Intrinsic::aarch64_neon_ld3lane:
5215 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5216 SelectLoadLane(Node, 3, AArch64::LD3i8);
5218 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5219 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5220 SelectLoadLane(Node, 3, AArch64::LD3i16);
5222 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5224 SelectLoadLane(Node, 3, AArch64::LD3i32);
5226 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5228 SelectLoadLane(Node, 3, AArch64::LD3i64);
5232 case Intrinsic::aarch64_neon_ld4lane:
5233 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5234 SelectLoadLane(Node, 4, AArch64::LD4i8);
5236 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5237 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5238 SelectLoadLane(Node, 4, AArch64::LD4i16);
5240 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5242 SelectLoadLane(Node, 4, AArch64::LD4i32);
5244 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5246 SelectLoadLane(Node, 4, AArch64::LD4i64);
5250 case Intrinsic::aarch64_ld64b:
5251 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5253 case Intrinsic::aarch64_sve_ld2q_sret: {
5254 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5257 case Intrinsic::aarch64_sve_ld3q_sret: {
5258 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5261 case Intrinsic::aarch64_sve_ld4q_sret: {
5262 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5265 case Intrinsic::aarch64_sve_ld2_sret: {
5266 if (VT == MVT::nxv16i8) {
5267 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5270 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5271 VT == MVT::nxv8bf16) {
5272 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5275 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5276 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5279 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5280 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5286 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5287 if (VT == MVT::nxv16i8) {
5288 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5289 SelectContiguousMultiVectorLoad(
5290 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5291 else if (Subtarget->hasSVE2p1())
5292 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5297 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5298 VT == MVT::nxv8bf16) {
5299 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5300 SelectContiguousMultiVectorLoad(
5301 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5302 else if (Subtarget->hasSVE2p1())
5303 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5308 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5309 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5310 SelectContiguousMultiVectorLoad(
5311 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5312 else if (Subtarget->hasSVE2p1())
5313 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5318 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5319 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5320 SelectContiguousMultiVectorLoad(
5321 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5322 else if (Subtarget->hasSVE2p1())
5323 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5331 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5332 if (VT == MVT::nxv16i8) {
5333 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5334 SelectContiguousMultiVectorLoad(
5335 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5336 else if (Subtarget->hasSVE2p1())
5337 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5342 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5343 VT == MVT::nxv8bf16) {
5344 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5345 SelectContiguousMultiVectorLoad(
5346 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5347 else if (Subtarget->hasSVE2p1())
5348 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5353 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5354 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5355 SelectContiguousMultiVectorLoad(
5356 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5357 else if (Subtarget->hasSVE2p1())
5358 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5363 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5364 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5365 SelectContiguousMultiVectorLoad(
5366 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5367 else if (Subtarget->hasSVE2p1())
5368 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5376 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5377 if (VT == MVT::nxv16i8) {
5378 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5379 SelectContiguousMultiVectorLoad(Node, 2, 0,
5380 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5381 AArch64::LDNT1B_2Z_PSEUDO);
5382 else if (Subtarget->hasSVE2p1())
5383 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5384 AArch64::LDNT1B_2Z);
5388 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5389 VT == MVT::nxv8bf16) {
5390 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5391 SelectContiguousMultiVectorLoad(Node, 2, 1,
5392 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5393 AArch64::LDNT1H_2Z_PSEUDO);
5394 else if (Subtarget->hasSVE2p1())
5395 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5396 AArch64::LDNT1H_2Z);
5400 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5401 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5402 SelectContiguousMultiVectorLoad(Node, 2, 2,
5403 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5404 AArch64::LDNT1W_2Z_PSEUDO);
5405 else if (Subtarget->hasSVE2p1())
5406 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5407 AArch64::LDNT1W_2Z);
5411 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5412 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5413 SelectContiguousMultiVectorLoad(Node, 2, 3,
5414 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5415 AArch64::LDNT1D_2Z_PSEUDO);
5416 else if (Subtarget->hasSVE2p1())
5417 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5418 AArch64::LDNT1D_2Z);
5425 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5426 if (VT == MVT::nxv16i8) {
5427 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5428 SelectContiguousMultiVectorLoad(Node, 4, 0,
5429 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5430 AArch64::LDNT1B_4Z_PSEUDO);
5431 else if (Subtarget->hasSVE2p1())
5432 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5433 AArch64::LDNT1B_4Z);
5437 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5438 VT == MVT::nxv8bf16) {
5439 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5440 SelectContiguousMultiVectorLoad(Node, 4, 1,
5441 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5442 AArch64::LDNT1H_4Z_PSEUDO);
5443 else if (Subtarget->hasSVE2p1())
5444 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5445 AArch64::LDNT1H_4Z);
5449 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5450 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5451 SelectContiguousMultiVectorLoad(Node, 4, 2,
5452 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5453 AArch64::LDNT1W_4Z_PSEUDO);
5454 else if (Subtarget->hasSVE2p1())
5455 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5456 AArch64::LDNT1W_4Z);
5460 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5461 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5462 SelectContiguousMultiVectorLoad(Node, 4, 3,
5463 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5464 AArch64::LDNT1D_4Z_PSEUDO);
5465 else if (Subtarget->hasSVE2p1())
5466 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5467 AArch64::LDNT1D_4Z);
5474 case Intrinsic::aarch64_sve_ld3_sret: {
5475 if (VT == MVT::nxv16i8) {
5476 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5479 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5480 VT == MVT::nxv8bf16) {
5481 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5484 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5485 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5488 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5489 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5495 case Intrinsic::aarch64_sve_ld4_sret: {
5496 if (VT == MVT::nxv16i8) {
5497 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5500 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5501 VT == MVT::nxv8bf16) {
5502 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5505 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5506 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5509 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5510 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5516 case Intrinsic::aarch64_sme_read_hor_vg2: {
5517 if (VT == MVT::nxv16i8) {
5518 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5519 AArch64::MOVA_2ZMXI_H_B);
5521 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5522 VT == MVT::nxv8bf16) {
5523 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5524 AArch64::MOVA_2ZMXI_H_H);
5526 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5527 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5528 AArch64::MOVA_2ZMXI_H_S);
5530 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5531 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5532 AArch64::MOVA_2ZMXI_H_D);
5537 case Intrinsic::aarch64_sme_read_ver_vg2: {
5538 if (VT == MVT::nxv16i8) {
5539 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5540 AArch64::MOVA_2ZMXI_V_B);
5542 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5543 VT == MVT::nxv8bf16) {
5544 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5545 AArch64::MOVA_2ZMXI_V_H);
5547 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5548 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5549 AArch64::MOVA_2ZMXI_V_S);
5551 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5552 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5553 AArch64::MOVA_2ZMXI_V_D);
5558 case Intrinsic::aarch64_sme_read_hor_vg4: {
5559 if (VT == MVT::nxv16i8) {
5560 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5561 AArch64::MOVA_4ZMXI_H_B);
5563 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5564 VT == MVT::nxv8bf16) {
5565 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5566 AArch64::MOVA_4ZMXI_H_H);
5568 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5569 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5570 AArch64::MOVA_4ZMXI_H_S);
5572 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5573 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5574 AArch64::MOVA_4ZMXI_H_D);
5579 case Intrinsic::aarch64_sme_read_ver_vg4: {
5580 if (VT == MVT::nxv16i8) {
5581 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5582 AArch64::MOVA_4ZMXI_V_B);
5584 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5585 VT == MVT::nxv8bf16) {
5586 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5587 AArch64::MOVA_4ZMXI_V_H);
5589 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5590 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5591 AArch64::MOVA_4ZMXI_V_S);
5593 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5594 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5595 AArch64::MOVA_4ZMXI_V_D);
5600 case Intrinsic::aarch64_sme_read_vg1x2: {
5601 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5602 AArch64::MOVA_VG2_2ZMXI);
5605 case Intrinsic::aarch64_sme_read_vg1x4: {
5606 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5607 AArch64::MOVA_VG4_4ZMXI);
5610 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5611 if (VT == MVT::nxv16i8) {
5612 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5614 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5615 VT == MVT::nxv8bf16) {
5616 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5618 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5619 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5621 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5622 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5627 case Intrinsic::aarch64_sme_readz_vert_x2: {
5628 if (VT == MVT::nxv16i8) {
5629 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5631 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5632 VT == MVT::nxv8bf16) {
5633 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5635 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5636 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5638 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5639 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5644 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5645 if (VT == MVT::nxv16i8) {
5646 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5648 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5649 VT == MVT::nxv8bf16) {
5650 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5652 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5653 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5655 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5656 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5661 case Intrinsic::aarch64_sme_readz_vert_x4: {
5662 if (VT == MVT::nxv16i8) {
5663 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5665 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5666 VT == MVT::nxv8bf16) {
5667 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5669 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5670 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5672 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5673 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5678 case Intrinsic::aarch64_sme_readz_x2: {
5679 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5683 case Intrinsic::aarch64_sme_readz_x4: {
5684 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5688 case Intrinsic::swift_async_context_addr: {
5691 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5693 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5694 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5695 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5697 ReplaceUses(
SDValue(Node, 0), Res);
5699 CurDAG->RemoveDeadNode(Node);
5701 auto &MF = CurDAG->getMachineFunction();
5702 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5703 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5706 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5708 Node->getValueType(0),
5709 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5710 AArch64::LUTI2_4ZTZI_S}))
5712 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5715 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5717 Node->getValueType(0),
5718 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5720 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5723 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5725 Node->getValueType(0),
5726 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5727 AArch64::LUTI2_2ZTZI_S}))
5729 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5732 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5734 Node->getValueType(0),
5735 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5736 AArch64::LUTI4_2ZTZI_S}))
5738 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5741 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5742 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5745 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5747 Node->getValueType(0),
5748 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5749 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5751 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5753 Node->getValueType(0),
5754 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5755 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5757 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5759 Node->getValueType(0),
5760 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5761 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5763 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5765 Node->getValueType(0),
5766 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5767 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5772 unsigned IntNo =
Node->getConstantOperandVal(0);
5776 case Intrinsic::aarch64_tagp:
5780 case Intrinsic::ptrauth_auth:
5781 SelectPtrauthAuth(Node);
5784 case Intrinsic::ptrauth_resign:
5785 SelectPtrauthResign(Node);
5788 case Intrinsic::aarch64_neon_tbl2:
5789 SelectTable(Node, 2,
5790 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5793 case Intrinsic::aarch64_neon_tbl3:
5794 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5795 : AArch64::TBLv16i8Three,
5798 case Intrinsic::aarch64_neon_tbl4:
5799 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5800 : AArch64::TBLv16i8Four,
5803 case Intrinsic::aarch64_neon_tbx2:
5804 SelectTable(Node, 2,
5805 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5808 case Intrinsic::aarch64_neon_tbx3:
5809 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5810 : AArch64::TBXv16i8Three,
5813 case Intrinsic::aarch64_neon_tbx4:
5814 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5815 : AArch64::TBXv16i8Four,
5818 case Intrinsic::aarch64_sve_srshl_single_x2:
5820 Node->getValueType(0),
5821 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5822 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5823 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5825 case Intrinsic::aarch64_sve_srshl_single_x4:
5827 Node->getValueType(0),
5828 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5829 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5830 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5832 case Intrinsic::aarch64_sve_urshl_single_x2:
5834 Node->getValueType(0),
5835 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5836 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5837 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5839 case Intrinsic::aarch64_sve_urshl_single_x4:
5841 Node->getValueType(0),
5842 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5843 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5844 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5846 case Intrinsic::aarch64_sve_srshl_x2:
5848 Node->getValueType(0),
5849 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5850 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5851 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5853 case Intrinsic::aarch64_sve_srshl_x4:
5855 Node->getValueType(0),
5856 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5857 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5858 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5860 case Intrinsic::aarch64_sve_urshl_x2:
5862 Node->getValueType(0),
5863 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5864 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5865 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5867 case Intrinsic::aarch64_sve_urshl_x4:
5869 Node->getValueType(0),
5870 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5871 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5872 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5874 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5876 Node->getValueType(0),
5877 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5878 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5879 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5881 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5883 Node->getValueType(0),
5884 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5885 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5886 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5888 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5890 Node->getValueType(0),
5891 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5892 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5893 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5895 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5897 Node->getValueType(0),
5898 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5899 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5900 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5902 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5904 Node->getValueType(0),
5905 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5906 AArch64::FSCALE_2ZZ_D}))
5907 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5909 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5911 Node->getValueType(0),
5912 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5913 AArch64::FSCALE_4ZZ_D}))
5914 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5916 case Intrinsic::aarch64_sme_fp8_scale_x2:
5918 Node->getValueType(0),
5919 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5920 AArch64::FSCALE_2Z2Z_D}))
5921 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5923 case Intrinsic::aarch64_sme_fp8_scale_x4:
5925 Node->getValueType(0),
5926 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5927 AArch64::FSCALE_4Z4Z_D}))
5928 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5930 case Intrinsic::aarch64_sve_whilege_x2:
5932 Node->getValueType(0),
5933 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5934 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5935 SelectWhilePair(Node,
Op);
5937 case Intrinsic::aarch64_sve_whilegt_x2:
5939 Node->getValueType(0),
5940 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5941 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5942 SelectWhilePair(Node,
Op);
5944 case Intrinsic::aarch64_sve_whilehi_x2:
5946 Node->getValueType(0),
5947 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5948 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5949 SelectWhilePair(Node,
Op);
5951 case Intrinsic::aarch64_sve_whilehs_x2:
5953 Node->getValueType(0),
5954 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5955 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5956 SelectWhilePair(Node,
Op);
5958 case Intrinsic::aarch64_sve_whilele_x2:
5960 Node->getValueType(0),
5961 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5962 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5963 SelectWhilePair(Node,
Op);
5965 case Intrinsic::aarch64_sve_whilelo_x2:
5967 Node->getValueType(0),
5968 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5969 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5970 SelectWhilePair(Node,
Op);
5972 case Intrinsic::aarch64_sve_whilels_x2:
5974 Node->getValueType(0),
5975 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5976 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5977 SelectWhilePair(Node,
Op);
5979 case Intrinsic::aarch64_sve_whilelt_x2:
5981 Node->getValueType(0),
5982 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
5983 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
5984 SelectWhilePair(Node,
Op);
5986 case Intrinsic::aarch64_sve_smax_single_x2:
5988 Node->getValueType(0),
5989 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
5990 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
5991 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5993 case Intrinsic::aarch64_sve_umax_single_x2:
5995 Node->getValueType(0),
5996 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
5997 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
5998 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6000 case Intrinsic::aarch64_sve_fmax_single_x2:
6002 Node->getValueType(0),
6003 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6004 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6005 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6007 case Intrinsic::aarch64_sve_smax_single_x4:
6009 Node->getValueType(0),
6010 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6011 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6012 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6014 case Intrinsic::aarch64_sve_umax_single_x4:
6016 Node->getValueType(0),
6017 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6018 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6019 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6021 case Intrinsic::aarch64_sve_fmax_single_x4:
6023 Node->getValueType(0),
6024 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6025 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6026 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6028 case Intrinsic::aarch64_sve_smin_single_x2:
6030 Node->getValueType(0),
6031 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6032 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6033 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6035 case Intrinsic::aarch64_sve_umin_single_x2:
6037 Node->getValueType(0),
6038 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6039 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6040 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6042 case Intrinsic::aarch64_sve_fmin_single_x2:
6044 Node->getValueType(0),
6045 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6046 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6047 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6049 case Intrinsic::aarch64_sve_smin_single_x4:
6051 Node->getValueType(0),
6052 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6053 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6054 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6056 case Intrinsic::aarch64_sve_umin_single_x4:
6058 Node->getValueType(0),
6059 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6060 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6061 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6063 case Intrinsic::aarch64_sve_fmin_single_x4:
6065 Node->getValueType(0),
6066 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6067 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6068 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6070 case Intrinsic::aarch64_sve_smax_x2:
6072 Node->getValueType(0),
6073 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6074 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6075 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6077 case Intrinsic::aarch64_sve_umax_x2:
6079 Node->getValueType(0),
6080 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6081 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6082 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6084 case Intrinsic::aarch64_sve_fmax_x2:
6086 Node->getValueType(0),
6087 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6088 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6089 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6091 case Intrinsic::aarch64_sve_smax_x4:
6093 Node->getValueType(0),
6094 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6095 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6096 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6098 case Intrinsic::aarch64_sve_umax_x4:
6100 Node->getValueType(0),
6101 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6102 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6103 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6105 case Intrinsic::aarch64_sve_fmax_x4:
6107 Node->getValueType(0),
6108 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6109 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6110 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6112 case Intrinsic::aarch64_sme_famax_x2:
6114 Node->getValueType(0),
6115 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6116 AArch64::FAMAX_2Z2Z_D}))
6117 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6119 case Intrinsic::aarch64_sme_famax_x4:
6121 Node->getValueType(0),
6122 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6123 AArch64::FAMAX_4Z4Z_D}))
6124 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6126 case Intrinsic::aarch64_sme_famin_x2:
6128 Node->getValueType(0),
6129 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6130 AArch64::FAMIN_2Z2Z_D}))
6131 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6133 case Intrinsic::aarch64_sme_famin_x4:
6135 Node->getValueType(0),
6136 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6137 AArch64::FAMIN_4Z4Z_D}))
6138 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6140 case Intrinsic::aarch64_sve_smin_x2:
6142 Node->getValueType(0),
6143 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6144 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6145 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6147 case Intrinsic::aarch64_sve_umin_x2:
6149 Node->getValueType(0),
6150 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6151 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6152 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6154 case Intrinsic::aarch64_sve_fmin_x2:
6156 Node->getValueType(0),
6157 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6158 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6159 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6161 case Intrinsic::aarch64_sve_smin_x4:
6163 Node->getValueType(0),
6164 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6165 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6166 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6168 case Intrinsic::aarch64_sve_umin_x4:
6170 Node->getValueType(0),
6171 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6172 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6173 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6175 case Intrinsic::aarch64_sve_fmin_x4:
6177 Node->getValueType(0),
6178 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6179 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6180 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6182 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6184 Node->getValueType(0),
6185 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6186 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6187 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6189 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6191 Node->getValueType(0),
6192 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6193 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6194 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6196 case Intrinsic::aarch64_sve_fminnm_single_x2:
6198 Node->getValueType(0),
6199 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6200 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6201 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6203 case Intrinsic::aarch64_sve_fminnm_single_x4:
6205 Node->getValueType(0),
6206 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6207 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6208 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6210 case Intrinsic::aarch64_sve_fscale_single_x4:
6211 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6213 case Intrinsic::aarch64_sve_fscale_single_x2:
6214 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6216 case Intrinsic::aarch64_sve_fmul_single_x4:
6218 Node->getValueType(0),
6219 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6220 AArch64::FMUL_4ZZ_D}))
6221 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6223 case Intrinsic::aarch64_sve_fmul_single_x2:
6225 Node->getValueType(0),
6226 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6227 AArch64::FMUL_2ZZ_D}))
6228 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6230 case Intrinsic::aarch64_sve_fmaxnm_x2:
6232 Node->getValueType(0),
6233 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6234 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6235 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6237 case Intrinsic::aarch64_sve_fmaxnm_x4:
6239 Node->getValueType(0),
6240 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6241 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6244 case Intrinsic::aarch64_sve_fminnm_x2:
6246 Node->getValueType(0),
6247 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6248 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6251 case Intrinsic::aarch64_sve_fminnm_x4:
6253 Node->getValueType(0),
6254 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6255 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6256 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6258 case Intrinsic::aarch64_sve_aese_lane_x2:
6259 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6261 case Intrinsic::aarch64_sve_aesd_lane_x2:
6262 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6264 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6265 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6267 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6268 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6270 case Intrinsic::aarch64_sve_aese_lane_x4:
6271 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6273 case Intrinsic::aarch64_sve_aesd_lane_x4:
6274 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6276 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6277 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6279 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6280 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6282 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6283 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6285 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6289 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6291 for (
unsigned I = 0;
I < 2;
I++)
6293 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6295 CurDAG->RemoveDeadNode(Node);
6298 case Intrinsic::aarch64_sve_fscale_x4:
6299 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6301 case Intrinsic::aarch64_sve_fscale_x2:
6302 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6304 case Intrinsic::aarch64_sve_fmul_x4:
6306 Node->getValueType(0),
6307 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6308 AArch64::FMUL_4Z4Z_D}))
6309 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6311 case Intrinsic::aarch64_sve_fmul_x2:
6313 Node->getValueType(0),
6314 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6315 AArch64::FMUL_2Z2Z_D}))
6316 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6318 case Intrinsic::aarch64_sve_fcvtzs_x2:
6319 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6321 case Intrinsic::aarch64_sve_scvtf_x2:
6322 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6324 case Intrinsic::aarch64_sve_fcvtzu_x2:
6325 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6327 case Intrinsic::aarch64_sve_ucvtf_x2:
6328 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6330 case Intrinsic::aarch64_sve_fcvtzs_x4:
6331 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6333 case Intrinsic::aarch64_sve_scvtf_x4:
6334 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6336 case Intrinsic::aarch64_sve_fcvtzu_x4:
6337 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6339 case Intrinsic::aarch64_sve_ucvtf_x4:
6340 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6342 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6343 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6345 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6346 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6348 case Intrinsic::aarch64_sve_sclamp_single_x2:
6350 Node->getValueType(0),
6351 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6352 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6353 SelectClamp(Node, 2,
Op);
6355 case Intrinsic::aarch64_sve_uclamp_single_x2:
6357 Node->getValueType(0),
6358 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6359 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6360 SelectClamp(Node, 2,
Op);
6362 case Intrinsic::aarch64_sve_fclamp_single_x2:
6364 Node->getValueType(0),
6365 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6366 AArch64::FCLAMP_VG2_2Z2Z_D}))
6367 SelectClamp(Node, 2,
Op);
6369 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6370 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6372 case Intrinsic::aarch64_sve_sclamp_single_x4:
6374 Node->getValueType(0),
6375 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6376 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6377 SelectClamp(Node, 4,
Op);
6379 case Intrinsic::aarch64_sve_uclamp_single_x4:
6381 Node->getValueType(0),
6382 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6383 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6384 SelectClamp(Node, 4,
Op);
6386 case Intrinsic::aarch64_sve_fclamp_single_x4:
6388 Node->getValueType(0),
6389 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6390 AArch64::FCLAMP_VG4_4Z4Z_D}))
6391 SelectClamp(Node, 4,
Op);
6393 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6394 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6396 case Intrinsic::aarch64_sve_add_single_x2:
6398 Node->getValueType(0),
6399 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6400 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6401 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6403 case Intrinsic::aarch64_sve_add_single_x4:
6405 Node->getValueType(0),
6406 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6407 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6408 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6410 case Intrinsic::aarch64_sve_zip_x2:
6412 Node->getValueType(0),
6413 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6414 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6415 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6417 case Intrinsic::aarch64_sve_zipq_x2:
6418 SelectUnaryMultiIntrinsic(Node, 2,
false,
6419 AArch64::ZIP_VG2_2ZZZ_Q);
6421 case Intrinsic::aarch64_sve_zip_x4:
6423 Node->getValueType(0),
6424 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6425 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6426 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6428 case Intrinsic::aarch64_sve_zipq_x4:
6429 SelectUnaryMultiIntrinsic(Node, 4,
true,
6430 AArch64::ZIP_VG4_4Z4Z_Q);
6432 case Intrinsic::aarch64_sve_uzp_x2:
6434 Node->getValueType(0),
6435 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6436 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6437 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6439 case Intrinsic::aarch64_sve_uzpq_x2:
6440 SelectUnaryMultiIntrinsic(Node, 2,
false,
6441 AArch64::UZP_VG2_2ZZZ_Q);
6443 case Intrinsic::aarch64_sve_uzp_x4:
6445 Node->getValueType(0),
6446 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6447 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6448 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6450 case Intrinsic::aarch64_sve_uzpq_x4:
6451 SelectUnaryMultiIntrinsic(Node, 4,
true,
6452 AArch64::UZP_VG4_4Z4Z_Q);
6454 case Intrinsic::aarch64_sve_sel_x2:
6456 Node->getValueType(0),
6457 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6458 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6459 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6461 case Intrinsic::aarch64_sve_sel_x4:
6463 Node->getValueType(0),
6464 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6465 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6466 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6468 case Intrinsic::aarch64_sve_frinta_x2:
6469 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6471 case Intrinsic::aarch64_sve_frinta_x4:
6472 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6474 case Intrinsic::aarch64_sve_frintm_x2:
6475 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6477 case Intrinsic::aarch64_sve_frintm_x4:
6478 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6480 case Intrinsic::aarch64_sve_frintn_x2:
6481 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6483 case Intrinsic::aarch64_sve_frintn_x4:
6484 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6486 case Intrinsic::aarch64_sve_frintp_x2:
6487 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6489 case Intrinsic::aarch64_sve_frintp_x4:
6490 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6492 case Intrinsic::aarch64_sve_sunpk_x2:
6494 Node->getValueType(0),
6495 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6496 AArch64::SUNPK_VG2_2ZZ_D}))
6497 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6499 case Intrinsic::aarch64_sve_uunpk_x2:
6501 Node->getValueType(0),
6502 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6503 AArch64::UUNPK_VG2_2ZZ_D}))
6504 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6506 case Intrinsic::aarch64_sve_sunpk_x4:
6508 Node->getValueType(0),
6509 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6510 AArch64::SUNPK_VG4_4Z2Z_D}))
6511 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6513 case Intrinsic::aarch64_sve_uunpk_x4:
6515 Node->getValueType(0),
6516 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6517 AArch64::UUNPK_VG4_4Z2Z_D}))
6518 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6520 case Intrinsic::aarch64_sve_pext_x2: {
6522 Node->getValueType(0),
6523 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6524 AArch64::PEXT_2PCI_D}))
6525 SelectPExtPair(Node,
Op);
6532 unsigned IntNo =
Node->getConstantOperandVal(1);
6533 if (
Node->getNumOperands() >= 3)
6534 VT =
Node->getOperand(2)->getValueType(0);
6538 case Intrinsic::aarch64_neon_st1x2: {
6539 if (VT == MVT::v8i8) {
6540 SelectStore(Node, 2, AArch64::ST1Twov8b);
6542 }
else if (VT == MVT::v16i8) {
6543 SelectStore(Node, 2, AArch64::ST1Twov16b);
6545 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6546 VT == MVT::v4bf16) {
6547 SelectStore(Node, 2, AArch64::ST1Twov4h);
6549 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6550 VT == MVT::v8bf16) {
6551 SelectStore(Node, 2, AArch64::ST1Twov8h);
6553 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6554 SelectStore(Node, 2, AArch64::ST1Twov2s);
6556 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6557 SelectStore(Node, 2, AArch64::ST1Twov4s);
6559 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6560 SelectStore(Node, 2, AArch64::ST1Twov2d);
6562 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6563 SelectStore(Node, 2, AArch64::ST1Twov1d);
6568 case Intrinsic::aarch64_neon_st1x3: {
6569 if (VT == MVT::v8i8) {
6570 SelectStore(Node, 3, AArch64::ST1Threev8b);
6572 }
else if (VT == MVT::v16i8) {
6573 SelectStore(Node, 3, AArch64::ST1Threev16b);
6575 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6576 VT == MVT::v4bf16) {
6577 SelectStore(Node, 3, AArch64::ST1Threev4h);
6579 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6580 VT == MVT::v8bf16) {
6581 SelectStore(Node, 3, AArch64::ST1Threev8h);
6583 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6584 SelectStore(Node, 3, AArch64::ST1Threev2s);
6586 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6587 SelectStore(Node, 3, AArch64::ST1Threev4s);
6589 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6590 SelectStore(Node, 3, AArch64::ST1Threev2d);
6592 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6593 SelectStore(Node, 3, AArch64::ST1Threev1d);
6598 case Intrinsic::aarch64_neon_st1x4: {
6599 if (VT == MVT::v8i8) {
6600 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6602 }
else if (VT == MVT::v16i8) {
6603 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6605 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6606 VT == MVT::v4bf16) {
6607 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6609 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6610 VT == MVT::v8bf16) {
6611 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6613 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6614 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6616 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6617 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6619 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6620 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6622 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6623 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6628 case Intrinsic::aarch64_neon_st2: {
6629 if (VT == MVT::v8i8) {
6630 SelectStore(Node, 2, AArch64::ST2Twov8b);
6632 }
else if (VT == MVT::v16i8) {
6633 SelectStore(Node, 2, AArch64::ST2Twov16b);
6635 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6636 VT == MVT::v4bf16) {
6637 SelectStore(Node, 2, AArch64::ST2Twov4h);
6639 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6640 VT == MVT::v8bf16) {
6641 SelectStore(Node, 2, AArch64::ST2Twov8h);
6643 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6644 SelectStore(Node, 2, AArch64::ST2Twov2s);
6646 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6647 SelectStore(Node, 2, AArch64::ST2Twov4s);
6649 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6650 SelectStore(Node, 2, AArch64::ST2Twov2d);
6652 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6653 SelectStore(Node, 2, AArch64::ST1Twov1d);
6658 case Intrinsic::aarch64_neon_st3: {
6659 if (VT == MVT::v8i8) {
6660 SelectStore(Node, 3, AArch64::ST3Threev8b);
6662 }
else if (VT == MVT::v16i8) {
6663 SelectStore(Node, 3, AArch64::ST3Threev16b);
6665 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6666 VT == MVT::v4bf16) {
6667 SelectStore(Node, 3, AArch64::ST3Threev4h);
6669 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6670 VT == MVT::v8bf16) {
6671 SelectStore(Node, 3, AArch64::ST3Threev8h);
6673 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6674 SelectStore(Node, 3, AArch64::ST3Threev2s);
6676 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6677 SelectStore(Node, 3, AArch64::ST3Threev4s);
6679 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6680 SelectStore(Node, 3, AArch64::ST3Threev2d);
6682 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6683 SelectStore(Node, 3, AArch64::ST1Threev1d);
6688 case Intrinsic::aarch64_neon_st4: {
6689 if (VT == MVT::v8i8) {
6690 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6692 }
else if (VT == MVT::v16i8) {
6693 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6695 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6696 VT == MVT::v4bf16) {
6697 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6699 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6700 VT == MVT::v8bf16) {
6701 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6703 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6704 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6706 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6707 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6709 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6710 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6712 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6713 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6718 case Intrinsic::aarch64_neon_st2lane: {
6719 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6720 SelectStoreLane(Node, 2, AArch64::ST2i8);
6722 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6723 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6724 SelectStoreLane(Node, 2, AArch64::ST2i16);
6726 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6728 SelectStoreLane(Node, 2, AArch64::ST2i32);
6730 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6732 SelectStoreLane(Node, 2, AArch64::ST2i64);
6737 case Intrinsic::aarch64_neon_st3lane: {
6738 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6739 SelectStoreLane(Node, 3, AArch64::ST3i8);
6741 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6742 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6743 SelectStoreLane(Node, 3, AArch64::ST3i16);
6745 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6747 SelectStoreLane(Node, 3, AArch64::ST3i32);
6749 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6751 SelectStoreLane(Node, 3, AArch64::ST3i64);
6756 case Intrinsic::aarch64_neon_st4lane: {
6757 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6758 SelectStoreLane(Node, 4, AArch64::ST4i8);
6760 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6761 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6762 SelectStoreLane(Node, 4, AArch64::ST4i16);
6764 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6766 SelectStoreLane(Node, 4, AArch64::ST4i32);
6768 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6770 SelectStoreLane(Node, 4, AArch64::ST4i64);
6775 case Intrinsic::aarch64_sve_st2q: {
6776 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6779 case Intrinsic::aarch64_sve_st3q: {
6780 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6783 case Intrinsic::aarch64_sve_st4q: {
6784 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6787 case Intrinsic::aarch64_sve_st2: {
6788 if (VT == MVT::nxv16i8) {
6789 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6791 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6792 VT == MVT::nxv8bf16) {
6793 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6795 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6796 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6798 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6799 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6804 case Intrinsic::aarch64_sve_st3: {
6805 if (VT == MVT::nxv16i8) {
6806 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6808 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6809 VT == MVT::nxv8bf16) {
6810 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6812 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6813 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6815 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6816 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6821 case Intrinsic::aarch64_sve_st4: {
6822 if (VT == MVT::nxv16i8) {
6823 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6825 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6826 VT == MVT::nxv8bf16) {
6827 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6829 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6830 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6832 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6833 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6841 case AArch64ISD::LD2post: {
6842 if (VT == MVT::v8i8) {
6843 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6845 }
else if (VT == MVT::v16i8) {
6846 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6848 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6849 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6851 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6852 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6854 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6855 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6857 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6858 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6860 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6861 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6863 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6864 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6869 case AArch64ISD::LD3post: {
6870 if (VT == MVT::v8i8) {
6871 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6873 }
else if (VT == MVT::v16i8) {
6874 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6876 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6877 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6879 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6880 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6882 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6883 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6885 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6886 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6888 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6889 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6891 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6892 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6897 case AArch64ISD::LD4post: {
6898 if (VT == MVT::v8i8) {
6899 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6901 }
else if (VT == MVT::v16i8) {
6902 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6904 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6905 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6907 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6908 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6910 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6911 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6913 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6914 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6916 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6917 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6919 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6920 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6925 case AArch64ISD::LD1x2post: {
6926 if (VT == MVT::v8i8) {
6927 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6929 }
else if (VT == MVT::v16i8) {
6930 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6932 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6933 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6935 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6936 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6938 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6939 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6941 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6942 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6944 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6945 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6947 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6948 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6953 case AArch64ISD::LD1x3post: {
6954 if (VT == MVT::v8i8) {
6955 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6957 }
else if (VT == MVT::v16i8) {
6958 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6960 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6961 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6963 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6964 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6966 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6967 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6969 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6970 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6972 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6973 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6975 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6976 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6981 case AArch64ISD::LD1x4post: {
6982 if (VT == MVT::v8i8) {
6983 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6985 }
else if (VT == MVT::v16i8) {
6986 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6988 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6989 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6991 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6992 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6994 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6995 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6997 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6998 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7000 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7001 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7003 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7004 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7009 case AArch64ISD::LD1DUPpost: {
7010 if (VT == MVT::v8i8) {
7011 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7013 }
else if (VT == MVT::v16i8) {
7014 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7016 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7017 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7019 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7020 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7022 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7023 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7025 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7026 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7028 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7029 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7031 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7032 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7037 case AArch64ISD::LD2DUPpost: {
7038 if (VT == MVT::v8i8) {
7039 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7041 }
else if (VT == MVT::v16i8) {
7042 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7044 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7045 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7047 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7048 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7050 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7051 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7053 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7054 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7056 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7057 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7059 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7060 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7065 case AArch64ISD::LD3DUPpost: {
7066 if (VT == MVT::v8i8) {
7067 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7069 }
else if (VT == MVT::v16i8) {
7070 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7072 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7073 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7075 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7076 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7078 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7079 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7081 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7082 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7084 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7085 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7087 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7088 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7093 case AArch64ISD::LD4DUPpost: {
7094 if (VT == MVT::v8i8) {
7095 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7097 }
else if (VT == MVT::v16i8) {
7098 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7100 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7101 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7103 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7104 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7106 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7107 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7109 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7110 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7112 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7113 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7115 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7116 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7121 case AArch64ISD::LD1LANEpost: {
7122 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7123 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7125 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7126 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7127 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7129 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7131 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7133 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7135 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7140 case AArch64ISD::LD2LANEpost: {
7141 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7142 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7144 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7145 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7146 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7148 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7150 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7152 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7154 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7159 case AArch64ISD::LD3LANEpost: {
7160 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7161 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7163 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7164 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7165 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7167 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7169 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7171 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7173 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7178 case AArch64ISD::LD4LANEpost: {
7179 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7180 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7182 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7183 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7184 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7186 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7188 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7190 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7192 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7197 case AArch64ISD::ST2post: {
7198 VT =
Node->getOperand(1).getValueType();
7199 if (VT == MVT::v8i8) {
7200 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7202 }
else if (VT == MVT::v16i8) {
7203 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7205 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7206 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7208 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7209 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7211 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7212 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7214 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7215 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7217 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7218 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7220 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7221 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7226 case AArch64ISD::ST3post: {
7227 VT =
Node->getOperand(1).getValueType();
7228 if (VT == MVT::v8i8) {
7229 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7231 }
else if (VT == MVT::v16i8) {
7232 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7234 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7235 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7237 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7238 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7240 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7241 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7243 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7244 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7246 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7247 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7249 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7250 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7255 case AArch64ISD::ST4post: {
7256 VT =
Node->getOperand(1).getValueType();
7257 if (VT == MVT::v8i8) {
7258 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7260 }
else if (VT == MVT::v16i8) {
7261 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7263 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7264 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7266 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7267 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7269 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7270 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7272 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7273 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7275 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7276 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7278 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7279 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7284 case AArch64ISD::ST1x2post: {
7285 VT =
Node->getOperand(1).getValueType();
7286 if (VT == MVT::v8i8) {
7287 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7289 }
else if (VT == MVT::v16i8) {
7290 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7292 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7293 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7295 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7296 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7298 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7299 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7301 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7302 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7304 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7305 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7307 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7308 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7313 case AArch64ISD::ST1x3post: {
7314 VT =
Node->getOperand(1).getValueType();
7315 if (VT == MVT::v8i8) {
7316 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7318 }
else if (VT == MVT::v16i8) {
7319 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7321 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7322 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7324 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7325 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7327 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7328 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7330 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7331 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7333 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7334 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7336 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7337 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7342 case AArch64ISD::ST1x4post: {
7343 VT =
Node->getOperand(1).getValueType();
7344 if (VT == MVT::v8i8) {
7345 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7347 }
else if (VT == MVT::v16i8) {
7348 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7350 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7351 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7353 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7354 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7356 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7357 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7359 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7360 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7362 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7363 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7365 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7366 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7371 case AArch64ISD::ST2LANEpost: {
7372 VT =
Node->getOperand(1).getValueType();
7373 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7374 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7376 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7377 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7378 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7380 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7382 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7384 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7386 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7391 case AArch64ISD::ST3LANEpost: {
7392 VT =
Node->getOperand(1).getValueType();
7393 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7394 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7396 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7397 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7398 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7400 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7402 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7404 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7406 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7411 case AArch64ISD::ST4LANEpost: {
7412 VT =
Node->getOperand(1).getValueType();
7413 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7414 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7416 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7417 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7418 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7420 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7422 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7424 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7426 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7441 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7453 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7457 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7458 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7473 return MemIntr->getMemoryVT();
7480 DataVT = Load->getValueType(0);
7482 DataVT = Load->getValueType(0);
7484 DataVT = Store->getValue().getValueType();
7486 DataVT = Store->getValue().getValueType();
7493 const unsigned Opcode = Root->
getOpcode();
7497 case AArch64ISD::LD1_MERGE_ZERO:
7498 case AArch64ISD::LD1S_MERGE_ZERO:
7499 case AArch64ISD::LDNF1_MERGE_ZERO:
7500 case AArch64ISD::LDNF1S_MERGE_ZERO:
7502 case AArch64ISD::ST1_PRED:
7514 case Intrinsic::aarch64_sme_ldr:
7515 case Intrinsic::aarch64_sme_str:
7516 return MVT::nxv16i8;
7517 case Intrinsic::aarch64_sve_prf:
7522 case Intrinsic::aarch64_sve_ld2_sret:
7523 case Intrinsic::aarch64_sve_ld2q_sret:
7526 case Intrinsic::aarch64_sve_st2q:
7529 case Intrinsic::aarch64_sve_ld3_sret:
7530 case Intrinsic::aarch64_sve_ld3q_sret:
7533 case Intrinsic::aarch64_sve_st3q:
7536 case Intrinsic::aarch64_sve_ld4_sret:
7537 case Intrinsic::aarch64_sve_ld4q_sret:
7540 case Intrinsic::aarch64_sve_st4q:
7543 case Intrinsic::aarch64_sve_ld1udq:
7544 case Intrinsic::aarch64_sve_st1dq:
7545 return EVT(MVT::nxv1i64);
7546 case Intrinsic::aarch64_sve_ld1uwq:
7547 case Intrinsic::aarch64_sve_st1wq:
7548 return EVT(MVT::nxv1i32);
7555template <
int64_t Min,
int64_t Max>
7556bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7560 const DataLayout &
DL = CurDAG->getDataLayout();
7561 const MachineFrameInfo &MFI = MF->getFrameInfo();
7569 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7583 int64_t MulImm = std::numeric_limits<int64_t>::max();
7587 int64_t ByteOffset =
C->getSExtValue();
7588 const auto KnownVScale =
7591 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7594 MulImm = ByteOffset / KnownVScale;
7601 if ((MulImm % MemWidthBytes) != 0)
7604 int64_t
Offset = MulImm / MemWidthBytes;
7608 Base =
N.getOperand(0);
7617 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7623bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7642 int64_t ImmOff =
C->getSExtValue();
7643 unsigned Size = 1 << Scale;
7652 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7654 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7665 if (
C->getZExtValue() == Scale) {
7674bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7675 const AArch64TargetLowering *TLI =
7676 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7681bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7682 EVT VT =
N.getValueType();
7686bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7691 int64_t ImmOff =
C->getSExtValue();
7692 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7693 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7698 if (
SDValue C = MatchConstantOffset(
N)) {
7699 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7705 if (CurDAG->isBaseWithConstantOffset(
N)) {
7706 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7707 Base =
N.getOperand(0);
7715 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7719bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7739 uint64_t LowerBound = 0, UpperBound = 64;
7757 if (CN->getAPIntValue().uge(LowerBound) &&
7758 CN->getAPIntValue().ult(UpperBound)) {
7760 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7768template <
bool MatchCBB>
7775 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7777 Reg =
N.getOperand(0);
7779 SDLoc(
N), MVT::i32);
7787 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
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...
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static bool isSVELogicalImm(unsigned SizeInBits, uint64_t ImmVal, uint64_t &Encoding)
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.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ 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.
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ 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
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
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.
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.