22#include "llvm/IR/IntrinsicsAArch64.h"
31#define DEBUG_TYPE "aarch64-isel"
32#define PASS_NAME "AArch64 Instruction Selection"
35#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
36#pragma inline_depth(0)
52 AArch64DAGToDAGISel() =
delete;
67 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
69 std::vector<SDValue> &OutOps)
override;
71 template <
signed Low,
signed High,
signed Scale>
74 template <
signed Low,
signed High>
82 return SelectShiftedRegister(
N,
false,
Reg, Shift);
85 return SelectShiftedRegister(
N,
true,
Reg, Shift);
88 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
91 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
94 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
97 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
100 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
103 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
106 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
109 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
112 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
115 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
118 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
121 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
124 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
127 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
130 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
133 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
136 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
138 template <
unsigned Size,
unsigned Max>
142 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
145 int64_t
C = CI->getSExtValue();
153 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
160 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
166 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
171 N =
N->getOperand(0);
175 EVT VT =
N->getValueType(0);
176 EVT LVT =
N->getOperand(0).getValueType();
177 unsigned Index =
N->getConstantOperandVal(1);
181 Res =
N->getOperand(0);
186 if (
N.getOpcode() != AArch64ISD::VLSHR)
189 EVT VT =
Op.getValueType();
190 unsigned ShtAmt =
N->getConstantOperandVal(1);
195 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
197 Op.getOperand(1).getConstantOperandVal(0)
198 <<
Op.getOperand(1).getConstantOperandVal(1));
199 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
202 Op.getOperand(1).getConstantOperandVal(0));
206 if (Imm != 1ULL << (ShtAmt - 1))
209 Res1 =
Op.getOperand(0);
210 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
214 bool SelectDupZeroOrUndef(
SDValue N) {
215 switch(
N->getOpcode()) {
218 case AArch64ISD::DUP:
220 auto Opnd0 =
N->getOperand(0);
234 bool SelectAny(
SDValue) {
return true; }
237 switch(
N->getOpcode()) {
238 case AArch64ISD::DUP:
240 auto Opnd0 =
N->getOperand(0);
252 template <MVT::SimpleValueType VT,
bool Negate>
254 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
257 template <MVT::SimpleValueType VT,
bool Negate>
259 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
262 template <MVT::SimpleValueType VT>
264 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
267 template <MVT::SimpleValueType VT,
bool Invert = false>
269 return SelectSVELogicalImm(
N, VT, Imm, Invert);
272 template <MVT::SimpleValueType VT>
274 return SelectSVEArithImm(
N, VT, Imm);
277 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
279 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
286 EVT EltVT =
N->getValueType(0).getVectorElementType();
287 return SelectSVEShiftImm(
N->getOperand(0), 1,
293 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
300 MulImm = 1LL << MulImm;
302 if ((MulImm % std::abs(Scale)) != 0)
306 if ((MulImm >= Min) && (MulImm <= Max)) {
307 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
314 template <
signed Max,
signed Scale>
321 if (MulImm >= 0 && MulImm <= Max) {
323 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
330 template <
unsigned BaseReg,
unsigned Max>
338 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
361 const unsigned SubRegs[]);
363 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
365 bool tryIndexedLoad(
SDNode *
N);
367 void SelectPtrauthAuth(
SDNode *
N);
368 void SelectPtrauthResign(
SDNode *
N);
370 bool trySelectStackSlotTagP(
SDNode *
N);
373 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
375 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
377 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
378 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
379 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
380 unsigned Opc_rr,
unsigned Opc_ri,
381 bool IsIntr =
false);
382 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
383 unsigned Scale,
unsigned Opc_ri,
385 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
386 bool IsZmMulti,
unsigned Opcode,
387 bool HasPred =
false);
389 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
390 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
391 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
392 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
393 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
394 bool IsTupleInput,
unsigned Opc);
395 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
397 template <
unsigned MaxIdx,
unsigned Scale>
398 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
400 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
401 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
402 unsigned BaseReg = 0);
405 template <
int64_t Min,
int64_t Max>
409 template <
unsigned Scale>
411 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
414 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
417 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc);
419 template <
unsigned MaxIdx,
unsigned Scale>
424 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
425 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
426 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
427 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
428 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
429 unsigned Opc_rr,
unsigned Opc_ri);
430 std::tuple<unsigned, SDValue, SDValue>
431 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
435 bool tryBitfieldExtractOp(
SDNode *
N);
436 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
437 bool tryBitfieldInsertOp(
SDNode *
N);
438 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
439 bool tryShiftAmountMod(
SDNode *
N);
441 bool tryReadRegister(
SDNode *
N);
442 bool tryWriteRegister(
SDNode *
N);
444 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
445 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
450#include "AArch64GenDAGISel.inc"
458 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
460 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
473 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
474 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
475 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
478 template<
unsigned RegW
idth>
480 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
483 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
485 template<
unsigned RegW
idth>
487 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
493 bool SelectCMP_SWAP(
SDNode *
N);
504 bool AllowSaturation,
SDValue &Imm);
512 bool SelectAllActivePredicate(
SDValue N);
517 template <
bool MatchCBB>
527 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
531char AArch64DAGToDAGISelLegacy::ID = 0;
539 Imm =
C->getZExtValue();
556 return N->getOpcode() ==
Opc &&
567 return Imm == ImmExpected;
571bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
573 std::vector<SDValue> &OutOps) {
574 switch(ConstraintID) {
577 case InlineAsm::ConstraintCode::m:
578 case InlineAsm::ConstraintCode::o:
579 case InlineAsm::ConstraintCode::Q:
583 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
585 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
587 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
588 dl,
Op.getValueType(),
590 OutOps.push_back(NewOp);
609 uint64_t Immed =
N.getNode()->getAsZExtVal();
612 if (Immed >> 12 == 0) {
614 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
622 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
623 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
640 uint64_t Immed =
N.getNode()->getAsZExtVal();
648 if (
N.getValueType() == MVT::i32)
649 Immed = ~((uint32_t)Immed) + 1;
651 Immed = ~Immed + 1ULL;
652 if (Immed & 0xFFFFFFFFFF000000ULL)
655 Immed &= 0xFFFFFFULL;
656 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
663 switch (
N.getOpcode()) {
689 unsigned ShiftVal = CSD->getZExtValue();
707bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
710 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
715 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
739 EVT VT =
N.getValueType();
740 if (VT != MVT::i32 && VT != MVT::i64)
743 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
749 unsigned LHSOpcode =
LHS->getOpcode();
763 unsigned LowZBits, MaskLen;
767 unsigned BitWidth =
N.getValueSizeInBits();
774 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
777 NewShiftC = LowZBits - ShiftAmtC;
778 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
784 NewShiftC = LowZBits + ShiftAmtC;
797 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
799 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
803 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
805 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
806 NewShiftAmt, BitWidthMinus1),
809 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
823 SrcVT =
N.getOperand(0).getValueType();
825 if (!IsLoadStore && SrcVT == MVT::i8)
827 else if (!IsLoadStore && SrcVT == MVT::i16)
829 else if (SrcVT == MVT::i32)
831 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
836 EVT SrcVT =
N.getOperand(0).getValueType();
837 if (!IsLoadStore && SrcVT == MVT::i8)
839 else if (!IsLoadStore && SrcVT == MVT::i16)
841 else if (SrcVT == MVT::i32)
843 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
871bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
874 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
879 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
880 V.getConstantOperandVal(1) <= 4 &&
893bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
895 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
905 unsigned BitSize =
N.getValueSizeInBits();
906 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
909 Reg =
N.getOperand(0);
910 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
911 return isWorthFoldingALU(
N,
true);
922 if (
N.getValueType() == MVT::i32)
930template<
signed Low,
signed High,
signed Scale>
936 if ((MulImm % std::abs(Scale)) == 0) {
937 int64_t RDVLImm = MulImm / Scale;
938 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
939 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
948template <
signed Low,
signed High>
949bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
954 if (MulImm >=
Low && MulImm <=
High) {
955 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
966 unsigned ShiftVal = 0;
981 Reg =
N.getOperand(0).getOperand(0);
987 Reg =
N.getOperand(0);
992 unsigned Opc =
N.getOpcode();
1010 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1012 return isWorthFoldingALU(
N);
1019 unsigned ShiftVal = 0;
1033 Reg =
N.getOperand(0);
1034 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1036 return isWorthFoldingALU(
N);
1045 for (
auto *
User :
N->users()) {
1046 if (
User->getOpcode() != ISD::LOAD &&
User->getOpcode() != ISD::STORE &&
1047 User->getOpcode() != ISD::ATOMIC_LOAD &&
1048 User->getOpcode() != ISD::ATOMIC_STORE)
1072bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1073 unsigned BW,
unsigned Size,
1077 const DataLayout &
DL = CurDAG->getDataLayout();
1078 const TargetLowering *TLI = getTargetLowering();
1082 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1088 if (CurDAG->isBaseWithConstantOffset(
N)) {
1091 int64_t RHSC =
RHS->getSExtValue();
1093 int64_t
Range = 0x1LL << (BW - 1);
1095 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1096 RHSC < (
Range << Scale)) {
1097 Base =
N.getOperand(0);
1102 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1107 uint64_t RHSC =
RHS->getZExtValue();
1109 uint64_t
Range = 0x1ULL << BW;
1111 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1112 Base =
N.getOperand(0);
1117 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1128 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1135bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1138 const DataLayout &
DL = CurDAG->getDataLayout();
1139 const TargetLowering *TLI = getTargetLowering();
1143 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1148 GlobalAddressSDNode *GAN =
1150 Base =
N.getOperand(0);
1160 if (CurDAG->isBaseWithConstantOffset(
N)) {
1162 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1165 Base =
N.getOperand(0);
1170 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1178 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1186 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1195bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1198 if (!CurDAG->isBaseWithConstantOffset(
N))
1201 int64_t RHSC =
RHS->getSExtValue();
1202 if (RHSC >= -256 && RHSC < 256) {
1203 Base =
N.getOperand(0);
1206 const TargetLowering *TLI = getTargetLowering();
1207 Base = CurDAG->getTargetFrameIndex(
1210 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1220 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1227bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1247 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1253 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1256 return isWorthFoldingAddr(
N,
Size);
1259bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1277 const SDNode *
Node =
N.getNode();
1278 for (SDNode *UI :
Node->users()) {
1284 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1287 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1290 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1295 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1298 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1303 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1307 if (IsExtendedRegisterWorthFolding &&
1314 if (isWorthFoldingAddr(
LHS,
Size))
1319 if (IsExtendedRegisterWorthFolding &&
1326 if (isWorthFoldingAddr(
RHS,
Size))
1338 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1341 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1343 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1344 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1348bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1361 const SDNode *
Node =
N.getNode();
1362 for (SDNode *UI :
Node->users()) {
1379 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1389 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1396 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1399 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1402 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1407 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1410 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1417 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1418 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1424 static const unsigned RegClassIDs[] = {
1425 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1426 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1427 AArch64::dsub2, AArch64::dsub3};
1433 static const unsigned RegClassIDs[] = {
1434 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1435 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1436 AArch64::qsub2, AArch64::qsub3};
1442 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1443 AArch64::ZPR3RegClassID,
1444 AArch64::ZPR4RegClassID};
1445 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1446 AArch64::zsub2, AArch64::zsub3};
1456 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1457 AArch64::ZPR4Mul4RegClassID};
1458 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1459 AArch64::zsub2, AArch64::zsub3};
1464 const unsigned RegClassIDs[],
1465 const unsigned SubRegs[]) {
1468 if (Regs.
size() == 1)
1479 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1482 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1483 Ops.push_back(Regs[i]);
1484 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1488 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1492void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1495 EVT VT =
N->getValueType(0);
1497 unsigned ExtOff = isExt;
1500 unsigned Vec0Off = ExtOff + 1;
1506 Ops.push_back(
N->getOperand(1));
1507 Ops.push_back(RegSeq);
1508 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1509 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1512static std::tuple<SDValue, SDValue>
1533 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1538 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1540 return std::make_tuple(
1545void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1550 SDValue AUTDisc =
N->getOperand(3);
1553 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1555 SDValue AUTAddrDisc, AUTConstDisc;
1556 std::tie(AUTConstDisc, AUTAddrDisc) =
1560 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1562 if (
N->getNumOperands() > 4)
1563 Ops.push_back(
N->getOperand(4));
1566 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1567 ReplaceNode(
N, AUT);
1569 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1570 AArch64::X16, Val,
SDValue());
1573 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1574 ReplaceNode(
N, AUT);
1578void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1590 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1591 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1593 SDValue AUTAddrDisc, AUTConstDisc;
1594 std::tie(AUTConstDisc, AUTAddrDisc) =
1597 SDValue PACAddrDisc, PACConstDisc;
1598 std::tie(PACConstDisc, PACAddrDisc) =
1601 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1602 AArch64::X16, Val,
SDValue());
1604 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1605 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1607 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1608 ReplaceNode(
N, AUTPAC);
1611bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1613 if (
LD->isUnindexed())
1615 EVT VT =
LD->getMemoryVT();
1616 EVT DstVT =
N->getValueType(0);
1620 int OffsetVal = (int)
OffsetOp->getZExtValue();
1625 unsigned Opcode = 0;
1628 bool InsertTo64 =
false;
1630 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1631 else if (VT == MVT::i32) {
1633 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1635 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1637 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1643 }
else if (VT == MVT::i16) {
1645 if (DstVT == MVT::i64)
1646 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1648 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1650 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1651 InsertTo64 = DstVT == MVT::i64;
1656 }
else if (VT == MVT::i8) {
1658 if (DstVT == MVT::i64)
1659 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1661 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1663 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1664 InsertTo64 = DstVT == MVT::i64;
1669 }
else if (VT == MVT::f16) {
1670 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1671 }
else if (VT == MVT::bf16) {
1672 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1673 }
else if (VT == MVT::f32) {
1674 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1675 }
else if (VT == MVT::f64 ||
1677 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1679 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1681 if (IsPre || OffsetVal != 8)
1685 Opcode = AArch64::LD1Onev8b_POST;
1688 Opcode = AArch64::LD1Onev4h_POST;
1691 Opcode = AArch64::LD1Onev2s_POST;
1694 Opcode = AArch64::LD1Onev1d_POST;
1700 if (IsPre || OffsetVal != 16)
1704 Opcode = AArch64::LD1Onev16b_POST;
1707 Opcode = AArch64::LD1Onev8h_POST;
1710 Opcode = AArch64::LD1Onev4s_POST;
1713 Opcode = AArch64::LD1Onev2d_POST;
1725 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1726 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1728 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1738 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1740 SDValue(CurDAG->getMachineNode(
1741 AArch64::SUBREG_TO_REG, dl, MVT::i64,
1742 CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1747 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1750 CurDAG->RemoveDeadNode(
N);
1754void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1755 unsigned SubRegIdx) {
1757 EVT VT =
N->getValueType(0);
1763 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1765 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1767 for (
unsigned i = 0; i < NumVecs; ++i)
1769 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1776 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1780 CurDAG->RemoveDeadNode(
N);
1783void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1784 unsigned Opc,
unsigned SubRegIdx) {
1786 EVT VT =
N->getValueType(0);
1793 const EVT ResTys[] = {MVT::i64,
1794 MVT::Untyped, MVT::Other};
1796 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1804 ReplaceUses(
SDValue(
N, 0), SuperReg);
1806 for (
unsigned i = 0; i < NumVecs; ++i)
1808 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1812 CurDAG->RemoveDeadNode(
N);
1818std::tuple<unsigned, SDValue, SDValue>
1819AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1825 SDValue NewOffset = OldOffset;
1827 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1828 N, OldBase, NewBase, NewOffset);
1832 const bool IsRegReg =
1833 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1836 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
1849template <SelectTypeKind Kind>
1861 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
1866 if (EltVT != MVT::i1)
1870 if (EltVT == MVT::bf16)
1872 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
1902void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
1905 if (
Imm->getZExtValue() > 1)
1909 EVT VT =
N->getValueType(0);
1911 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1914 for (
unsigned I = 0;
I < 2; ++
I)
1915 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1916 AArch64::psub0 +
I,
DL, VT, SuperReg));
1918 CurDAG->RemoveDeadNode(
N);
1921void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
1923 EVT VT =
N->getValueType(0);
1927 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1930 for (
unsigned I = 0;
I < 2; ++
I)
1931 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1932 AArch64::psub0 +
I,
DL, VT, SuperReg));
1934 CurDAG->RemoveDeadNode(
N);
1937void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
1939 EVT VT =
N->getValueType(0);
1943 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
1945 for (
unsigned i = 0; i < NumVecs; ++i)
1946 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1947 AArch64::zsub0 + i,
DL, VT, SuperReg));
1949 CurDAG->RemoveDeadNode(
N);
1952void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
1955 EVT VT =
N->getValueType(0);
1957 Ops.push_back(
N->getOperand(0));
1960 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
1963 for (
unsigned i = 0; i < NumVecs; ++i)
1964 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1965 AArch64::zsub0 + i,
DL, VT, SuperReg));
1968 unsigned ChainIdx = NumVecs;
1970 CurDAG->RemoveDeadNode(
N);
1973void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
1978 assert(Opcode != 0 &&
"Unexpected opcode");
1981 EVT VT =
N->getValueType(0);
1982 unsigned FirstVecIdx = HasPred ? 2 : 1;
1984 auto GetMultiVecOperand = [=](
unsigned StartIdx) {
1986 return createZMulTuple(Regs);
1989 SDValue Zdn = GetMultiVecOperand(FirstVecIdx);
1993 Zm = GetMultiVecOperand(NumVecs + FirstVecIdx);
1999 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
2000 N->getOperand(1), Zdn, Zm);
2002 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped, Zdn, Zm);
2004 for (
unsigned i = 0; i < NumVecs; ++i)
2005 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2006 AArch64::zsub0 + i,
DL, VT, SuperReg));
2008 CurDAG->RemoveDeadNode(
N);
2011void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2012 unsigned Scale,
unsigned Opc_ri,
2013 unsigned Opc_rr,
bool IsIntr) {
2014 assert(Scale < 5 &&
"Invalid scaling value.");
2016 EVT VT =
N->getValueType(0);
2023 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2024 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2030 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2032 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2034 for (
unsigned i = 0; i < NumVecs; ++i)
2035 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2036 AArch64::zsub0 + i,
DL, VT, SuperReg));
2039 unsigned ChainIdx = NumVecs;
2041 CurDAG->RemoveDeadNode(
N);
2044void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2049 assert(Scale < 4 &&
"Invalid scaling value.");
2051 EVT VT =
N->getValueType(0);
2059 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2065 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2067 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2069 for (
unsigned i = 0; i < NumVecs; ++i)
2070 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2071 AArch64::zsub0 + i,
DL, VT, SuperReg));
2074 unsigned ChainIdx = NumVecs;
2076 CurDAG->RemoveDeadNode(
N);
2079void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2081 if (
N->getValueType(0) != MVT::nxv4f32)
2083 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2086void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2087 unsigned NumOutVecs,
2091 if (
Imm->getZExtValue() > MaxImm)
2095 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2101 EVT VT =
Node->getValueType(0);
2104 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2107 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2108 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2109 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2112 unsigned ChainIdx = NumOutVecs;
2114 CurDAG->RemoveDeadNode(Node);
2117void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2118 unsigned NumOutVecs,
2121 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2126 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2130 EVT VT =
Node->getValueType(0);
2133 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2136 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2137 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2138 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2141 unsigned ChainIdx = NumOutVecs;
2143 CurDAG->RemoveDeadNode(Node);
2146void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2149 EVT VT =
N->getValueType(0);
2152 SDValue Zd = createZMulTuple(Regs);
2153 SDValue Zn =
N->getOperand(1 + NumVecs);
2160 for (
unsigned i = 0; i < NumVecs; ++i)
2161 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2162 AArch64::zsub0 + i,
DL, VT, SuperReg));
2164 CurDAG->RemoveDeadNode(
N);
2194template <
unsigned MaxIdx,
unsigned Scale>
2195void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2196 unsigned BaseReg,
unsigned Op) {
2197 unsigned TileNum = 0;
2198 if (BaseReg != AArch64::ZA)
2199 TileNum =
N->getConstantOperandVal(2);
2205 if (BaseReg == AArch64::ZA)
2210 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2216 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2218 EVT VT =
N->getValueType(0);
2219 for (
unsigned I = 0;
I < NumVecs; ++
I)
2221 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2224 unsigned ChainIdx = NumVecs;
2226 CurDAG->RemoveDeadNode(
N);
2229void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2230 unsigned Op,
unsigned MaxIdx,
2231 unsigned Scale,
unsigned BaseReg) {
2236 if (BaseReg != AArch64::ZA)
2240 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2247 if (BaseReg != AArch64::ZA )
2248 Ops.push_back(
N->getOperand(2));
2251 Ops.push_back(
N->getOperand(0));
2252 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2254 EVT VT =
N->getValueType(0);
2255 for (
unsigned I = 0;
I < NumVecs; ++
I)
2257 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2261 unsigned ChainIdx = NumVecs;
2263 CurDAG->RemoveDeadNode(
N);
2266void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2267 unsigned NumOutVecs,
2271 EVT VT =
N->getValueType(0);
2272 unsigned NumInVecs =
N->getNumOperands() - 1;
2276 assert((NumInVecs == 2 || NumInVecs == 4) &&
2277 "Don't know how to handle multi-register input!");
2279 Ops.push_back(createZMulTuple(Regs));
2282 for (
unsigned I = 0;
I < NumInVecs;
I++)
2283 Ops.push_back(
N->getOperand(1 +
I));
2286 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2289 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2290 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2291 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2292 CurDAG->RemoveDeadNode(
N);
2295void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2298 EVT VT =
N->getOperand(2)->getValueType(0);
2306 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2315void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2316 unsigned Scale,
unsigned Opc_rr,
2322 SDValue RegSeq = createZTuple(Regs);
2328 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2329 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2335 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2343 const DataLayout &
DL = CurDAG->getDataLayout();
2344 const TargetLowering *TLI = getTargetLowering();
2348 int FI = FINode->getIndex();
2350 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2357void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2360 EVT VT =
N->getOperand(2)->getValueType(0);
2361 const EVT ResTys[] = {MVT::i64,
2373 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2413void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2416 EVT VT =
N->getValueType(0);
2428 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2430 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2432 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2434 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2438 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2439 AArch64::qsub2, AArch64::qsub3 };
2440 for (
unsigned i = 0; i < NumVecs; ++i) {
2441 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2448 CurDAG->RemoveDeadNode(
N);
2451void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2454 EVT VT =
N->getValueType(0);
2466 const EVT ResTys[] = {MVT::i64,
2469 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2472 CurDAG->getTargetConstant(LaneNo, dl,
2477 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2489 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2490 AArch64::qsub2, AArch64::qsub3 };
2491 for (
unsigned i = 0; i < NumVecs; ++i) {
2492 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2502 CurDAG->RemoveDeadNode(
N);
2505void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2508 EVT VT =
N->getOperand(2)->getValueType(0);
2520 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2522 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2524 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2533void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2536 EVT VT =
N->getOperand(2)->getValueType(0);
2548 const EVT ResTys[] = {MVT::i64,
2551 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2553 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2557 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2568 unsigned &LSB,
unsigned &MSB,
2569 unsigned NumberOfIgnoredLowBits,
2570 bool BiggerPattern) {
2572 "N must be a AND operation to call this function");
2574 EVT VT =
N->getValueType(0);
2579 assert((VT == MVT::i32 || VT == MVT::i64) &&
2580 "Type checking must have been done before calling this function");
2594 const SDNode *Op0 =
N->getOperand(0).getNode();
2601 if (AndImm & (AndImm + 1))
2604 bool ClampMSB =
false;
2624 ClampMSB = (VT == MVT::i32);
2625 }
else if (BiggerPattern) {
2631 Opd0 =
N->getOperand(0);
2637 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2640 <<
": Found large shift immediate, this should not happen\n"));
2654 MSB = MSB > 31 ? 31 : MSB;
2656 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2661 SDValue &Opd0,
unsigned &Immr,
2665 EVT VT =
N->getValueType(0);
2667 assert((VT == MVT::i32 || VT == MVT::i64) &&
2668 "Type checking must have been done before calling this function");
2672 Op =
Op->getOperand(0);
2673 VT =
Op->getValueType(0);
2682 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2686 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2687 Opd0 =
Op.getOperand(0);
2689 Imms = ShiftImm + Width - 1;
2717 Opd0 =
N->getOperand(0).getOperand(0);
2727 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2734 unsigned &Immr,
unsigned &Imms,
2735 bool BiggerPattern) {
2737 "N must be a SHR/SRA operation to call this function");
2739 EVT VT =
N->getValueType(0);
2744 assert((VT == MVT::i32 || VT == MVT::i64) &&
2745 "Type checking must have been done before calling this function");
2755 Opd0 =
N->getOperand(0).getOperand(0);
2756 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2762 Opd0 =
N->getOperand(0).getOperand(0);
2765 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2766 }
else if (BiggerPattern) {
2770 Opd0 =
N->getOperand(0);
2779 <<
": Found large shift immediate, this should not happen\n"));
2788 "bad amount in shift node!");
2789 int immr = SrlImm - ShlImm;
2794 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2796 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2800bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2803 EVT VT =
N->getValueType(0);
2804 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2805 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2816 unsigned Immr = ShiftImm;
2818 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2819 CurDAG->getTargetConstant(Imms, dl, VT)};
2820 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2825 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2826 unsigned NumberOfIgnoredLowBits = 0,
2827 bool BiggerPattern =
false) {
2828 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2831 switch (
N->getOpcode()) {
2833 if (!
N->isMachineOpcode())
2838 NumberOfIgnoredLowBits, BiggerPattern);
2847 unsigned NOpc =
N->getMachineOpcode();
2851 case AArch64::SBFMWri:
2852 case AArch64::UBFMWri:
2853 case AArch64::SBFMXri:
2854 case AArch64::UBFMXri:
2856 Opd0 =
N->getOperand(0);
2857 Immr =
N->getConstantOperandVal(1);
2858 Imms =
N->getConstantOperandVal(2);
2865bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2866 unsigned Opc, Immr, Imms;
2871 EVT VT =
N->getValueType(0);
2876 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2877 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2878 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2880 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2881 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2887 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2888 CurDAG->getTargetConstant(Imms, dl, VT)};
2889 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2898 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2899 assert((VT == MVT::i32 || VT == MVT::i64) &&
2900 "i32 or i64 mask type expected!");
2904 APInt SignificantDstMask =
2908 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2909 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2942 APInt OpUsefulBits(UsefulBits);
2946 OpUsefulBits <<= MSB - Imm + 1;
2951 OpUsefulBits <<= Imm;
2953 OpUsefulBits <<= MSB + 1;
2956 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2962 UsefulBits &= OpUsefulBits;
2979 APInt Mask(UsefulBits);
2980 Mask.clearAllBits();
2988 Mask.lshrInPlace(ShiftAmt);
2994 Mask.lshrInPlace(ShiftAmt);
3010 APInt OpUsefulBits(UsefulBits);
3024 OpUsefulBits <<= Width;
3027 if (
Op.getOperand(1) == Orig) {
3029 Mask = ResultUsefulBits & OpUsefulBits;
3033 if (
Op.getOperand(0) == Orig)
3035 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3041 OpUsefulBits <<= Width;
3043 OpUsefulBits <<= LSB;
3045 if (
Op.getOperand(1) == Orig) {
3047 Mask = ResultUsefulBits & OpUsefulBits;
3048 Mask.lshrInPlace(LSB);
3051 if (
Op.getOperand(0) == Orig)
3052 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3069 case AArch64::ANDSWri:
3070 case AArch64::ANDSXri:
3071 case AArch64::ANDWri:
3072 case AArch64::ANDXri:
3076 case AArch64::UBFMWri:
3077 case AArch64::UBFMXri:
3080 case AArch64::ORRWrs:
3081 case AArch64::ORRXrs:
3086 case AArch64::BFMWri:
3087 case AArch64::BFMXri:
3090 case AArch64::STRBBui:
3091 case AArch64::STURBBi:
3097 case AArch64::STRHHui:
3098 case AArch64::STURHHi:
3111 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3113 UsefulBits =
APInt(Bitwidth, 0);
3122 UsersUsefulBits |= UsefulBitsForUse;
3127 UsefulBits &= UsersUsefulBits;
3137 EVT VT =
Op.getValueType();
3140 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3143 if (ShlAmount > 0) {
3146 UBFMOpc, dl, VT,
Op,
3151 assert(ShlAmount < 0 &&
"expected right shift");
3152 int ShrAmount = -ShlAmount;
3164 const uint64_t NonZeroBits,
3171 const uint64_t NonZeroBits,
3178 bool BiggerPattern,
SDValue &Src,
3179 int &DstLSB,
int &Width) {
3180 EVT VT =
Op.getValueType();
3189 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3193 switch (
Op.getOpcode()) {
3198 NonZeroBits, Src, DstLSB, Width);
3201 NonZeroBits, Src, DstLSB, Width);
3214 EVT VT =
Op.getValueType();
3215 assert((VT == MVT::i32 || VT == MVT::i64) &&
3216 "Caller guarantees VT is one of i32 or i64");
3229 assert((~AndImm & NonZeroBits) == 0 &&
3230 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3259 if (!BiggerPattern && !AndOp0.
hasOneUse())
3278 <<
"Found large Width in bit-field-positioning -- this indicates no "
3279 "proper combining / constant folding was performed\n");
3288 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3303 "Op.getNode() should be a SHL node to call this function");
3305 "Op.getNode() should shift ShlImm to call this function");
3312 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3336 EVT VT =
Op.getValueType();
3337 assert((VT == MVT::i32 || VT == MVT::i64) &&
3338 "Caller guarantees that type is i32 or i64");
3345 if (!BiggerPattern && !
Op.hasOneUse())
3354 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3362 assert(VT == MVT::i32 || VT == MVT::i64);
3373 EVT VT =
N->getValueType(0);
3374 if (VT != MVT::i32 && VT != MVT::i64)
3392 if (!
And.hasOneUse() ||
3402 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3409 if ((OrImm & NotKnownZero) != 0) {
3421 unsigned ImmS = Width - 1;
3427 bool IsBFI = LSB != 0;
3432 unsigned OrChunks = 0, BFIChunks = 0;
3433 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3434 if (((OrImm >> Shift) & 0xFFFF) != 0)
3436 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3439 if (BFIChunks > OrChunks)
3445 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3453 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3462 if (!Dst.hasOneUse())
3465 EVT VT = Dst.getValueType();
3466 assert((VT == MVT::i32 || VT == MVT::i64) &&
3467 "Caller should guarantee that VT is one of i32 or i64");
3495 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3496 unsigned MaskWidth =
3499 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3505 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3506 ShiftedOperand =
SDValue(UBFMNode, 0);
3535 const bool BiggerPattern) {
3536 EVT VT =
N->getValueType(0);
3537 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3538 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3539 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3540 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3541 assert((VT == MVT::i32 || VT == MVT::i64) &&
3542 "Expect result type to be i32 or i64 since N is combinable to BFM");
3549 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3552 if (BiggerPattern) {
3575 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3637 EVT VT =
N->getValueType(0);
3638 if (VT != MVT::i32 && VT != MVT::i64)
3646 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3647 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3667 for (
int I = 0;
I < 4; ++
I) {
3670 unsigned ImmR, ImmS;
3671 bool BiggerPattern =
I / 2;
3672 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3674 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3680 NumberOfIgnoredLowBits, BiggerPattern)) {
3683 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3684 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3689 Width = ImmS - ImmR + 1;
3700 Src, DstLSB, Width)) {
3708 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3718 APInt BitsToBeInserted =
3721 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3745 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3778 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3780 if (Src->hasOneUse() &&
3783 Src = Src->getOperand(0);
3793 unsigned ImmS = Width - 1;
3799 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3807bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3816 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3829bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3833 EVT VT =
N->getValueType(0);
3834 if (VT != MVT::i32 && VT != MVT::i64)
3840 Op0, DstLSB, Width))
3846 unsigned ImmS = Width - 1;
3849 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3850 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3851 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3852 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3858bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3859 EVT VT =
N->getValueType(0);
3862 switch (
N->getOpcode()) {
3864 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3867 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3870 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3873 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3881 if (VT == MVT::i32) {
3884 }
else if (VT == MVT::i64) {
3890 SDValue ShiftAmt =
N->getOperand(1);
3910 (Add0Imm %
Size == 0)) {
3916 if (SubVT == MVT::i32) {
3917 NegOpc = AArch64::SUBWrr;
3918 ZeroReg = AArch64::WZR;
3920 assert(SubVT == MVT::i64);
3921 NegOpc = AArch64::SUBXrr;
3922 ZeroReg = AArch64::XZR;
3925 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3926 MachineSDNode *Neg =
3927 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3928 NewShiftAmt =
SDValue(Neg, 0);
3936 if (SubVT == MVT::i32) {
3937 NotOpc = AArch64::ORNWrr;
3938 ZeroReg = AArch64::WZR;
3940 assert(SubVT == MVT::i64);
3941 NotOpc = AArch64::ORNXrr;
3942 ZeroReg = AArch64::XZR;
3945 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3946 MachineSDNode *
Not =
3947 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3948 NewShiftAmt =
SDValue(Not, 0);
3969 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3970 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3971 MachineSDNode *
Ext = CurDAG->getMachineNode(
3972 AArch64::SUBREG_TO_REG,
DL, VT,
3973 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3974 NewShiftAmt =
SDValue(Ext, 0);
3978 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3985 bool isReciprocal) {
3988 FVal = CN->getValueAPF();
3991 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4020 if (!IsExact || !IntVal.isPowerOf2())
4022 unsigned FBits = IntVal.logBase2();
4026 if (FBits == 0 || FBits > RegWidth)
return false;
4032bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4033 unsigned RegWidth) {
4038bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4040 unsigned RegWidth) {
4050 RegString.
split(Fields,
':');
4052 if (Fields.
size() == 1)
4056 &&
"Invalid number of fields in read register string");
4059 bool AllIntFields =
true;
4063 AllIntFields &= !
Field.getAsInteger(10, IntField);
4064 Ops.push_back(IntField);
4068 "Unexpected non-integer value in special register string.");
4073 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4074 (
Ops[3] << 3) | (
Ops[4]);
4081bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4083 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4086 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4088 unsigned Opcode64Bit = AArch64::MRS;
4093 const auto *TheReg =
4094 AArch64SysReg::lookupSysRegByName(RegString->getString());
4095 if (TheReg && TheReg->Readable &&
4096 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4097 Imm = TheReg->Encoding;
4103 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4104 Opcode64Bit = AArch64::ADR;
4112 SDValue InChain =
N->getOperand(0);
4113 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4114 if (!ReadIs128Bit) {
4115 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4116 {SysRegImm, InChain});
4118 SDNode *MRRS = CurDAG->getMachineNode(
4120 {MVT::Untyped , MVT::Other },
4121 {SysRegImm, InChain});
4125 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4127 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4133 ReplaceUses(
SDValue(
N, 2), OutChain);
4142bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4144 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4147 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4149 if (!WriteIs128Bit) {
4155 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4158 "Expected a constant integer expression.");
4159 unsigned Reg = PMapper->Encoding;
4160 uint64_t Immed =
N->getConstantOperandVal(2);
4161 CurDAG->SelectNodeTo(
4162 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4163 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4169 if (trySelectPState(
4170 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4171 AArch64::MSRpstateImm4))
4173 if (trySelectPState(
4174 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4175 AArch64::MSRpstateImm1))
4184 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4185 if (TheReg && TheReg->Writeable &&
4186 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4187 Imm = TheReg->Encoding;
4196 if (!WriteIs128Bit) {
4197 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4198 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4199 N->getOperand(2), InChain);
4203 SDNode *Pair = CurDAG->getMachineNode(
4204 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4205 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4208 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4210 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4212 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4213 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4221bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4226 if (Subtarget->hasLSE())
return false;
4228 if (MemTy == MVT::i8)
4229 Opcode = AArch64::CMP_SWAP_8;
4230 else if (MemTy == MVT::i16)
4231 Opcode = AArch64::CMP_SWAP_16;
4232 else if (MemTy == MVT::i32)
4233 Opcode = AArch64::CMP_SWAP_32;
4234 else if (MemTy == MVT::i64)
4235 Opcode = AArch64::CMP_SWAP_64;
4239 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4240 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4242 SDNode *CmpSwap = CurDAG->getMachineNode(
4244 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4251 CurDAG->RemoveDeadNode(
N);
4256bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4257 SDValue &Shift,
bool Negate) {
4271 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4278 if ((Val & ~0xff) == 0) {
4279 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4284 if ((Val & ~0xff00) == 0) {
4285 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4297bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4321 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4322 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4329 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4330 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4334 if (Val <= 65280 && Val % 256 == 0) {
4335 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4336 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4347bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4357 int32_t ImmVal, ShiftVal;
4362 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4363 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4367bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4369 int64_t ImmVal = CNode->getSExtValue();
4371 if (ImmVal >= -128 && ImmVal < 128) {
4372 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4379bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4381 uint64_t ImmVal = CNode->getZExtValue();
4391 ImmVal &= 0xFFFFFFFF;
4400 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4407bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4411 ImmVal = CI->getZExtValue();
4413 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4424 ImmVal |= ImmVal << 8;
4425 ImmVal |= ImmVal << 16;
4426 ImmVal |= ImmVal << 32;
4430 ImmVal |= ImmVal << 16;
4431 ImmVal |= ImmVal << 32;
4434 ImmVal &= 0xFFFFFFFF;
4435 ImmVal |= ImmVal << 32;
4447 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4456bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4457 uint64_t
High,
bool AllowSaturation,
4460 uint64_t ImmVal = CN->getZExtValue();
4467 if (ImmVal >
High) {
4468 if (!AllowSaturation)
4473 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4480bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4494 const TargetLowering *TLI = getTargetLowering();
4497 SDValue FiOp = CurDAG->getTargetFrameIndex(
4499 int TagOffset =
N->getConstantOperandVal(3);
4501 SDNode *Out = CurDAG->getMachineNode(
4502 AArch64::TAGPstack,
DL, MVT::i64,
4503 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4504 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4505 ReplaceNode(
N, Out);
4509void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4511 "llvm.aarch64.tagp third argument must be an immediate");
4512 if (trySelectStackSlotTagP(
N))
4519 int TagOffset =
N->getConstantOperandVal(3);
4520 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4521 {
N->getOperand(1),
N->getOperand(2)});
4522 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4523 {
SDValue(N1, 0),
N->getOperand(2)});
4524 SDNode *N3 = CurDAG->getMachineNode(
4525 AArch64::ADDG,
DL, MVT::i64,
4526 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4527 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4531bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4535 if (
N->getConstantOperandVal(2) != 0)
4537 if (!
N->getOperand(0).isUndef())
4541 EVT VT =
N->getValueType(0);
4542 EVT InVT =
N->getOperand(1).getValueType();
4553 "Expected to insert into a packed scalable vector!");
4556 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4557 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4558 N->getOperand(1), RC));
4562bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4566 if (
N->getConstantOperandVal(1) != 0)
4570 EVT VT =
N->getValueType(0);
4571 EVT InVT =
N->getOperand(0).getValueType();
4582 "Expected to extract from a packed scalable vector!");
4585 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4586 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4587 N->getOperand(0), RC));
4591bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4597 EVT VT =
N->getValueType(0);
4610 (Subtarget->hasSVE2() ||
4611 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4612 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4615 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4619 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4620 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4621 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4628 bool IsXOROperand =
true;
4630 IsXOROperand =
false;
4636 APInt ShlAmt, ShrAmt;
4644 if (!IsXOROperand) {
4646 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4649 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4650 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4651 VT, Zero, MOVIV, ZSub);
4662 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4663 AArch64::XAR_ZZZI_D})) {
4664 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4689 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4699 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4707 bool IsXOROperand =
true;
4709 IsXOROperand =
false;
4712 R1 =
XOR.getOperand(0);
4713 R2 =
XOR.getOperand(1);
4723 if (ShAmt + HsAmt != VTSizeInBits)
4726 if (!IsXOROperand) {
4729 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4738 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4744 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4745 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4747 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4750 if (
R2.getValueType() == VT)
4751 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4759 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4764 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4770 SDNode *XAR =
nullptr;
4774 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4775 AArch64::XAR_ZZZI_D}))
4776 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4778 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4781 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4787 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4788 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4791 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4792 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4798 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4802 ReplaceNode(
N, XAR);
4806void AArch64DAGToDAGISel::Select(SDNode *Node) {
4808 if (
Node->isMachineOpcode()) {
4810 Node->setNodeId(-1);
4815 EVT VT =
Node->getValueType(0);
4817 switch (
Node->getOpcode()) {
4821 case ISD::ATOMIC_CMP_SWAP:
4822 if (SelectCMP_SWAP(Node))
4827 case AArch64ISD::MRRS:
4828 if (tryReadRegister(Node))
4833 case AArch64ISD::MSRR:
4834 if (tryWriteRegister(Node))
4841 if (tryIndexedLoad(Node))
4850 if (tryBitfieldExtractOp(Node))
4852 if (tryBitfieldInsertInZeroOp(Node))
4857 if (tryShiftAmountMod(Node))
4862 if (tryBitfieldExtractOpFromSExt(Node))
4867 if (tryBitfieldInsertOp(Node))
4869 if (trySelectXAR(Node))
4874 if (trySelectCastScalableToFixedLengthVector(Node))
4880 if (trySelectCastFixedLengthToScalableVector(Node))
4889 if (ConstNode->
isZero()) {
4890 if (VT == MVT::i32) {
4892 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4893 ReplaceNode(Node,
New.getNode());
4895 }
else if (VT == MVT::i64) {
4897 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4898 ReplaceNode(Node,
New.getNode());
4909 const TargetLowering *TLI = getTargetLowering();
4910 SDValue TFI = CurDAG->getTargetFrameIndex(
4913 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4914 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4915 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4919 unsigned IntNo =
Node->getConstantOperandVal(1);
4923 case Intrinsic::aarch64_gcsss: {
4927 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4929 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4930 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4931 MVT::Other, Zero,
SDValue(SS1, 0));
4932 ReplaceNode(Node, SS2);
4935 case Intrinsic::aarch64_ldaxp:
4936 case Intrinsic::aarch64_ldxp: {
4938 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4943 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4944 MVT::Other, MemAddr, Chain);
4947 MachineMemOperand *MemOp =
4950 ReplaceNode(Node, Ld);
4953 case Intrinsic::aarch64_stlxp:
4954 case Intrinsic::aarch64_stxp: {
4956 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4964 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4966 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4968 MachineMemOperand *MemOp =
4972 ReplaceNode(Node, St);
4975 case Intrinsic::aarch64_neon_ld1x2:
4976 if (VT == MVT::v8i8) {
4977 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4979 }
else if (VT == MVT::v16i8) {
4980 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4982 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4983 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4985 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4986 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4988 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4989 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4991 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4992 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4994 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4995 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4997 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4998 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5002 case Intrinsic::aarch64_neon_ld1x3:
5003 if (VT == MVT::v8i8) {
5004 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5006 }
else if (VT == MVT::v16i8) {
5007 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5009 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5010 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5012 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5013 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5015 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5016 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5018 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5019 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5021 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5022 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5024 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5025 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5029 case Intrinsic::aarch64_neon_ld1x4:
5030 if (VT == MVT::v8i8) {
5031 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5033 }
else if (VT == MVT::v16i8) {
5034 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5036 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5037 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5039 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5040 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5042 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5043 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5045 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5046 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5048 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5049 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5051 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5052 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5056 case Intrinsic::aarch64_neon_ld2:
5057 if (VT == MVT::v8i8) {
5058 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5060 }
else if (VT == MVT::v16i8) {
5061 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5063 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5064 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5066 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5067 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5069 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5070 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5072 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5073 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5075 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5076 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5078 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5079 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5083 case Intrinsic::aarch64_neon_ld3:
5084 if (VT == MVT::v8i8) {
5085 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5087 }
else if (VT == MVT::v16i8) {
5088 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5090 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5091 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5093 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5094 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5096 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5097 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5099 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5100 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5102 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5103 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5105 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5106 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5110 case Intrinsic::aarch64_neon_ld4:
5111 if (VT == MVT::v8i8) {
5112 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5114 }
else if (VT == MVT::v16i8) {
5115 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5117 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5118 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5120 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5121 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5123 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5124 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5126 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5127 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5129 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5130 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5132 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5133 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5137 case Intrinsic::aarch64_neon_ld2r:
5138 if (VT == MVT::v8i8) {
5139 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5141 }
else if (VT == MVT::v16i8) {
5142 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5144 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5145 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5147 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5148 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5150 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5151 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5153 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5154 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5156 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5157 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5159 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5160 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5164 case Intrinsic::aarch64_neon_ld3r:
5165 if (VT == MVT::v8i8) {
5166 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5168 }
else if (VT == MVT::v16i8) {
5169 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5171 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5172 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5174 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5175 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5177 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5178 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5180 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5181 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5183 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5184 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5186 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5187 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5191 case Intrinsic::aarch64_neon_ld4r:
5192 if (VT == MVT::v8i8) {
5193 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5195 }
else if (VT == MVT::v16i8) {
5196 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5198 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5199 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5201 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5202 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5204 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5205 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5207 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5208 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5210 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5211 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5213 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5214 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5218 case Intrinsic::aarch64_neon_ld2lane:
5219 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5220 SelectLoadLane(Node, 2, AArch64::LD2i8);
5222 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5223 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5224 SelectLoadLane(Node, 2, AArch64::LD2i16);
5226 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5228 SelectLoadLane(Node, 2, AArch64::LD2i32);
5230 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5232 SelectLoadLane(Node, 2, AArch64::LD2i64);
5236 case Intrinsic::aarch64_neon_ld3lane:
5237 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5238 SelectLoadLane(Node, 3, AArch64::LD3i8);
5240 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5241 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5242 SelectLoadLane(Node, 3, AArch64::LD3i16);
5244 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5246 SelectLoadLane(Node, 3, AArch64::LD3i32);
5248 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5250 SelectLoadLane(Node, 3, AArch64::LD3i64);
5254 case Intrinsic::aarch64_neon_ld4lane:
5255 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5256 SelectLoadLane(Node, 4, AArch64::LD4i8);
5258 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5259 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5260 SelectLoadLane(Node, 4, AArch64::LD4i16);
5262 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5264 SelectLoadLane(Node, 4, AArch64::LD4i32);
5266 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5268 SelectLoadLane(Node, 4, AArch64::LD4i64);
5272 case Intrinsic::aarch64_ld64b:
5273 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5275 case Intrinsic::aarch64_sve_ld2q_sret: {
5276 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5279 case Intrinsic::aarch64_sve_ld3q_sret: {
5280 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5283 case Intrinsic::aarch64_sve_ld4q_sret: {
5284 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5287 case Intrinsic::aarch64_sve_ld2_sret: {
5288 if (VT == MVT::nxv16i8) {
5289 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5292 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5293 VT == MVT::nxv8bf16) {
5294 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5297 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5298 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5301 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5302 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5308 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5309 if (VT == MVT::nxv16i8) {
5310 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5311 SelectContiguousMultiVectorLoad(
5312 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5313 else if (Subtarget->hasSVE2p1())
5314 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5319 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5320 VT == MVT::nxv8bf16) {
5321 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5322 SelectContiguousMultiVectorLoad(
5323 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5324 else if (Subtarget->hasSVE2p1())
5325 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5330 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5331 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5332 SelectContiguousMultiVectorLoad(
5333 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5334 else if (Subtarget->hasSVE2p1())
5335 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5340 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5341 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5342 SelectContiguousMultiVectorLoad(
5343 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5344 else if (Subtarget->hasSVE2p1())
5345 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5353 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5354 if (VT == MVT::nxv16i8) {
5355 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5356 SelectContiguousMultiVectorLoad(
5357 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5358 else if (Subtarget->hasSVE2p1())
5359 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5364 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5365 VT == MVT::nxv8bf16) {
5366 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5367 SelectContiguousMultiVectorLoad(
5368 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5369 else if (Subtarget->hasSVE2p1())
5370 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5375 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5376 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5377 SelectContiguousMultiVectorLoad(
5378 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5379 else if (Subtarget->hasSVE2p1())
5380 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5385 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5386 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5387 SelectContiguousMultiVectorLoad(
5388 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5389 else if (Subtarget->hasSVE2p1())
5390 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5398 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5399 if (VT == MVT::nxv16i8) {
5400 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5401 SelectContiguousMultiVectorLoad(Node, 2, 0,
5402 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5403 AArch64::LDNT1B_2Z_PSEUDO);
5404 else if (Subtarget->hasSVE2p1())
5405 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5406 AArch64::LDNT1B_2Z);
5410 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5411 VT == MVT::nxv8bf16) {
5412 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5413 SelectContiguousMultiVectorLoad(Node, 2, 1,
5414 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5415 AArch64::LDNT1H_2Z_PSEUDO);
5416 else if (Subtarget->hasSVE2p1())
5417 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5418 AArch64::LDNT1H_2Z);
5422 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5423 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5424 SelectContiguousMultiVectorLoad(Node, 2, 2,
5425 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5426 AArch64::LDNT1W_2Z_PSEUDO);
5427 else if (Subtarget->hasSVE2p1())
5428 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5429 AArch64::LDNT1W_2Z);
5433 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5434 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5435 SelectContiguousMultiVectorLoad(Node, 2, 3,
5436 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5437 AArch64::LDNT1D_2Z_PSEUDO);
5438 else if (Subtarget->hasSVE2p1())
5439 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5440 AArch64::LDNT1D_2Z);
5447 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5448 if (VT == MVT::nxv16i8) {
5449 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5450 SelectContiguousMultiVectorLoad(Node, 4, 0,
5451 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5452 AArch64::LDNT1B_4Z_PSEUDO);
5453 else if (Subtarget->hasSVE2p1())
5454 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5455 AArch64::LDNT1B_4Z);
5459 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5460 VT == MVT::nxv8bf16) {
5461 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5462 SelectContiguousMultiVectorLoad(Node, 4, 1,
5463 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5464 AArch64::LDNT1H_4Z_PSEUDO);
5465 else if (Subtarget->hasSVE2p1())
5466 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5467 AArch64::LDNT1H_4Z);
5471 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5472 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5473 SelectContiguousMultiVectorLoad(Node, 4, 2,
5474 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5475 AArch64::LDNT1W_4Z_PSEUDO);
5476 else if (Subtarget->hasSVE2p1())
5477 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5478 AArch64::LDNT1W_4Z);
5482 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5483 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5484 SelectContiguousMultiVectorLoad(Node, 4, 3,
5485 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5486 AArch64::LDNT1D_4Z_PSEUDO);
5487 else if (Subtarget->hasSVE2p1())
5488 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5489 AArch64::LDNT1D_4Z);
5496 case Intrinsic::aarch64_sve_ld3_sret: {
5497 if (VT == MVT::nxv16i8) {
5498 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5501 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5502 VT == MVT::nxv8bf16) {
5503 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5506 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5507 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5510 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5511 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5517 case Intrinsic::aarch64_sve_ld4_sret: {
5518 if (VT == MVT::nxv16i8) {
5519 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5522 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5523 VT == MVT::nxv8bf16) {
5524 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5527 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5528 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5531 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5532 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5538 case Intrinsic::aarch64_sme_read_hor_vg2: {
5539 if (VT == MVT::nxv16i8) {
5540 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5541 AArch64::MOVA_2ZMXI_H_B);
5543 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5544 VT == MVT::nxv8bf16) {
5545 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5546 AArch64::MOVA_2ZMXI_H_H);
5548 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5549 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5550 AArch64::MOVA_2ZMXI_H_S);
5552 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5553 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5554 AArch64::MOVA_2ZMXI_H_D);
5559 case Intrinsic::aarch64_sme_read_ver_vg2: {
5560 if (VT == MVT::nxv16i8) {
5561 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5562 AArch64::MOVA_2ZMXI_V_B);
5564 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5565 VT == MVT::nxv8bf16) {
5566 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5567 AArch64::MOVA_2ZMXI_V_H);
5569 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5570 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5571 AArch64::MOVA_2ZMXI_V_S);
5573 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5574 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5575 AArch64::MOVA_2ZMXI_V_D);
5580 case Intrinsic::aarch64_sme_read_hor_vg4: {
5581 if (VT == MVT::nxv16i8) {
5582 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5583 AArch64::MOVA_4ZMXI_H_B);
5585 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5586 VT == MVT::nxv8bf16) {
5587 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5588 AArch64::MOVA_4ZMXI_H_H);
5590 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5591 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5592 AArch64::MOVA_4ZMXI_H_S);
5594 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5595 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5596 AArch64::MOVA_4ZMXI_H_D);
5601 case Intrinsic::aarch64_sme_read_ver_vg4: {
5602 if (VT == MVT::nxv16i8) {
5603 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5604 AArch64::MOVA_4ZMXI_V_B);
5606 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5607 VT == MVT::nxv8bf16) {
5608 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5609 AArch64::MOVA_4ZMXI_V_H);
5611 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5612 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5613 AArch64::MOVA_4ZMXI_V_S);
5615 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5616 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5617 AArch64::MOVA_4ZMXI_V_D);
5622 case Intrinsic::aarch64_sme_read_vg1x2: {
5623 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5624 AArch64::MOVA_VG2_2ZMXI);
5627 case Intrinsic::aarch64_sme_read_vg1x4: {
5628 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5629 AArch64::MOVA_VG4_4ZMXI);
5632 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5633 if (VT == MVT::nxv16i8) {
5634 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5636 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5637 VT == MVT::nxv8bf16) {
5638 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5640 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5641 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5643 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5644 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5649 case Intrinsic::aarch64_sme_readz_vert_x2: {
5650 if (VT == MVT::nxv16i8) {
5651 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5653 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5654 VT == MVT::nxv8bf16) {
5655 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5657 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5658 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5660 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5661 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5666 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5667 if (VT == MVT::nxv16i8) {
5668 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5670 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5671 VT == MVT::nxv8bf16) {
5672 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5674 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5675 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5677 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5678 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5683 case Intrinsic::aarch64_sme_readz_vert_x4: {
5684 if (VT == MVT::nxv16i8) {
5685 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5687 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5688 VT == MVT::nxv8bf16) {
5689 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5691 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5692 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5694 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5695 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5700 case Intrinsic::aarch64_sme_readz_x2: {
5701 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5705 case Intrinsic::aarch64_sme_readz_x4: {
5706 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5710 case Intrinsic::swift_async_context_addr: {
5713 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5715 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5716 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5717 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5719 ReplaceUses(
SDValue(Node, 0), Res);
5721 CurDAG->RemoveDeadNode(Node);
5723 auto &MF = CurDAG->getMachineFunction();
5724 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5725 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5728 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5730 Node->getValueType(0),
5731 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5732 AArch64::LUTI2_4ZTZI_S}))
5734 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5737 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5739 Node->getValueType(0),
5740 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5742 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5745 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5747 Node->getValueType(0),
5748 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5749 AArch64::LUTI2_2ZTZI_S}))
5751 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5754 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5756 Node->getValueType(0),
5757 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5758 AArch64::LUTI4_2ZTZI_S}))
5760 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5763 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5764 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5767 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5769 Node->getValueType(0),
5770 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5771 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5773 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5775 Node->getValueType(0),
5776 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5777 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5779 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5781 Node->getValueType(0),
5782 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5783 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5785 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5787 Node->getValueType(0),
5788 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5789 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5794 unsigned IntNo =
Node->getConstantOperandVal(0);
5798 case Intrinsic::aarch64_tagp:
5802 case Intrinsic::ptrauth_auth:
5803 SelectPtrauthAuth(Node);
5806 case Intrinsic::ptrauth_resign:
5807 SelectPtrauthResign(Node);
5810 case Intrinsic::aarch64_neon_tbl2:
5811 SelectTable(Node, 2,
5812 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5815 case Intrinsic::aarch64_neon_tbl3:
5816 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5817 : AArch64::TBLv16i8Three,
5820 case Intrinsic::aarch64_neon_tbl4:
5821 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5822 : AArch64::TBLv16i8Four,
5825 case Intrinsic::aarch64_neon_tbx2:
5826 SelectTable(Node, 2,
5827 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5830 case Intrinsic::aarch64_neon_tbx3:
5831 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5832 : AArch64::TBXv16i8Three,
5835 case Intrinsic::aarch64_neon_tbx4:
5836 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5837 : AArch64::TBXv16i8Four,
5840 case Intrinsic::aarch64_sve_srshl_single_x2:
5842 Node->getValueType(0),
5843 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5844 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5845 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5847 case Intrinsic::aarch64_sve_srshl_single_x4:
5849 Node->getValueType(0),
5850 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5851 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5852 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5854 case Intrinsic::aarch64_sve_urshl_single_x2:
5856 Node->getValueType(0),
5857 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5858 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5859 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5861 case Intrinsic::aarch64_sve_urshl_single_x4:
5863 Node->getValueType(0),
5864 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5865 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5866 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5868 case Intrinsic::aarch64_sve_srshl_x2:
5870 Node->getValueType(0),
5871 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5872 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5873 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5875 case Intrinsic::aarch64_sve_srshl_x4:
5877 Node->getValueType(0),
5878 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5879 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5880 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5882 case Intrinsic::aarch64_sve_urshl_x2:
5884 Node->getValueType(0),
5885 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5886 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5887 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5889 case Intrinsic::aarch64_sve_urshl_x4:
5891 Node->getValueType(0),
5892 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5893 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5894 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5896 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5898 Node->getValueType(0),
5899 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5900 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5901 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5903 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5905 Node->getValueType(0),
5906 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5907 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5908 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5910 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5912 Node->getValueType(0),
5913 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5914 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5915 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5917 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5919 Node->getValueType(0),
5920 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5921 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5922 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5924 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5926 Node->getValueType(0),
5927 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5928 AArch64::FSCALE_2ZZ_D}))
5929 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5931 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5933 Node->getValueType(0),
5934 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5935 AArch64::FSCALE_4ZZ_D}))
5936 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5938 case Intrinsic::aarch64_sme_fp8_scale_x2:
5940 Node->getValueType(0),
5941 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5942 AArch64::FSCALE_2Z2Z_D}))
5943 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5945 case Intrinsic::aarch64_sme_fp8_scale_x4:
5947 Node->getValueType(0),
5948 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5949 AArch64::FSCALE_4Z4Z_D}))
5950 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5952 case Intrinsic::aarch64_sve_whilege_x2:
5954 Node->getValueType(0),
5955 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5956 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5957 SelectWhilePair(Node,
Op);
5959 case Intrinsic::aarch64_sve_whilegt_x2:
5961 Node->getValueType(0),
5962 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5963 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5964 SelectWhilePair(Node,
Op);
5966 case Intrinsic::aarch64_sve_whilehi_x2:
5968 Node->getValueType(0),
5969 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5970 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5971 SelectWhilePair(Node,
Op);
5973 case Intrinsic::aarch64_sve_whilehs_x2:
5975 Node->getValueType(0),
5976 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5977 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5978 SelectWhilePair(Node,
Op);
5980 case Intrinsic::aarch64_sve_whilele_x2:
5982 Node->getValueType(0),
5983 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5984 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5985 SelectWhilePair(Node,
Op);
5987 case Intrinsic::aarch64_sve_whilelo_x2:
5989 Node->getValueType(0),
5990 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5991 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5992 SelectWhilePair(Node,
Op);
5994 case Intrinsic::aarch64_sve_whilels_x2:
5996 Node->getValueType(0),
5997 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5998 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5999 SelectWhilePair(Node,
Op);
6001 case Intrinsic::aarch64_sve_whilelt_x2:
6003 Node->getValueType(0),
6004 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6005 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6006 SelectWhilePair(Node,
Op);
6008 case Intrinsic::aarch64_sve_smax_single_x2:
6010 Node->getValueType(0),
6011 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6012 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6013 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6015 case Intrinsic::aarch64_sve_umax_single_x2:
6017 Node->getValueType(0),
6018 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6019 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6020 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6022 case Intrinsic::aarch64_sve_fmax_single_x2:
6024 Node->getValueType(0),
6025 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6026 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6027 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6029 case Intrinsic::aarch64_sve_smax_single_x4:
6031 Node->getValueType(0),
6032 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6033 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6034 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6036 case Intrinsic::aarch64_sve_umax_single_x4:
6038 Node->getValueType(0),
6039 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6040 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6041 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6043 case Intrinsic::aarch64_sve_fmax_single_x4:
6045 Node->getValueType(0),
6046 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6047 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6048 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6050 case Intrinsic::aarch64_sve_smin_single_x2:
6052 Node->getValueType(0),
6053 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6054 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6055 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6057 case Intrinsic::aarch64_sve_umin_single_x2:
6059 Node->getValueType(0),
6060 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6061 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6062 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6064 case Intrinsic::aarch64_sve_fmin_single_x2:
6066 Node->getValueType(0),
6067 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6068 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6069 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6071 case Intrinsic::aarch64_sve_smin_single_x4:
6073 Node->getValueType(0),
6074 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6075 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6076 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6078 case Intrinsic::aarch64_sve_umin_single_x4:
6080 Node->getValueType(0),
6081 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6082 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6083 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6085 case Intrinsic::aarch64_sve_fmin_single_x4:
6087 Node->getValueType(0),
6088 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6089 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6090 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6092 case Intrinsic::aarch64_sve_smax_x2:
6094 Node->getValueType(0),
6095 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6096 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6097 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6099 case Intrinsic::aarch64_sve_umax_x2:
6101 Node->getValueType(0),
6102 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6103 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6104 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6106 case Intrinsic::aarch64_sve_fmax_x2:
6108 Node->getValueType(0),
6109 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6110 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6111 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6113 case Intrinsic::aarch64_sve_smax_x4:
6115 Node->getValueType(0),
6116 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6117 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6118 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6120 case Intrinsic::aarch64_sve_umax_x4:
6122 Node->getValueType(0),
6123 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6124 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6125 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6127 case Intrinsic::aarch64_sve_fmax_x4:
6129 Node->getValueType(0),
6130 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6131 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6132 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6134 case Intrinsic::aarch64_sme_famax_x2:
6136 Node->getValueType(0),
6137 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6138 AArch64::FAMAX_2Z2Z_D}))
6139 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6141 case Intrinsic::aarch64_sme_famax_x4:
6143 Node->getValueType(0),
6144 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6145 AArch64::FAMAX_4Z4Z_D}))
6146 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6148 case Intrinsic::aarch64_sme_famin_x2:
6150 Node->getValueType(0),
6151 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6152 AArch64::FAMIN_2Z2Z_D}))
6153 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6155 case Intrinsic::aarch64_sme_famin_x4:
6157 Node->getValueType(0),
6158 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6159 AArch64::FAMIN_4Z4Z_D}))
6160 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6162 case Intrinsic::aarch64_sve_smin_x2:
6164 Node->getValueType(0),
6165 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6166 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6167 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6169 case Intrinsic::aarch64_sve_umin_x2:
6171 Node->getValueType(0),
6172 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6173 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6174 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6176 case Intrinsic::aarch64_sve_fmin_x2:
6178 Node->getValueType(0),
6179 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6180 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6181 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6183 case Intrinsic::aarch64_sve_smin_x4:
6185 Node->getValueType(0),
6186 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6187 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6188 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6190 case Intrinsic::aarch64_sve_umin_x4:
6192 Node->getValueType(0),
6193 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6194 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6195 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6197 case Intrinsic::aarch64_sve_fmin_x4:
6199 Node->getValueType(0),
6200 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6201 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6202 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6204 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6206 Node->getValueType(0),
6207 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6208 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6209 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6211 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6213 Node->getValueType(0),
6214 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6215 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6216 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6218 case Intrinsic::aarch64_sve_fminnm_single_x2:
6220 Node->getValueType(0),
6221 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6222 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6223 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6225 case Intrinsic::aarch64_sve_fminnm_single_x4:
6227 Node->getValueType(0),
6228 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6229 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6230 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6232 case Intrinsic::aarch64_sve_fmaxnm_x2:
6234 Node->getValueType(0),
6235 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6236 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6237 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6239 case Intrinsic::aarch64_sve_fmaxnm_x4:
6241 Node->getValueType(0),
6242 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6243 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6244 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6246 case Intrinsic::aarch64_sve_fminnm_x2:
6248 Node->getValueType(0),
6249 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6250 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6251 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6253 case Intrinsic::aarch64_sve_fminnm_x4:
6255 Node->getValueType(0),
6256 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6257 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6258 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6260 case Intrinsic::aarch64_sve_fcvtzs_x2:
6261 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6263 case Intrinsic::aarch64_sve_scvtf_x2:
6264 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6266 case Intrinsic::aarch64_sve_fcvtzu_x2:
6267 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6269 case Intrinsic::aarch64_sve_ucvtf_x2:
6270 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6272 case Intrinsic::aarch64_sve_fcvtzs_x4:
6273 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6275 case Intrinsic::aarch64_sve_scvtf_x4:
6276 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6278 case Intrinsic::aarch64_sve_fcvtzu_x4:
6279 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6281 case Intrinsic::aarch64_sve_ucvtf_x4:
6282 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6284 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6285 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6287 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6288 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6290 case Intrinsic::aarch64_sve_sclamp_single_x2:
6292 Node->getValueType(0),
6293 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6294 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6295 SelectClamp(Node, 2,
Op);
6297 case Intrinsic::aarch64_sve_uclamp_single_x2:
6299 Node->getValueType(0),
6300 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6301 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6302 SelectClamp(Node, 2,
Op);
6304 case Intrinsic::aarch64_sve_fclamp_single_x2:
6306 Node->getValueType(0),
6307 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6308 AArch64::FCLAMP_VG2_2Z2Z_D}))
6309 SelectClamp(Node, 2,
Op);
6311 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6312 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6314 case Intrinsic::aarch64_sve_sclamp_single_x4:
6316 Node->getValueType(0),
6317 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6318 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6319 SelectClamp(Node, 4,
Op);
6321 case Intrinsic::aarch64_sve_uclamp_single_x4:
6323 Node->getValueType(0),
6324 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6325 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6326 SelectClamp(Node, 4,
Op);
6328 case Intrinsic::aarch64_sve_fclamp_single_x4:
6330 Node->getValueType(0),
6331 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6332 AArch64::FCLAMP_VG4_4Z4Z_D}))
6333 SelectClamp(Node, 4,
Op);
6335 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6336 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6338 case Intrinsic::aarch64_sve_add_single_x2:
6340 Node->getValueType(0),
6341 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6342 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6343 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6345 case Intrinsic::aarch64_sve_add_single_x4:
6347 Node->getValueType(0),
6348 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6349 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6350 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6352 case Intrinsic::aarch64_sve_zip_x2:
6354 Node->getValueType(0),
6355 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6356 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6357 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6359 case Intrinsic::aarch64_sve_zipq_x2:
6360 SelectUnaryMultiIntrinsic(Node, 2,
false,
6361 AArch64::ZIP_VG2_2ZZZ_Q);
6363 case Intrinsic::aarch64_sve_zip_x4:
6365 Node->getValueType(0),
6366 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6367 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6368 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6370 case Intrinsic::aarch64_sve_zipq_x4:
6371 SelectUnaryMultiIntrinsic(Node, 4,
true,
6372 AArch64::ZIP_VG4_4Z4Z_Q);
6374 case Intrinsic::aarch64_sve_uzp_x2:
6376 Node->getValueType(0),
6377 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6378 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6379 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6381 case Intrinsic::aarch64_sve_uzpq_x2:
6382 SelectUnaryMultiIntrinsic(Node, 2,
false,
6383 AArch64::UZP_VG2_2ZZZ_Q);
6385 case Intrinsic::aarch64_sve_uzp_x4:
6387 Node->getValueType(0),
6388 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6389 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6390 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6392 case Intrinsic::aarch64_sve_uzpq_x4:
6393 SelectUnaryMultiIntrinsic(Node, 4,
true,
6394 AArch64::UZP_VG4_4Z4Z_Q);
6396 case Intrinsic::aarch64_sve_sel_x2:
6398 Node->getValueType(0),
6399 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6400 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6401 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6403 case Intrinsic::aarch64_sve_sel_x4:
6405 Node->getValueType(0),
6406 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6407 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6408 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6410 case Intrinsic::aarch64_sve_frinta_x2:
6411 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6413 case Intrinsic::aarch64_sve_frinta_x4:
6414 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6416 case Intrinsic::aarch64_sve_frintm_x2:
6417 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6419 case Intrinsic::aarch64_sve_frintm_x4:
6420 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6422 case Intrinsic::aarch64_sve_frintn_x2:
6423 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6425 case Intrinsic::aarch64_sve_frintn_x4:
6426 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6428 case Intrinsic::aarch64_sve_frintp_x2:
6429 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6431 case Intrinsic::aarch64_sve_frintp_x4:
6432 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6434 case Intrinsic::aarch64_sve_sunpk_x2:
6436 Node->getValueType(0),
6437 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6438 AArch64::SUNPK_VG2_2ZZ_D}))
6439 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6441 case Intrinsic::aarch64_sve_uunpk_x2:
6443 Node->getValueType(0),
6444 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6445 AArch64::UUNPK_VG2_2ZZ_D}))
6446 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6448 case Intrinsic::aarch64_sve_sunpk_x4:
6450 Node->getValueType(0),
6451 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6452 AArch64::SUNPK_VG4_4Z2Z_D}))
6453 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6455 case Intrinsic::aarch64_sve_uunpk_x4:
6457 Node->getValueType(0),
6458 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6459 AArch64::UUNPK_VG4_4Z2Z_D}))
6460 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6462 case Intrinsic::aarch64_sve_pext_x2: {
6464 Node->getValueType(0),
6465 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6466 AArch64::PEXT_2PCI_D}))
6467 SelectPExtPair(Node,
Op);
6474 unsigned IntNo =
Node->getConstantOperandVal(1);
6475 if (
Node->getNumOperands() >= 3)
6476 VT =
Node->getOperand(2)->getValueType(0);
6480 case Intrinsic::aarch64_neon_st1x2: {
6481 if (VT == MVT::v8i8) {
6482 SelectStore(Node, 2, AArch64::ST1Twov8b);
6484 }
else if (VT == MVT::v16i8) {
6485 SelectStore(Node, 2, AArch64::ST1Twov16b);
6487 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6488 VT == MVT::v4bf16) {
6489 SelectStore(Node, 2, AArch64::ST1Twov4h);
6491 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6492 VT == MVT::v8bf16) {
6493 SelectStore(Node, 2, AArch64::ST1Twov8h);
6495 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6496 SelectStore(Node, 2, AArch64::ST1Twov2s);
6498 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6499 SelectStore(Node, 2, AArch64::ST1Twov4s);
6501 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6502 SelectStore(Node, 2, AArch64::ST1Twov2d);
6504 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6505 SelectStore(Node, 2, AArch64::ST1Twov1d);
6510 case Intrinsic::aarch64_neon_st1x3: {
6511 if (VT == MVT::v8i8) {
6512 SelectStore(Node, 3, AArch64::ST1Threev8b);
6514 }
else if (VT == MVT::v16i8) {
6515 SelectStore(Node, 3, AArch64::ST1Threev16b);
6517 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6518 VT == MVT::v4bf16) {
6519 SelectStore(Node, 3, AArch64::ST1Threev4h);
6521 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6522 VT == MVT::v8bf16) {
6523 SelectStore(Node, 3, AArch64::ST1Threev8h);
6525 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6526 SelectStore(Node, 3, AArch64::ST1Threev2s);
6528 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6529 SelectStore(Node, 3, AArch64::ST1Threev4s);
6531 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6532 SelectStore(Node, 3, AArch64::ST1Threev2d);
6534 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6535 SelectStore(Node, 3, AArch64::ST1Threev1d);
6540 case Intrinsic::aarch64_neon_st1x4: {
6541 if (VT == MVT::v8i8) {
6542 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6544 }
else if (VT == MVT::v16i8) {
6545 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6547 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6548 VT == MVT::v4bf16) {
6549 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6551 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6552 VT == MVT::v8bf16) {
6553 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6555 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6556 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6558 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6559 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6561 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6562 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6564 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6565 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6570 case Intrinsic::aarch64_neon_st2: {
6571 if (VT == MVT::v8i8) {
6572 SelectStore(Node, 2, AArch64::ST2Twov8b);
6574 }
else if (VT == MVT::v16i8) {
6575 SelectStore(Node, 2, AArch64::ST2Twov16b);
6577 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6578 VT == MVT::v4bf16) {
6579 SelectStore(Node, 2, AArch64::ST2Twov4h);
6581 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6582 VT == MVT::v8bf16) {
6583 SelectStore(Node, 2, AArch64::ST2Twov8h);
6585 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6586 SelectStore(Node, 2, AArch64::ST2Twov2s);
6588 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6589 SelectStore(Node, 2, AArch64::ST2Twov4s);
6591 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6592 SelectStore(Node, 2, AArch64::ST2Twov2d);
6594 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6595 SelectStore(Node, 2, AArch64::ST1Twov1d);
6600 case Intrinsic::aarch64_neon_st3: {
6601 if (VT == MVT::v8i8) {
6602 SelectStore(Node, 3, AArch64::ST3Threev8b);
6604 }
else if (VT == MVT::v16i8) {
6605 SelectStore(Node, 3, AArch64::ST3Threev16b);
6607 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6608 VT == MVT::v4bf16) {
6609 SelectStore(Node, 3, AArch64::ST3Threev4h);
6611 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6612 VT == MVT::v8bf16) {
6613 SelectStore(Node, 3, AArch64::ST3Threev8h);
6615 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6616 SelectStore(Node, 3, AArch64::ST3Threev2s);
6618 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6619 SelectStore(Node, 3, AArch64::ST3Threev4s);
6621 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6622 SelectStore(Node, 3, AArch64::ST3Threev2d);
6624 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6625 SelectStore(Node, 3, AArch64::ST1Threev1d);
6630 case Intrinsic::aarch64_neon_st4: {
6631 if (VT == MVT::v8i8) {
6632 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6634 }
else if (VT == MVT::v16i8) {
6635 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6637 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6638 VT == MVT::v4bf16) {
6639 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6641 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6642 VT == MVT::v8bf16) {
6643 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6645 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6646 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6648 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6649 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6651 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6652 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6654 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6655 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6660 case Intrinsic::aarch64_neon_st2lane: {
6661 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6662 SelectStoreLane(Node, 2, AArch64::ST2i8);
6664 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6665 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6666 SelectStoreLane(Node, 2, AArch64::ST2i16);
6668 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6670 SelectStoreLane(Node, 2, AArch64::ST2i32);
6672 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6674 SelectStoreLane(Node, 2, AArch64::ST2i64);
6679 case Intrinsic::aarch64_neon_st3lane: {
6680 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6681 SelectStoreLane(Node, 3, AArch64::ST3i8);
6683 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6684 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6685 SelectStoreLane(Node, 3, AArch64::ST3i16);
6687 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6689 SelectStoreLane(Node, 3, AArch64::ST3i32);
6691 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6693 SelectStoreLane(Node, 3, AArch64::ST3i64);
6698 case Intrinsic::aarch64_neon_st4lane: {
6699 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6700 SelectStoreLane(Node, 4, AArch64::ST4i8);
6702 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6703 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6704 SelectStoreLane(Node, 4, AArch64::ST4i16);
6706 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6708 SelectStoreLane(Node, 4, AArch64::ST4i32);
6710 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6712 SelectStoreLane(Node, 4, AArch64::ST4i64);
6717 case Intrinsic::aarch64_sve_st2q: {
6718 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6721 case Intrinsic::aarch64_sve_st3q: {
6722 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6725 case Intrinsic::aarch64_sve_st4q: {
6726 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6729 case Intrinsic::aarch64_sve_st2: {
6730 if (VT == MVT::nxv16i8) {
6731 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6733 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6734 VT == MVT::nxv8bf16) {
6735 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6737 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6738 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6740 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6741 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6746 case Intrinsic::aarch64_sve_st3: {
6747 if (VT == MVT::nxv16i8) {
6748 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6750 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6751 VT == MVT::nxv8bf16) {
6752 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6754 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6755 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6757 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6758 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6763 case Intrinsic::aarch64_sve_st4: {
6764 if (VT == MVT::nxv16i8) {
6765 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6767 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6768 VT == MVT::nxv8bf16) {
6769 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6771 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6772 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6774 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6775 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6783 case AArch64ISD::LD2post: {
6784 if (VT == MVT::v8i8) {
6785 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6787 }
else if (VT == MVT::v16i8) {
6788 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6790 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6791 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6793 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6794 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6796 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6797 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6799 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6800 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6802 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6803 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6805 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6806 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6811 case AArch64ISD::LD3post: {
6812 if (VT == MVT::v8i8) {
6813 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6815 }
else if (VT == MVT::v16i8) {
6816 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6818 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6819 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6821 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6822 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6824 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6825 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6827 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6828 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6830 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6831 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6833 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6834 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6839 case AArch64ISD::LD4post: {
6840 if (VT == MVT::v8i8) {
6841 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6843 }
else if (VT == MVT::v16i8) {
6844 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6846 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6847 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6849 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6850 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6852 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6853 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6855 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6856 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6858 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6859 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6861 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6862 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6867 case AArch64ISD::LD1x2post: {
6868 if (VT == MVT::v8i8) {
6869 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6871 }
else if (VT == MVT::v16i8) {
6872 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6874 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6875 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6877 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6878 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6880 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6881 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6883 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6884 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6886 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6887 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6889 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6890 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6895 case AArch64ISD::LD1x3post: {
6896 if (VT == MVT::v8i8) {
6897 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6899 }
else if (VT == MVT::v16i8) {
6900 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6902 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6903 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6905 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6906 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6908 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6909 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6911 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6912 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6914 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6915 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6917 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6918 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6923 case AArch64ISD::LD1x4post: {
6924 if (VT == MVT::v8i8) {
6925 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6927 }
else if (VT == MVT::v16i8) {
6928 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6930 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6931 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6933 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6934 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6936 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6937 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6939 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6940 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6942 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6943 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6945 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6946 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6951 case AArch64ISD::LD1DUPpost: {
6952 if (VT == MVT::v8i8) {
6953 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6955 }
else if (VT == MVT::v16i8) {
6956 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6958 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6959 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6961 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6962 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6964 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6965 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6967 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6968 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
6970 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6971 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
6973 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6974 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
6979 case AArch64ISD::LD2DUPpost: {
6980 if (VT == MVT::v8i8) {
6981 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
6983 }
else if (VT == MVT::v16i8) {
6984 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
6986 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6987 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
6989 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6990 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
6992 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6993 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
6995 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6996 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
6998 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6999 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7001 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7002 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7007 case AArch64ISD::LD3DUPpost: {
7008 if (VT == MVT::v8i8) {
7009 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7011 }
else if (VT == MVT::v16i8) {
7012 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7014 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7015 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7017 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7018 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7020 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7021 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7023 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7024 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7026 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7027 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7029 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7030 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7035 case AArch64ISD::LD4DUPpost: {
7036 if (VT == MVT::v8i8) {
7037 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7039 }
else if (VT == MVT::v16i8) {
7040 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7042 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7043 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7045 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7046 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7048 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7049 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7051 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7052 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7054 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7055 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7057 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7058 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7063 case AArch64ISD::LD1LANEpost: {
7064 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7065 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7067 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7068 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7069 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7071 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7073 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7075 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7077 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7082 case AArch64ISD::LD2LANEpost: {
7083 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7084 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7086 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7087 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7088 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7090 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7092 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7094 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7096 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7101 case AArch64ISD::LD3LANEpost: {
7102 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7103 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7105 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7106 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7107 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7109 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7111 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7113 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7115 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7120 case AArch64ISD::LD4LANEpost: {
7121 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7122 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7124 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7125 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7126 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7128 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7130 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7132 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7134 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7139 case AArch64ISD::ST2post: {
7140 VT =
Node->getOperand(1).getValueType();
7141 if (VT == MVT::v8i8) {
7142 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7144 }
else if (VT == MVT::v16i8) {
7145 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7147 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7148 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7150 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7151 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7153 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7154 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7156 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7157 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7159 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7160 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7162 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7163 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7168 case AArch64ISD::ST3post: {
7169 VT =
Node->getOperand(1).getValueType();
7170 if (VT == MVT::v8i8) {
7171 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7173 }
else if (VT == MVT::v16i8) {
7174 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7176 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7177 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7179 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7180 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7182 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7183 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7185 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7186 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7188 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7189 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7191 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7192 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7197 case AArch64ISD::ST4post: {
7198 VT =
Node->getOperand(1).getValueType();
7199 if (VT == MVT::v8i8) {
7200 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7202 }
else if (VT == MVT::v16i8) {
7203 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7205 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7206 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7208 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7209 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7211 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7212 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7214 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7215 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7217 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7218 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7220 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7221 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7226 case AArch64ISD::ST1x2post: {
7227 VT =
Node->getOperand(1).getValueType();
7228 if (VT == MVT::v8i8) {
7229 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7231 }
else if (VT == MVT::v16i8) {
7232 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7234 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7235 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7237 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7238 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7240 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7241 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7243 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7244 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7246 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7247 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7249 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7250 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7255 case AArch64ISD::ST1x3post: {
7256 VT =
Node->getOperand(1).getValueType();
7257 if (VT == MVT::v8i8) {
7258 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7260 }
else if (VT == MVT::v16i8) {
7261 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7263 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7264 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7266 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7267 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7269 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7270 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7272 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7273 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7275 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7276 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7278 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7279 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7284 case AArch64ISD::ST1x4post: {
7285 VT =
Node->getOperand(1).getValueType();
7286 if (VT == MVT::v8i8) {
7287 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7289 }
else if (VT == MVT::v16i8) {
7290 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7292 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7293 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7295 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7296 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7298 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7299 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7301 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7302 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7304 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7305 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7307 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7308 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7313 case AArch64ISD::ST2LANEpost: {
7314 VT =
Node->getOperand(1).getValueType();
7315 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7316 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7318 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7319 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7320 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7322 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7324 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7326 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7328 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7333 case AArch64ISD::ST3LANEpost: {
7334 VT =
Node->getOperand(1).getValueType();
7335 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7336 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7338 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7339 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7340 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7342 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7344 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7346 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7348 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7353 case AArch64ISD::ST4LANEpost: {
7354 VT =
Node->getOperand(1).getValueType();
7355 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7356 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7358 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7359 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7360 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7362 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7364 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7366 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7368 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7383 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7395 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7399 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7400 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7415 return MemIntr->getMemoryVT();
7422 DataVT = Load->getValueType(0);
7424 DataVT = Load->getValueType(0);
7426 DataVT = Store->getValue().getValueType();
7428 DataVT = Store->getValue().getValueType();
7435 const unsigned Opcode = Root->
getOpcode();
7439 case AArch64ISD::LD1_MERGE_ZERO:
7440 case AArch64ISD::LD1S_MERGE_ZERO:
7441 case AArch64ISD::LDNF1_MERGE_ZERO:
7442 case AArch64ISD::LDNF1S_MERGE_ZERO:
7444 case AArch64ISD::ST1_PRED:
7456 case Intrinsic::aarch64_sme_ldr:
7457 case Intrinsic::aarch64_sme_str:
7458 return MVT::nxv16i8;
7459 case Intrinsic::aarch64_sve_prf:
7464 case Intrinsic::aarch64_sve_ld2_sret:
7465 case Intrinsic::aarch64_sve_ld2q_sret:
7468 case Intrinsic::aarch64_sve_st2q:
7471 case Intrinsic::aarch64_sve_ld3_sret:
7472 case Intrinsic::aarch64_sve_ld3q_sret:
7475 case Intrinsic::aarch64_sve_st3q:
7478 case Intrinsic::aarch64_sve_ld4_sret:
7479 case Intrinsic::aarch64_sve_ld4q_sret:
7482 case Intrinsic::aarch64_sve_st4q:
7485 case Intrinsic::aarch64_sve_ld1udq:
7486 case Intrinsic::aarch64_sve_st1dq:
7487 return EVT(MVT::nxv1i64);
7488 case Intrinsic::aarch64_sve_ld1uwq:
7489 case Intrinsic::aarch64_sve_st1wq:
7490 return EVT(MVT::nxv1i32);
7497template <
int64_t Min,
int64_t Max>
7498bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7502 const DataLayout &
DL = CurDAG->getDataLayout();
7503 const MachineFrameInfo &MFI = MF->getFrameInfo();
7511 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7525 int64_t MulImm = std::numeric_limits<int64_t>::max();
7526 if (VScale.
getOpcode() == ISD::VSCALE) {
7529 int64_t ByteOffset =
C->getSExtValue();
7530 const auto KnownVScale =
7533 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7536 MulImm = ByteOffset / KnownVScale;
7543 if ((MulImm % MemWidthBytes) != 0)
7546 int64_t
Offset = MulImm / MemWidthBytes;
7550 Base =
N.getOperand(0);
7559 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7565bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7584 int64_t ImmOff =
C->getSExtValue();
7585 unsigned Size = 1 << Scale;
7594 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7596 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7607 if (
C->getZExtValue() == Scale) {
7616bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7617 const AArch64TargetLowering *TLI =
7618 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7623bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7624 EVT VT =
N.getValueType();
7628bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7633 int64_t ImmOff =
C->getSExtValue();
7634 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7635 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7640 if (
SDValue C = MatchConstantOffset(
N)) {
7641 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7647 if (CurDAG->isBaseWithConstantOffset(
N)) {
7648 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7649 Base =
N.getOperand(0);
7657 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7661bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7681 uint64_t LowerBound = 0, UpperBound = 64;
7699 if (CN->getAPIntValue().uge(LowerBound) &&
7700 CN->getAPIntValue().ult(UpperBound)) {
7702 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7710template <
bool MatchCBB>
7717 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7719 Reg =
N.getOperand(0);
7721 SDLoc(
N), MVT::i32);
7729 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...
static bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t &Encoding)
processLogicalImmediate - Determine if an immediate value can be encoded as the immediate operand of ...
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static constexpr unsigned SVEBitsPerBlock
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SIGN_EXTEND
Conversion operators.
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
@ Undef
Value of the register doesn't matter.
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
unsigned getBitWidth() const
Get the bit width of this value.