22#include "llvm/IR/IntrinsicsAArch64.h"
31#define DEBUG_TYPE "aarch64-isel"
32#define PASS_NAME "AArch64 Instruction Selection"
35#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
36#pragma inline_depth(0)
52 AArch64DAGToDAGISel() =
delete;
67 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
69 std::vector<SDValue> &OutOps)
override;
71 template <
signed Low,
signed High,
signed Scale>
74 template <
signed Low,
signed High>
82 return SelectShiftedRegister(
N,
false,
Reg, Shift);
85 return SelectShiftedRegister(
N,
true,
Reg, Shift);
88 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
91 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
94 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
97 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
100 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
103 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
106 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
109 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
112 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
115 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
118 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
121 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
124 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
127 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
130 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
133 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
136 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
138 template <
unsigned Size,
unsigned Max>
142 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
145 int64_t
C = CI->getSExtValue();
153 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
160 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
166 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
171 N =
N->getOperand(0);
175 EVT VT =
N->getValueType(0);
176 EVT LVT =
N->getOperand(0).getValueType();
177 unsigned Index =
N->getConstantOperandVal(1);
181 Res =
N->getOperand(0);
186 if (
N.getOpcode() != AArch64ISD::VLSHR)
189 EVT VT =
Op.getValueType();
190 unsigned ShtAmt =
N->getConstantOperandVal(1);
195 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
197 Op.getOperand(1).getConstantOperandVal(0)
198 <<
Op.getOperand(1).getConstantOperandVal(1));
199 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
202 Op.getOperand(1).getConstantOperandVal(0));
206 if (Imm != 1ULL << (ShtAmt - 1))
209 Res1 =
Op.getOperand(0);
210 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
214 bool SelectDupZeroOrUndef(
SDValue N) {
215 switch(
N->getOpcode()) {
218 case AArch64ISD::DUP:
220 auto Opnd0 =
N->getOperand(0);
234 bool SelectAny(
SDValue) {
return true; }
237 switch(
N->getOpcode()) {
238 case AArch64ISD::DUP:
240 auto Opnd0 =
N->getOperand(0);
252 template <MVT::SimpleValueType VT,
bool Negate>
254 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
257 template <MVT::SimpleValueType VT,
bool Negate>
259 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
262 template <MVT::SimpleValueType VT>
264 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
267 template <MVT::SimpleValueType VT,
bool Invert = false>
269 return SelectSVELogicalImm(
N, VT, Imm, Invert);
272 template <MVT::SimpleValueType VT>
274 return SelectSVEArithImm(
N, VT, Imm);
277 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
279 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
286 EVT EltVT =
N->getValueType(0).getVectorElementType();
287 return SelectSVEShiftImm(
N->getOperand(0), 1,
293 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
300 MulImm = 1LL << MulImm;
302 if ((MulImm % std::abs(Scale)) != 0)
306 if ((MulImm >= Min) && (MulImm <= Max)) {
307 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
314 template <
signed Max,
signed Scale>
321 if (MulImm >= 0 && MulImm <= Max) {
323 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
330 template <
unsigned BaseReg,
unsigned Max>
338 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
361 const unsigned SubRegs[]);
363 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
365 bool tryIndexedLoad(
SDNode *
N);
367 void SelectPtrauthAuth(
SDNode *
N);
368 void SelectPtrauthResign(
SDNode *
N);
370 bool trySelectStackSlotTagP(
SDNode *
N);
373 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
375 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
377 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
378 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
379 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
380 unsigned Opc_rr,
unsigned Opc_ri,
381 bool IsIntr =
false);
382 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
383 unsigned Scale,
unsigned Opc_ri,
385 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
386 bool IsZmMulti,
unsigned Opcode,
387 bool HasPred =
false);
389 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
390 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
391 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
392 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
393 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
394 bool IsTupleInput,
unsigned Opc);
395 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
397 template <
unsigned MaxIdx,
unsigned Scale>
398 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
400 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
401 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
402 unsigned BaseReg = 0);
405 template <
int64_t Min,
int64_t Max>
409 template <
unsigned Scale>
411 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
414 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
417 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc);
419 template <
unsigned MaxIdx,
unsigned Scale>
424 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
425 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
426 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
427 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
428 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
429 unsigned Opc_rr,
unsigned Opc_ri);
430 std::tuple<unsigned, SDValue, SDValue>
431 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
435 bool tryBitfieldExtractOp(
SDNode *
N);
436 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
437 bool tryBitfieldInsertOp(
SDNode *
N);
438 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
439 bool tryShiftAmountMod(
SDNode *
N);
441 bool tryReadRegister(
SDNode *
N);
442 bool tryWriteRegister(
SDNode *
N);
444 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
445 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
450#include "AArch64GenDAGISel.inc"
458 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
460 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
473 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
474 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
475 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
478 template<
unsigned RegW
idth>
480 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
483 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
485 template<
unsigned RegW
idth>
487 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
493 bool SelectCMP_SWAP(
SDNode *
N);
504 bool AllowSaturation,
SDValue &Imm);
512 bool SelectAllActivePredicate(
SDValue N);
517 template <
bool MatchCBB>
527 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
531char AArch64DAGToDAGISelLegacy::ID = 0;
539 Imm =
C->getZExtValue();
556 return N->getOpcode() ==
Opc &&
567 return Imm == ImmExpected;
571bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
573 std::vector<SDValue> &OutOps) {
574 switch(ConstraintID) {
577 case InlineAsm::ConstraintCode::m:
578 case InlineAsm::ConstraintCode::o:
579 case InlineAsm::ConstraintCode::Q:
583 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
585 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
587 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
588 dl,
Op.getValueType(),
590 OutOps.push_back(NewOp);
609 uint64_t Immed =
N.getNode()->getAsZExtVal();
612 if (Immed >> 12 == 0) {
614 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
622 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
623 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
640 uint64_t Immed =
N.getNode()->getAsZExtVal();
648 if (
N.getValueType() == MVT::i32)
649 Immed = ~((uint32_t)Immed) + 1;
651 Immed = ~Immed + 1ULL;
652 if (Immed & 0xFFFFFFFFFF000000ULL)
655 Immed &= 0xFFFFFFULL;
656 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
663 switch (
N.getOpcode()) {
689 unsigned ShiftVal = CSD->getZExtValue();
707bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
710 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
715 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
739 EVT VT =
N.getValueType();
740 if (VT != MVT::i32 && VT != MVT::i64)
743 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
749 unsigned LHSOpcode =
LHS->getOpcode();
763 unsigned LowZBits, MaskLen;
767 unsigned BitWidth =
N.getValueSizeInBits();
774 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
777 NewShiftC = LowZBits - ShiftAmtC;
778 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
784 NewShiftC = LowZBits + ShiftAmtC;
797 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
799 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
803 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
805 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
806 NewShiftAmt, BitWidthMinus1),
809 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
823 SrcVT =
N.getOperand(0).getValueType();
825 if (!IsLoadStore && SrcVT == MVT::i8)
827 else if (!IsLoadStore && SrcVT == MVT::i16)
829 else if (SrcVT == MVT::i32)
831 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
836 EVT SrcVT =
N.getOperand(0).getValueType();
837 if (!IsLoadStore && SrcVT == MVT::i8)
839 else if (!IsLoadStore && SrcVT == MVT::i16)
841 else if (SrcVT == MVT::i32)
843 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
871bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
874 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
879 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
880 V.getConstantOperandVal(1) <= 4 &&
893bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
895 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
905 unsigned BitSize =
N.getValueSizeInBits();
906 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
909 Reg =
N.getOperand(0);
910 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
911 return isWorthFoldingALU(
N,
true);
922 if (
N.getValueType() == MVT::i32)
930template<
signed Low,
signed High,
signed Scale>
936 if ((MulImm % std::abs(Scale)) == 0) {
937 int64_t RDVLImm = MulImm / Scale;
938 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
939 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
948template <
signed Low,
signed High>
949bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
954 if (MulImm >=
Low && MulImm <=
High) {
955 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
966 unsigned ShiftVal = 0;
981 Reg =
N.getOperand(0).getOperand(0);
987 Reg =
N.getOperand(0);
992 unsigned Opc =
N.getOpcode();
1010 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1012 return isWorthFoldingALU(
N);
1019 unsigned ShiftVal = 0;
1033 Reg =
N.getOperand(0);
1034 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1036 return isWorthFoldingALU(
N);
1045 for (
auto *
User :
N->users()) {
1072bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1073 unsigned BW,
unsigned Size,
1077 const DataLayout &
DL = CurDAG->getDataLayout();
1078 const TargetLowering *TLI = getTargetLowering();
1082 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1088 if (CurDAG->isBaseWithConstantOffset(
N)) {
1091 int64_t RHSC =
RHS->getSExtValue();
1093 int64_t
Range = 0x1LL << (BW - 1);
1095 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1096 RHSC < (
Range << Scale)) {
1097 Base =
N.getOperand(0);
1102 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1107 uint64_t RHSC =
RHS->getZExtValue();
1109 uint64_t
Range = 0x1ULL << BW;
1111 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1112 Base =
N.getOperand(0);
1117 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1128 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1135bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1138 const DataLayout &
DL = CurDAG->getDataLayout();
1139 const TargetLowering *TLI = getTargetLowering();
1143 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1148 GlobalAddressSDNode *GAN =
1150 Base =
N.getOperand(0);
1160 if (CurDAG->isBaseWithConstantOffset(
N)) {
1162 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1165 Base =
N.getOperand(0);
1170 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1178 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1186 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1195bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1198 if (!CurDAG->isBaseWithConstantOffset(
N))
1201 int64_t RHSC =
RHS->getSExtValue();
1202 if (RHSC >= -256 && RHSC < 256) {
1203 Base =
N.getOperand(0);
1206 const TargetLowering *TLI = getTargetLowering();
1207 Base = CurDAG->getTargetFrameIndex(
1210 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1220 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1227bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1247 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1253 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1256 return isWorthFoldingAddr(
N,
Size);
1259bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1277 const SDNode *
Node =
N.getNode();
1278 for (SDNode *UI :
Node->users()) {
1284 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1287 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1290 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1295 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1298 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1303 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1307 if (IsExtendedRegisterWorthFolding &&
1314 if (isWorthFoldingAddr(
LHS,
Size))
1319 if (IsExtendedRegisterWorthFolding &&
1326 if (isWorthFoldingAddr(
RHS,
Size))
1338 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1341 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1343 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1344 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1348bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1361 const SDNode *
Node =
N.getNode();
1362 for (SDNode *UI :
Node->users()) {
1379 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1389 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1396 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1399 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1402 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1407 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1410 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1417 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1418 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1424 static const unsigned RegClassIDs[] = {
1425 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1426 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1427 AArch64::dsub2, AArch64::dsub3};
1433 static const unsigned RegClassIDs[] = {
1434 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1435 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1436 AArch64::qsub2, AArch64::qsub3};
1442 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1443 AArch64::ZPR3RegClassID,
1444 AArch64::ZPR4RegClassID};
1445 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1446 AArch64::zsub2, AArch64::zsub3};
1456 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1457 AArch64::ZPR4Mul4RegClassID};
1458 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1459 AArch64::zsub2, AArch64::zsub3};
1464 const unsigned RegClassIDs[],
1465 const unsigned SubRegs[]) {
1468 if (Regs.
size() == 1)
1479 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1482 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1483 Ops.push_back(Regs[i]);
1484 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1488 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1492void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1495 EVT VT =
N->getValueType(0);
1497 unsigned ExtOff = isExt;
1500 unsigned Vec0Off = ExtOff + 1;
1506 Ops.push_back(
N->getOperand(1));
1507 Ops.push_back(RegSeq);
1508 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1509 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1512static std::tuple<SDValue, SDValue>
1533 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1538 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1540 return std::make_tuple(
1545void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1550 SDValue AUTDisc =
N->getOperand(3);
1553 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1555 SDValue AUTAddrDisc, AUTConstDisc;
1556 std::tie(AUTConstDisc, AUTAddrDisc) =
1560 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1562 if (
N->getNumOperands() > 4)
1563 Ops.push_back(
N->getOperand(4));
1566 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1567 ReplaceNode(
N, AUT);
1569 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1570 AArch64::X16, Val,
SDValue());
1573 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1574 ReplaceNode(
N, AUT);
1578void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1590 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1591 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1593 SDValue AUTAddrDisc, AUTConstDisc;
1594 std::tie(AUTConstDisc, AUTAddrDisc) =
1597 SDValue PACAddrDisc, PACConstDisc;
1598 std::tie(PACConstDisc, PACAddrDisc) =
1601 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1602 AArch64::X16, Val,
SDValue());
1604 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1605 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1607 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1608 ReplaceNode(
N, AUTPAC);
1611bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1613 if (
LD->isUnindexed())
1615 EVT VT =
LD->getMemoryVT();
1616 EVT DstVT =
N->getValueType(0);
1620 int OffsetVal = (int)
OffsetOp->getZExtValue();
1625 unsigned Opcode = 0;
1628 bool InsertTo64 =
false;
1630 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1631 else if (VT == MVT::i32) {
1633 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1635 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1637 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1643 }
else if (VT == MVT::i16) {
1645 if (DstVT == MVT::i64)
1646 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1648 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1650 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1651 InsertTo64 = DstVT == MVT::i64;
1656 }
else if (VT == MVT::i8) {
1658 if (DstVT == MVT::i64)
1659 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1661 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1663 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1664 InsertTo64 = DstVT == MVT::i64;
1669 }
else if (VT == MVT::f16) {
1670 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1671 }
else if (VT == MVT::bf16) {
1672 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1673 }
else if (VT == MVT::f32) {
1674 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1675 }
else if (VT == MVT::f64 ||
1677 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1679 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1681 if (IsPre || OffsetVal != 8)
1685 Opcode = AArch64::LD1Onev8b_POST;
1688 Opcode = AArch64::LD1Onev4h_POST;
1691 Opcode = AArch64::LD1Onev2s_POST;
1694 Opcode = AArch64::LD1Onev1d_POST;
1700 if (IsPre || OffsetVal != 16)
1704 Opcode = AArch64::LD1Onev16b_POST;
1707 Opcode = AArch64::LD1Onev8h_POST;
1710 Opcode = AArch64::LD1Onev4s_POST;
1713 Opcode = AArch64::LD1Onev2d_POST;
1725 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1726 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1728 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1738 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1740 SDValue(CurDAG->getMachineNode(
1741 AArch64::SUBREG_TO_REG, dl, MVT::i64,
1742 CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1747 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1750 CurDAG->RemoveDeadNode(
N);
1754void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1755 unsigned SubRegIdx) {
1757 EVT VT =
N->getValueType(0);
1763 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1765 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1767 for (
unsigned i = 0; i < NumVecs; ++i)
1769 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1776 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1780 CurDAG->RemoveDeadNode(
N);
1783void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1784 unsigned Opc,
unsigned SubRegIdx) {
1786 EVT VT =
N->getValueType(0);
1793 const EVT ResTys[] = {MVT::i64,
1794 MVT::Untyped, MVT::Other};
1796 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1804 ReplaceUses(
SDValue(
N, 0), SuperReg);
1806 for (
unsigned i = 0; i < NumVecs; ++i)
1808 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1812 CurDAG->RemoveDeadNode(
N);
1818std::tuple<unsigned, SDValue, SDValue>
1819AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1825 SDValue NewOffset = OldOffset;
1827 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1828 N, OldBase, NewBase, NewOffset);
1832 const bool IsRegReg =
1833 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1836 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
1849template <SelectTypeKind Kind>
1861 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
1866 if (EltVT != MVT::i1)
1870 if (EltVT == MVT::bf16)
1872 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
1902void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
1905 if (
Imm->getZExtValue() > 1)
1909 EVT VT =
N->getValueType(0);
1911 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1914 for (
unsigned I = 0;
I < 2; ++
I)
1915 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1916 AArch64::psub0 +
I,
DL, VT, SuperReg));
1918 CurDAG->RemoveDeadNode(
N);
1921void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
1923 EVT VT =
N->getValueType(0);
1927 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1930 for (
unsigned I = 0;
I < 2; ++
I)
1931 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1932 AArch64::psub0 +
I,
DL, VT, SuperReg));
1934 CurDAG->RemoveDeadNode(
N);
1937void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
1939 EVT VT =
N->getValueType(0);
1943 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
1945 for (
unsigned i = 0; i < NumVecs; ++i)
1946 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1947 AArch64::zsub0 + i,
DL, VT, SuperReg));
1949 CurDAG->RemoveDeadNode(
N);
1952void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
1955 EVT VT =
N->getValueType(0);
1957 Ops.push_back(
N->getOperand(0));
1960 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
1963 for (
unsigned i = 0; i < NumVecs; ++i)
1964 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1965 AArch64::zsub0 + i,
DL, VT, SuperReg));
1968 unsigned ChainIdx = NumVecs;
1970 CurDAG->RemoveDeadNode(
N);
1973void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
1978 assert(Opcode != 0 &&
"Unexpected opcode");
1981 EVT VT =
N->getValueType(0);
1982 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 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4433bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4434 uint64_t
High,
bool AllowSaturation,
4437 uint64_t ImmVal = CN->getZExtValue();
4444 if (ImmVal >
High) {
4445 if (!AllowSaturation)
4450 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4457bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4471 const TargetLowering *TLI = getTargetLowering();
4474 SDValue FiOp = CurDAG->getTargetFrameIndex(
4476 int TagOffset =
N->getConstantOperandVal(3);
4478 SDNode *Out = CurDAG->getMachineNode(
4479 AArch64::TAGPstack,
DL, MVT::i64,
4480 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4481 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4482 ReplaceNode(
N, Out);
4486void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4488 "llvm.aarch64.tagp third argument must be an immediate");
4489 if (trySelectStackSlotTagP(
N))
4496 int TagOffset =
N->getConstantOperandVal(3);
4497 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4498 {
N->getOperand(1),
N->getOperand(2)});
4499 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4500 {
SDValue(N1, 0),
N->getOperand(2)});
4501 SDNode *N3 = CurDAG->getMachineNode(
4502 AArch64::ADDG,
DL, MVT::i64,
4503 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4504 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4508bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4512 if (
N->getConstantOperandVal(2) != 0)
4514 if (!
N->getOperand(0).isUndef())
4518 EVT VT =
N->getValueType(0);
4519 EVT InVT =
N->getOperand(1).getValueType();
4530 "Expected to insert into a packed scalable vector!");
4533 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4534 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4535 N->getOperand(1), RC));
4539bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4543 if (
N->getConstantOperandVal(1) != 0)
4547 EVT VT =
N->getValueType(0);
4548 EVT InVT =
N->getOperand(0).getValueType();
4559 "Expected to extract from a packed scalable vector!");
4562 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4563 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4564 N->getOperand(0), RC));
4568bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4574 EVT VT =
N->getValueType(0);
4587 (Subtarget->hasSVE2() ||
4588 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4589 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4592 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4596 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4597 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4598 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4605 bool IsXOROperand =
true;
4607 IsXOROperand =
false;
4613 APInt ShlAmt, ShrAmt;
4621 if (!IsXOROperand) {
4623 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4626 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4627 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4628 VT, Zero, MOVIV, ZSub);
4639 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4640 AArch64::XAR_ZZZI_D})) {
4641 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4666 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4676 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4684 bool IsXOROperand =
true;
4686 IsXOROperand =
false;
4689 R1 =
XOR.getOperand(0);
4690 R2 =
XOR.getOperand(1);
4700 if (ShAmt + HsAmt != VTSizeInBits)
4703 if (!IsXOROperand) {
4706 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4715 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4721 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4722 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4724 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4727 if (
R2.getValueType() == VT)
4728 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4736 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4741 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4747 SDNode *XAR =
nullptr;
4751 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4752 AArch64::XAR_ZZZI_D}))
4753 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4755 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4758 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4764 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4765 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4768 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4769 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4775 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4779 ReplaceNode(
N, XAR);
4783void AArch64DAGToDAGISel::Select(SDNode *Node) {
4785 if (
Node->isMachineOpcode()) {
4787 Node->setNodeId(-1);
4792 EVT VT =
Node->getValueType(0);
4794 switch (
Node->getOpcode()) {
4799 if (SelectCMP_SWAP(Node))
4804 case AArch64ISD::MRRS:
4805 if (tryReadRegister(Node))
4810 case AArch64ISD::MSRR:
4811 if (tryWriteRegister(Node))
4818 if (tryIndexedLoad(Node))
4827 if (tryBitfieldExtractOp(Node))
4829 if (tryBitfieldInsertInZeroOp(Node))
4834 if (tryShiftAmountMod(Node))
4839 if (tryBitfieldExtractOpFromSExt(Node))
4844 if (tryBitfieldInsertOp(Node))
4846 if (trySelectXAR(Node))
4851 if (trySelectCastScalableToFixedLengthVector(Node))
4857 if (trySelectCastFixedLengthToScalableVector(Node))
4866 if (ConstNode->
isZero()) {
4867 if (VT == MVT::i32) {
4869 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4870 ReplaceNode(Node,
New.getNode());
4872 }
else if (VT == MVT::i64) {
4874 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4875 ReplaceNode(Node,
New.getNode());
4886 const TargetLowering *TLI = getTargetLowering();
4887 SDValue TFI = CurDAG->getTargetFrameIndex(
4890 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4891 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4892 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4896 unsigned IntNo =
Node->getConstantOperandVal(1);
4900 case Intrinsic::aarch64_gcsss: {
4904 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4906 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4907 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4908 MVT::Other, Zero,
SDValue(SS1, 0));
4909 ReplaceNode(Node, SS2);
4912 case Intrinsic::aarch64_ldaxp:
4913 case Intrinsic::aarch64_ldxp: {
4915 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4920 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4921 MVT::Other, MemAddr, Chain);
4924 MachineMemOperand *MemOp =
4927 ReplaceNode(Node, Ld);
4930 case Intrinsic::aarch64_stlxp:
4931 case Intrinsic::aarch64_stxp: {
4933 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4941 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4943 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4945 MachineMemOperand *MemOp =
4949 ReplaceNode(Node, St);
4952 case Intrinsic::aarch64_neon_ld1x2:
4953 if (VT == MVT::v8i8) {
4954 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4956 }
else if (VT == MVT::v16i8) {
4957 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4959 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4960 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4962 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4963 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4965 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4966 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4968 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4969 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4971 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4972 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4974 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4975 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
4979 case Intrinsic::aarch64_neon_ld1x3:
4980 if (VT == MVT::v8i8) {
4981 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
4983 }
else if (VT == MVT::v16i8) {
4984 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
4986 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4987 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
4989 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4990 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
4992 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4993 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
4995 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4996 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
4998 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4999 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5001 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5002 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5006 case Intrinsic::aarch64_neon_ld1x4:
5007 if (VT == MVT::v8i8) {
5008 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5010 }
else if (VT == MVT::v16i8) {
5011 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5013 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5014 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5016 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5017 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5019 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5020 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5022 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5023 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5025 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5026 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5028 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5029 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5033 case Intrinsic::aarch64_neon_ld2:
5034 if (VT == MVT::v8i8) {
5035 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5037 }
else if (VT == MVT::v16i8) {
5038 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5040 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5041 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5043 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5044 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5046 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5047 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5049 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5050 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5052 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5053 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5055 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5056 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5060 case Intrinsic::aarch64_neon_ld3:
5061 if (VT == MVT::v8i8) {
5062 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5064 }
else if (VT == MVT::v16i8) {
5065 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5067 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5068 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5070 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5071 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5073 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5074 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5076 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5077 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5079 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5080 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5082 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5083 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5087 case Intrinsic::aarch64_neon_ld4:
5088 if (VT == MVT::v8i8) {
5089 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5091 }
else if (VT == MVT::v16i8) {
5092 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5094 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5095 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5097 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5098 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5100 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5101 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5103 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5104 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5106 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5107 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5109 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5110 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5114 case Intrinsic::aarch64_neon_ld2r:
5115 if (VT == MVT::v8i8) {
5116 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5118 }
else if (VT == MVT::v16i8) {
5119 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5121 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5122 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5124 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5125 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5127 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5128 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5130 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5131 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5133 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5134 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5136 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5137 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5141 case Intrinsic::aarch64_neon_ld3r:
5142 if (VT == MVT::v8i8) {
5143 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5145 }
else if (VT == MVT::v16i8) {
5146 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5148 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5149 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5151 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5152 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5154 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5155 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5157 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5158 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5160 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5161 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5163 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5164 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5168 case Intrinsic::aarch64_neon_ld4r:
5169 if (VT == MVT::v8i8) {
5170 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5172 }
else if (VT == MVT::v16i8) {
5173 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5175 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5176 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5178 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5179 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5181 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5182 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5184 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5185 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5187 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5188 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5190 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5191 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5195 case Intrinsic::aarch64_neon_ld2lane:
5196 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5197 SelectLoadLane(Node, 2, AArch64::LD2i8);
5199 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5200 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5201 SelectLoadLane(Node, 2, AArch64::LD2i16);
5203 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5205 SelectLoadLane(Node, 2, AArch64::LD2i32);
5207 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5209 SelectLoadLane(Node, 2, AArch64::LD2i64);
5213 case Intrinsic::aarch64_neon_ld3lane:
5214 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5215 SelectLoadLane(Node, 3, AArch64::LD3i8);
5217 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5218 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5219 SelectLoadLane(Node, 3, AArch64::LD3i16);
5221 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5223 SelectLoadLane(Node, 3, AArch64::LD3i32);
5225 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5227 SelectLoadLane(Node, 3, AArch64::LD3i64);
5231 case Intrinsic::aarch64_neon_ld4lane:
5232 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5233 SelectLoadLane(Node, 4, AArch64::LD4i8);
5235 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5236 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5237 SelectLoadLane(Node, 4, AArch64::LD4i16);
5239 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5241 SelectLoadLane(Node, 4, AArch64::LD4i32);
5243 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5245 SelectLoadLane(Node, 4, AArch64::LD4i64);
5249 case Intrinsic::aarch64_ld64b:
5250 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5252 case Intrinsic::aarch64_sve_ld2q_sret: {
5253 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5256 case Intrinsic::aarch64_sve_ld3q_sret: {
5257 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5260 case Intrinsic::aarch64_sve_ld4q_sret: {
5261 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5264 case Intrinsic::aarch64_sve_ld2_sret: {
5265 if (VT == MVT::nxv16i8) {
5266 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5269 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5270 VT == MVT::nxv8bf16) {
5271 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5274 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5275 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5278 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5279 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5285 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5286 if (VT == MVT::nxv16i8) {
5287 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5288 SelectContiguousMultiVectorLoad(
5289 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5290 else if (Subtarget->hasSVE2p1())
5291 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5296 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5297 VT == MVT::nxv8bf16) {
5298 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5299 SelectContiguousMultiVectorLoad(
5300 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5301 else if (Subtarget->hasSVE2p1())
5302 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5307 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5308 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5309 SelectContiguousMultiVectorLoad(
5310 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5311 else if (Subtarget->hasSVE2p1())
5312 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5317 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5318 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5319 SelectContiguousMultiVectorLoad(
5320 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5321 else if (Subtarget->hasSVE2p1())
5322 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5330 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5331 if (VT == MVT::nxv16i8) {
5332 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5333 SelectContiguousMultiVectorLoad(
5334 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5335 else if (Subtarget->hasSVE2p1())
5336 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5341 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5342 VT == MVT::nxv8bf16) {
5343 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5344 SelectContiguousMultiVectorLoad(
5345 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5346 else if (Subtarget->hasSVE2p1())
5347 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5352 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5353 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5354 SelectContiguousMultiVectorLoad(
5355 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5356 else if (Subtarget->hasSVE2p1())
5357 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5362 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5363 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5364 SelectContiguousMultiVectorLoad(
5365 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5366 else if (Subtarget->hasSVE2p1())
5367 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5375 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5376 if (VT == MVT::nxv16i8) {
5377 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5378 SelectContiguousMultiVectorLoad(Node, 2, 0,
5379 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5380 AArch64::LDNT1B_2Z_PSEUDO);
5381 else if (Subtarget->hasSVE2p1())
5382 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5383 AArch64::LDNT1B_2Z);
5387 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5388 VT == MVT::nxv8bf16) {
5389 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5390 SelectContiguousMultiVectorLoad(Node, 2, 1,
5391 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5392 AArch64::LDNT1H_2Z_PSEUDO);
5393 else if (Subtarget->hasSVE2p1())
5394 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5395 AArch64::LDNT1H_2Z);
5399 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5400 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5401 SelectContiguousMultiVectorLoad(Node, 2, 2,
5402 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5403 AArch64::LDNT1W_2Z_PSEUDO);
5404 else if (Subtarget->hasSVE2p1())
5405 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5406 AArch64::LDNT1W_2Z);
5410 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5411 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5412 SelectContiguousMultiVectorLoad(Node, 2, 3,
5413 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5414 AArch64::LDNT1D_2Z_PSEUDO);
5415 else if (Subtarget->hasSVE2p1())
5416 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5417 AArch64::LDNT1D_2Z);
5424 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5425 if (VT == MVT::nxv16i8) {
5426 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5427 SelectContiguousMultiVectorLoad(Node, 4, 0,
5428 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5429 AArch64::LDNT1B_4Z_PSEUDO);
5430 else if (Subtarget->hasSVE2p1())
5431 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5432 AArch64::LDNT1B_4Z);
5436 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5437 VT == MVT::nxv8bf16) {
5438 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5439 SelectContiguousMultiVectorLoad(Node, 4, 1,
5440 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5441 AArch64::LDNT1H_4Z_PSEUDO);
5442 else if (Subtarget->hasSVE2p1())
5443 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5444 AArch64::LDNT1H_4Z);
5448 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5449 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5450 SelectContiguousMultiVectorLoad(Node, 4, 2,
5451 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5452 AArch64::LDNT1W_4Z_PSEUDO);
5453 else if (Subtarget->hasSVE2p1())
5454 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5455 AArch64::LDNT1W_4Z);
5459 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5460 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5461 SelectContiguousMultiVectorLoad(Node, 4, 3,
5462 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5463 AArch64::LDNT1D_4Z_PSEUDO);
5464 else if (Subtarget->hasSVE2p1())
5465 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5466 AArch64::LDNT1D_4Z);
5473 case Intrinsic::aarch64_sve_ld3_sret: {
5474 if (VT == MVT::nxv16i8) {
5475 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5478 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5479 VT == MVT::nxv8bf16) {
5480 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5483 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5484 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5487 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5488 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5494 case Intrinsic::aarch64_sve_ld4_sret: {
5495 if (VT == MVT::nxv16i8) {
5496 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5499 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5500 VT == MVT::nxv8bf16) {
5501 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5504 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5505 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5508 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5509 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5515 case Intrinsic::aarch64_sme_read_hor_vg2: {
5516 if (VT == MVT::nxv16i8) {
5517 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5518 AArch64::MOVA_2ZMXI_H_B);
5520 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5521 VT == MVT::nxv8bf16) {
5522 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5523 AArch64::MOVA_2ZMXI_H_H);
5525 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5526 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5527 AArch64::MOVA_2ZMXI_H_S);
5529 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5530 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5531 AArch64::MOVA_2ZMXI_H_D);
5536 case Intrinsic::aarch64_sme_read_ver_vg2: {
5537 if (VT == MVT::nxv16i8) {
5538 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5539 AArch64::MOVA_2ZMXI_V_B);
5541 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5542 VT == MVT::nxv8bf16) {
5543 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5544 AArch64::MOVA_2ZMXI_V_H);
5546 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5547 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5548 AArch64::MOVA_2ZMXI_V_S);
5550 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5551 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5552 AArch64::MOVA_2ZMXI_V_D);
5557 case Intrinsic::aarch64_sme_read_hor_vg4: {
5558 if (VT == MVT::nxv16i8) {
5559 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5560 AArch64::MOVA_4ZMXI_H_B);
5562 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5563 VT == MVT::nxv8bf16) {
5564 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5565 AArch64::MOVA_4ZMXI_H_H);
5567 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5568 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5569 AArch64::MOVA_4ZMXI_H_S);
5571 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5572 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5573 AArch64::MOVA_4ZMXI_H_D);
5578 case Intrinsic::aarch64_sme_read_ver_vg4: {
5579 if (VT == MVT::nxv16i8) {
5580 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5581 AArch64::MOVA_4ZMXI_V_B);
5583 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5584 VT == MVT::nxv8bf16) {
5585 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5586 AArch64::MOVA_4ZMXI_V_H);
5588 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5589 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5590 AArch64::MOVA_4ZMXI_V_S);
5592 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5593 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5594 AArch64::MOVA_4ZMXI_V_D);
5599 case Intrinsic::aarch64_sme_read_vg1x2: {
5600 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5601 AArch64::MOVA_VG2_2ZMXI);
5604 case Intrinsic::aarch64_sme_read_vg1x4: {
5605 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5606 AArch64::MOVA_VG4_4ZMXI);
5609 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5610 if (VT == MVT::nxv16i8) {
5611 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5613 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5614 VT == MVT::nxv8bf16) {
5615 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5617 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5618 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5620 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5621 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5626 case Intrinsic::aarch64_sme_readz_vert_x2: {
5627 if (VT == MVT::nxv16i8) {
5628 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5630 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5631 VT == MVT::nxv8bf16) {
5632 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5634 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5635 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5637 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5638 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5643 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5644 if (VT == MVT::nxv16i8) {
5645 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5647 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5648 VT == MVT::nxv8bf16) {
5649 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5651 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5652 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5654 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5655 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5660 case Intrinsic::aarch64_sme_readz_vert_x4: {
5661 if (VT == MVT::nxv16i8) {
5662 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5664 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5665 VT == MVT::nxv8bf16) {
5666 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5668 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5669 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5671 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5672 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5677 case Intrinsic::aarch64_sme_readz_x2: {
5678 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5682 case Intrinsic::aarch64_sme_readz_x4: {
5683 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5687 case Intrinsic::swift_async_context_addr: {
5690 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5692 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5693 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5694 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5696 ReplaceUses(
SDValue(Node, 0), Res);
5698 CurDAG->RemoveDeadNode(Node);
5700 auto &MF = CurDAG->getMachineFunction();
5701 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5702 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5705 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5707 Node->getValueType(0),
5708 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5709 AArch64::LUTI2_4ZTZI_S}))
5711 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5714 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5716 Node->getValueType(0),
5717 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5719 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5722 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5724 Node->getValueType(0),
5725 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5726 AArch64::LUTI2_2ZTZI_S}))
5728 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5731 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5733 Node->getValueType(0),
5734 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5735 AArch64::LUTI4_2ZTZI_S}))
5737 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5740 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5741 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5744 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5746 Node->getValueType(0),
5747 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5748 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5750 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5752 Node->getValueType(0),
5753 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5754 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5756 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5758 Node->getValueType(0),
5759 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5760 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5762 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5764 Node->getValueType(0),
5765 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5766 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5771 unsigned IntNo =
Node->getConstantOperandVal(0);
5775 case Intrinsic::aarch64_tagp:
5779 case Intrinsic::ptrauth_auth:
5780 SelectPtrauthAuth(Node);
5783 case Intrinsic::ptrauth_resign:
5784 SelectPtrauthResign(Node);
5787 case Intrinsic::aarch64_neon_tbl2:
5788 SelectTable(Node, 2,
5789 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5792 case Intrinsic::aarch64_neon_tbl3:
5793 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5794 : AArch64::TBLv16i8Three,
5797 case Intrinsic::aarch64_neon_tbl4:
5798 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5799 : AArch64::TBLv16i8Four,
5802 case Intrinsic::aarch64_neon_tbx2:
5803 SelectTable(Node, 2,
5804 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5807 case Intrinsic::aarch64_neon_tbx3:
5808 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5809 : AArch64::TBXv16i8Three,
5812 case Intrinsic::aarch64_neon_tbx4:
5813 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5814 : AArch64::TBXv16i8Four,
5817 case Intrinsic::aarch64_sve_srshl_single_x2:
5819 Node->getValueType(0),
5820 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5821 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5822 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5824 case Intrinsic::aarch64_sve_srshl_single_x4:
5826 Node->getValueType(0),
5827 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5828 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5829 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5831 case Intrinsic::aarch64_sve_urshl_single_x2:
5833 Node->getValueType(0),
5834 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5835 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5836 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5838 case Intrinsic::aarch64_sve_urshl_single_x4:
5840 Node->getValueType(0),
5841 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5842 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5843 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5845 case Intrinsic::aarch64_sve_srshl_x2:
5847 Node->getValueType(0),
5848 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5849 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5850 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5852 case Intrinsic::aarch64_sve_srshl_x4:
5854 Node->getValueType(0),
5855 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5856 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5857 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5859 case Intrinsic::aarch64_sve_urshl_x2:
5861 Node->getValueType(0),
5862 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5863 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5864 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5866 case Intrinsic::aarch64_sve_urshl_x4:
5868 Node->getValueType(0),
5869 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5870 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5871 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5873 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5875 Node->getValueType(0),
5876 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5877 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5878 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5880 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5882 Node->getValueType(0),
5883 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5884 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5885 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5887 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5889 Node->getValueType(0),
5890 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5891 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5892 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5894 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5896 Node->getValueType(0),
5897 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5898 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5899 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5901 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5903 Node->getValueType(0),
5904 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5905 AArch64::FSCALE_2ZZ_D}))
5906 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5908 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5910 Node->getValueType(0),
5911 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5912 AArch64::FSCALE_4ZZ_D}))
5913 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5915 case Intrinsic::aarch64_sme_fp8_scale_x2:
5917 Node->getValueType(0),
5918 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5919 AArch64::FSCALE_2Z2Z_D}))
5920 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5922 case Intrinsic::aarch64_sme_fp8_scale_x4:
5924 Node->getValueType(0),
5925 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5926 AArch64::FSCALE_4Z4Z_D}))
5927 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5929 case Intrinsic::aarch64_sve_whilege_x2:
5931 Node->getValueType(0),
5932 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5933 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5934 SelectWhilePair(Node,
Op);
5936 case Intrinsic::aarch64_sve_whilegt_x2:
5938 Node->getValueType(0),
5939 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5940 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5941 SelectWhilePair(Node,
Op);
5943 case Intrinsic::aarch64_sve_whilehi_x2:
5945 Node->getValueType(0),
5946 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5947 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5948 SelectWhilePair(Node,
Op);
5950 case Intrinsic::aarch64_sve_whilehs_x2:
5952 Node->getValueType(0),
5953 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5954 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5955 SelectWhilePair(Node,
Op);
5957 case Intrinsic::aarch64_sve_whilele_x2:
5959 Node->getValueType(0),
5960 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5961 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5962 SelectWhilePair(Node,
Op);
5964 case Intrinsic::aarch64_sve_whilelo_x2:
5966 Node->getValueType(0),
5967 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5968 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5969 SelectWhilePair(Node,
Op);
5971 case Intrinsic::aarch64_sve_whilels_x2:
5973 Node->getValueType(0),
5974 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5975 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5976 SelectWhilePair(Node,
Op);
5978 case Intrinsic::aarch64_sve_whilelt_x2:
5980 Node->getValueType(0),
5981 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
5982 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
5983 SelectWhilePair(Node,
Op);
5985 case Intrinsic::aarch64_sve_smax_single_x2:
5987 Node->getValueType(0),
5988 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
5989 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
5990 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5992 case Intrinsic::aarch64_sve_umax_single_x2:
5994 Node->getValueType(0),
5995 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
5996 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
5997 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5999 case Intrinsic::aarch64_sve_fmax_single_x2:
6001 Node->getValueType(0),
6002 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6003 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6004 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6006 case Intrinsic::aarch64_sve_smax_single_x4:
6008 Node->getValueType(0),
6009 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6010 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6011 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6013 case Intrinsic::aarch64_sve_umax_single_x4:
6015 Node->getValueType(0),
6016 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6017 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6018 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6020 case Intrinsic::aarch64_sve_fmax_single_x4:
6022 Node->getValueType(0),
6023 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6024 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6025 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6027 case Intrinsic::aarch64_sve_smin_single_x2:
6029 Node->getValueType(0),
6030 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6031 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6032 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6034 case Intrinsic::aarch64_sve_umin_single_x2:
6036 Node->getValueType(0),
6037 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6038 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6039 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6041 case Intrinsic::aarch64_sve_fmin_single_x2:
6043 Node->getValueType(0),
6044 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6045 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6046 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6048 case Intrinsic::aarch64_sve_smin_single_x4:
6050 Node->getValueType(0),
6051 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6052 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6053 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6055 case Intrinsic::aarch64_sve_umin_single_x4:
6057 Node->getValueType(0),
6058 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6059 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6060 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6062 case Intrinsic::aarch64_sve_fmin_single_x4:
6064 Node->getValueType(0),
6065 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6066 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6067 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6069 case Intrinsic::aarch64_sve_smax_x2:
6071 Node->getValueType(0),
6072 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6073 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6074 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6076 case Intrinsic::aarch64_sve_umax_x2:
6078 Node->getValueType(0),
6079 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6080 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6081 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6083 case Intrinsic::aarch64_sve_fmax_x2:
6085 Node->getValueType(0),
6086 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6087 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6088 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6090 case Intrinsic::aarch64_sve_smax_x4:
6092 Node->getValueType(0),
6093 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6094 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6095 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6097 case Intrinsic::aarch64_sve_umax_x4:
6099 Node->getValueType(0),
6100 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6101 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6102 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6104 case Intrinsic::aarch64_sve_fmax_x4:
6106 Node->getValueType(0),
6107 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6108 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6109 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6111 case Intrinsic::aarch64_sme_famax_x2:
6113 Node->getValueType(0),
6114 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6115 AArch64::FAMAX_2Z2Z_D}))
6116 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6118 case Intrinsic::aarch64_sme_famax_x4:
6120 Node->getValueType(0),
6121 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6122 AArch64::FAMAX_4Z4Z_D}))
6123 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6125 case Intrinsic::aarch64_sme_famin_x2:
6127 Node->getValueType(0),
6128 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6129 AArch64::FAMIN_2Z2Z_D}))
6130 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6132 case Intrinsic::aarch64_sme_famin_x4:
6134 Node->getValueType(0),
6135 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6136 AArch64::FAMIN_4Z4Z_D}))
6137 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6139 case Intrinsic::aarch64_sve_smin_x2:
6141 Node->getValueType(0),
6142 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6143 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6144 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6146 case Intrinsic::aarch64_sve_umin_x2:
6148 Node->getValueType(0),
6149 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6150 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6151 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6153 case Intrinsic::aarch64_sve_fmin_x2:
6155 Node->getValueType(0),
6156 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6157 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6158 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6160 case Intrinsic::aarch64_sve_smin_x4:
6162 Node->getValueType(0),
6163 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6164 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6165 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6167 case Intrinsic::aarch64_sve_umin_x4:
6169 Node->getValueType(0),
6170 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6171 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6172 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6174 case Intrinsic::aarch64_sve_fmin_x4:
6176 Node->getValueType(0),
6177 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6178 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6179 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6181 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6183 Node->getValueType(0),
6184 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6185 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6186 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6188 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6190 Node->getValueType(0),
6191 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6192 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6193 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6195 case Intrinsic::aarch64_sve_fminnm_single_x2:
6197 Node->getValueType(0),
6198 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6199 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6200 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6202 case Intrinsic::aarch64_sve_fminnm_single_x4:
6204 Node->getValueType(0),
6205 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6206 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6207 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6209 case Intrinsic::aarch64_sve_fscale_single_x4:
6210 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6212 case Intrinsic::aarch64_sve_fscale_single_x2:
6213 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6215 case Intrinsic::aarch64_sve_fmul_single_x4:
6217 Node->getValueType(0),
6218 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6219 AArch64::FMUL_4ZZ_D}))
6220 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6222 case Intrinsic::aarch64_sve_fmul_single_x2:
6224 Node->getValueType(0),
6225 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6226 AArch64::FMUL_2ZZ_D}))
6227 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6229 case Intrinsic::aarch64_sve_fmaxnm_x2:
6231 Node->getValueType(0),
6232 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6233 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6234 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6236 case Intrinsic::aarch64_sve_fmaxnm_x4:
6238 Node->getValueType(0),
6239 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6240 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6241 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6243 case Intrinsic::aarch64_sve_fminnm_x2:
6245 Node->getValueType(0),
6246 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6247 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6248 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6250 case Intrinsic::aarch64_sve_fminnm_x4:
6252 Node->getValueType(0),
6253 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6254 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6255 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6257 case Intrinsic::aarch64_sve_fscale_x4:
6258 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6260 case Intrinsic::aarch64_sve_fscale_x2:
6261 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6263 case Intrinsic::aarch64_sve_fmul_x4:
6265 Node->getValueType(0),
6266 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6267 AArch64::FMUL_4Z4Z_D}))
6268 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6270 case Intrinsic::aarch64_sve_fmul_x2:
6272 Node->getValueType(0),
6273 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6274 AArch64::FMUL_2Z2Z_D}))
6275 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6277 case Intrinsic::aarch64_sve_fcvtzs_x2:
6278 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6280 case Intrinsic::aarch64_sve_scvtf_x2:
6281 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6283 case Intrinsic::aarch64_sve_fcvtzu_x2:
6284 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6286 case Intrinsic::aarch64_sve_ucvtf_x2:
6287 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6289 case Intrinsic::aarch64_sve_fcvtzs_x4:
6290 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6292 case Intrinsic::aarch64_sve_scvtf_x4:
6293 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6295 case Intrinsic::aarch64_sve_fcvtzu_x4:
6296 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6298 case Intrinsic::aarch64_sve_ucvtf_x4:
6299 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6301 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6302 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6304 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6305 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6307 case Intrinsic::aarch64_sve_sclamp_single_x2:
6309 Node->getValueType(0),
6310 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6311 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6312 SelectClamp(Node, 2,
Op);
6314 case Intrinsic::aarch64_sve_uclamp_single_x2:
6316 Node->getValueType(0),
6317 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6318 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6319 SelectClamp(Node, 2,
Op);
6321 case Intrinsic::aarch64_sve_fclamp_single_x2:
6323 Node->getValueType(0),
6324 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6325 AArch64::FCLAMP_VG2_2Z2Z_D}))
6326 SelectClamp(Node, 2,
Op);
6328 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6329 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6331 case Intrinsic::aarch64_sve_sclamp_single_x4:
6333 Node->getValueType(0),
6334 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6335 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6336 SelectClamp(Node, 4,
Op);
6338 case Intrinsic::aarch64_sve_uclamp_single_x4:
6340 Node->getValueType(0),
6341 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6342 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6343 SelectClamp(Node, 4,
Op);
6345 case Intrinsic::aarch64_sve_fclamp_single_x4:
6347 Node->getValueType(0),
6348 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6349 AArch64::FCLAMP_VG4_4Z4Z_D}))
6350 SelectClamp(Node, 4,
Op);
6352 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6353 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6355 case Intrinsic::aarch64_sve_add_single_x2:
6357 Node->getValueType(0),
6358 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6359 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6360 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6362 case Intrinsic::aarch64_sve_add_single_x4:
6364 Node->getValueType(0),
6365 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6366 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6367 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6369 case Intrinsic::aarch64_sve_zip_x2:
6371 Node->getValueType(0),
6372 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6373 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6374 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6376 case Intrinsic::aarch64_sve_zipq_x2:
6377 SelectUnaryMultiIntrinsic(Node, 2,
false,
6378 AArch64::ZIP_VG2_2ZZZ_Q);
6380 case Intrinsic::aarch64_sve_zip_x4:
6382 Node->getValueType(0),
6383 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6384 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6385 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6387 case Intrinsic::aarch64_sve_zipq_x4:
6388 SelectUnaryMultiIntrinsic(Node, 4,
true,
6389 AArch64::ZIP_VG4_4Z4Z_Q);
6391 case Intrinsic::aarch64_sve_uzp_x2:
6393 Node->getValueType(0),
6394 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6395 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6396 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6398 case Intrinsic::aarch64_sve_uzpq_x2:
6399 SelectUnaryMultiIntrinsic(Node, 2,
false,
6400 AArch64::UZP_VG2_2ZZZ_Q);
6402 case Intrinsic::aarch64_sve_uzp_x4:
6404 Node->getValueType(0),
6405 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6406 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6407 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6409 case Intrinsic::aarch64_sve_uzpq_x4:
6410 SelectUnaryMultiIntrinsic(Node, 4,
true,
6411 AArch64::UZP_VG4_4Z4Z_Q);
6413 case Intrinsic::aarch64_sve_sel_x2:
6415 Node->getValueType(0),
6416 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6417 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6418 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6420 case Intrinsic::aarch64_sve_sel_x4:
6422 Node->getValueType(0),
6423 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6424 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6425 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6427 case Intrinsic::aarch64_sve_frinta_x2:
6428 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6430 case Intrinsic::aarch64_sve_frinta_x4:
6431 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6433 case Intrinsic::aarch64_sve_frintm_x2:
6434 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6436 case Intrinsic::aarch64_sve_frintm_x4:
6437 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6439 case Intrinsic::aarch64_sve_frintn_x2:
6440 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6442 case Intrinsic::aarch64_sve_frintn_x4:
6443 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6445 case Intrinsic::aarch64_sve_frintp_x2:
6446 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6448 case Intrinsic::aarch64_sve_frintp_x4:
6449 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6451 case Intrinsic::aarch64_sve_sunpk_x2:
6453 Node->getValueType(0),
6454 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6455 AArch64::SUNPK_VG2_2ZZ_D}))
6456 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6458 case Intrinsic::aarch64_sve_uunpk_x2:
6460 Node->getValueType(0),
6461 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6462 AArch64::UUNPK_VG2_2ZZ_D}))
6463 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6465 case Intrinsic::aarch64_sve_sunpk_x4:
6467 Node->getValueType(0),
6468 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6469 AArch64::SUNPK_VG4_4Z2Z_D}))
6470 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6472 case Intrinsic::aarch64_sve_uunpk_x4:
6474 Node->getValueType(0),
6475 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6476 AArch64::UUNPK_VG4_4Z2Z_D}))
6477 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6479 case Intrinsic::aarch64_sve_pext_x2: {
6481 Node->getValueType(0),
6482 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6483 AArch64::PEXT_2PCI_D}))
6484 SelectPExtPair(Node,
Op);
6491 unsigned IntNo =
Node->getConstantOperandVal(1);
6492 if (
Node->getNumOperands() >= 3)
6493 VT =
Node->getOperand(2)->getValueType(0);
6497 case Intrinsic::aarch64_neon_st1x2: {
6498 if (VT == MVT::v8i8) {
6499 SelectStore(Node, 2, AArch64::ST1Twov8b);
6501 }
else if (VT == MVT::v16i8) {
6502 SelectStore(Node, 2, AArch64::ST1Twov16b);
6504 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6505 VT == MVT::v4bf16) {
6506 SelectStore(Node, 2, AArch64::ST1Twov4h);
6508 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6509 VT == MVT::v8bf16) {
6510 SelectStore(Node, 2, AArch64::ST1Twov8h);
6512 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6513 SelectStore(Node, 2, AArch64::ST1Twov2s);
6515 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6516 SelectStore(Node, 2, AArch64::ST1Twov4s);
6518 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6519 SelectStore(Node, 2, AArch64::ST1Twov2d);
6521 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6522 SelectStore(Node, 2, AArch64::ST1Twov1d);
6527 case Intrinsic::aarch64_neon_st1x3: {
6528 if (VT == MVT::v8i8) {
6529 SelectStore(Node, 3, AArch64::ST1Threev8b);
6531 }
else if (VT == MVT::v16i8) {
6532 SelectStore(Node, 3, AArch64::ST1Threev16b);
6534 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6535 VT == MVT::v4bf16) {
6536 SelectStore(Node, 3, AArch64::ST1Threev4h);
6538 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6539 VT == MVT::v8bf16) {
6540 SelectStore(Node, 3, AArch64::ST1Threev8h);
6542 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6543 SelectStore(Node, 3, AArch64::ST1Threev2s);
6545 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6546 SelectStore(Node, 3, AArch64::ST1Threev4s);
6548 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6549 SelectStore(Node, 3, AArch64::ST1Threev2d);
6551 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6552 SelectStore(Node, 3, AArch64::ST1Threev1d);
6557 case Intrinsic::aarch64_neon_st1x4: {
6558 if (VT == MVT::v8i8) {
6559 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6561 }
else if (VT == MVT::v16i8) {
6562 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6564 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6565 VT == MVT::v4bf16) {
6566 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6568 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6569 VT == MVT::v8bf16) {
6570 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6572 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6573 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6575 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6576 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6578 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6579 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6581 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6582 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6587 case Intrinsic::aarch64_neon_st2: {
6588 if (VT == MVT::v8i8) {
6589 SelectStore(Node, 2, AArch64::ST2Twov8b);
6591 }
else if (VT == MVT::v16i8) {
6592 SelectStore(Node, 2, AArch64::ST2Twov16b);
6594 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6595 VT == MVT::v4bf16) {
6596 SelectStore(Node, 2, AArch64::ST2Twov4h);
6598 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6599 VT == MVT::v8bf16) {
6600 SelectStore(Node, 2, AArch64::ST2Twov8h);
6602 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6603 SelectStore(Node, 2, AArch64::ST2Twov2s);
6605 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6606 SelectStore(Node, 2, AArch64::ST2Twov4s);
6608 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6609 SelectStore(Node, 2, AArch64::ST2Twov2d);
6611 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6612 SelectStore(Node, 2, AArch64::ST1Twov1d);
6617 case Intrinsic::aarch64_neon_st3: {
6618 if (VT == MVT::v8i8) {
6619 SelectStore(Node, 3, AArch64::ST3Threev8b);
6621 }
else if (VT == MVT::v16i8) {
6622 SelectStore(Node, 3, AArch64::ST3Threev16b);
6624 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6625 VT == MVT::v4bf16) {
6626 SelectStore(Node, 3, AArch64::ST3Threev4h);
6628 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6629 VT == MVT::v8bf16) {
6630 SelectStore(Node, 3, AArch64::ST3Threev8h);
6632 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6633 SelectStore(Node, 3, AArch64::ST3Threev2s);
6635 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6636 SelectStore(Node, 3, AArch64::ST3Threev4s);
6638 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6639 SelectStore(Node, 3, AArch64::ST3Threev2d);
6641 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6642 SelectStore(Node, 3, AArch64::ST1Threev1d);
6647 case Intrinsic::aarch64_neon_st4: {
6648 if (VT == MVT::v8i8) {
6649 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6651 }
else if (VT == MVT::v16i8) {
6652 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6654 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6655 VT == MVT::v4bf16) {
6656 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6658 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6659 VT == MVT::v8bf16) {
6660 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6662 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6663 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6665 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6666 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6668 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6669 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6671 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6672 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6677 case Intrinsic::aarch64_neon_st2lane: {
6678 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6679 SelectStoreLane(Node, 2, AArch64::ST2i8);
6681 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6682 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6683 SelectStoreLane(Node, 2, AArch64::ST2i16);
6685 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6687 SelectStoreLane(Node, 2, AArch64::ST2i32);
6689 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6691 SelectStoreLane(Node, 2, AArch64::ST2i64);
6696 case Intrinsic::aarch64_neon_st3lane: {
6697 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6698 SelectStoreLane(Node, 3, AArch64::ST3i8);
6700 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6701 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6702 SelectStoreLane(Node, 3, AArch64::ST3i16);
6704 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6706 SelectStoreLane(Node, 3, AArch64::ST3i32);
6708 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6710 SelectStoreLane(Node, 3, AArch64::ST3i64);
6715 case Intrinsic::aarch64_neon_st4lane: {
6716 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6717 SelectStoreLane(Node, 4, AArch64::ST4i8);
6719 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6720 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6721 SelectStoreLane(Node, 4, AArch64::ST4i16);
6723 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6725 SelectStoreLane(Node, 4, AArch64::ST4i32);
6727 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6729 SelectStoreLane(Node, 4, AArch64::ST4i64);
6734 case Intrinsic::aarch64_sve_st2q: {
6735 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6738 case Intrinsic::aarch64_sve_st3q: {
6739 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6742 case Intrinsic::aarch64_sve_st4q: {
6743 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6746 case Intrinsic::aarch64_sve_st2: {
6747 if (VT == MVT::nxv16i8) {
6748 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6750 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6751 VT == MVT::nxv8bf16) {
6752 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6754 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6755 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6757 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6758 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6763 case Intrinsic::aarch64_sve_st3: {
6764 if (VT == MVT::nxv16i8) {
6765 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6767 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6768 VT == MVT::nxv8bf16) {
6769 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6771 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6772 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6774 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6775 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6780 case Intrinsic::aarch64_sve_st4: {
6781 if (VT == MVT::nxv16i8) {
6782 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6784 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6785 VT == MVT::nxv8bf16) {
6786 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6788 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6789 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6791 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6792 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6800 case AArch64ISD::LD2post: {
6801 if (VT == MVT::v8i8) {
6802 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6804 }
else if (VT == MVT::v16i8) {
6805 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6807 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6808 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6810 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6811 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6813 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6814 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6816 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6817 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6819 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6820 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6822 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6823 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6828 case AArch64ISD::LD3post: {
6829 if (VT == MVT::v8i8) {
6830 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6832 }
else if (VT == MVT::v16i8) {
6833 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6835 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6836 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6838 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6839 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6841 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6842 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6844 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6845 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6847 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6848 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6850 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6851 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6856 case AArch64ISD::LD4post: {
6857 if (VT == MVT::v8i8) {
6858 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6860 }
else if (VT == MVT::v16i8) {
6861 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6863 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6864 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6866 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6867 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6869 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6870 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6872 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6873 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6875 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6876 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6878 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6879 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6884 case AArch64ISD::LD1x2post: {
6885 if (VT == MVT::v8i8) {
6886 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6888 }
else if (VT == MVT::v16i8) {
6889 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6891 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6892 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6894 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6895 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6897 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6898 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6900 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6901 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6903 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6904 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6906 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6907 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6912 case AArch64ISD::LD1x3post: {
6913 if (VT == MVT::v8i8) {
6914 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6916 }
else if (VT == MVT::v16i8) {
6917 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6919 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6920 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6922 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6923 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6925 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6926 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6928 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6929 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6931 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6932 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6934 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6935 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6940 case AArch64ISD::LD1x4post: {
6941 if (VT == MVT::v8i8) {
6942 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6944 }
else if (VT == MVT::v16i8) {
6945 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6947 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6948 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6950 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6951 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6953 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6954 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6956 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6957 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6959 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6960 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6962 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6963 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6968 case AArch64ISD::LD1DUPpost: {
6969 if (VT == MVT::v8i8) {
6970 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6972 }
else if (VT == MVT::v16i8) {
6973 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6975 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6976 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6978 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6979 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6981 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6982 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6984 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6985 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
6987 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6988 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
6990 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6991 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
6996 case AArch64ISD::LD2DUPpost: {
6997 if (VT == MVT::v8i8) {
6998 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7000 }
else if (VT == MVT::v16i8) {
7001 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7003 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7004 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7006 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7007 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7009 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7010 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7012 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7013 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7015 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7016 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7018 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7019 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7024 case AArch64ISD::LD3DUPpost: {
7025 if (VT == MVT::v8i8) {
7026 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7028 }
else if (VT == MVT::v16i8) {
7029 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7031 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7032 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7034 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7035 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7037 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7038 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7040 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7041 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7043 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7044 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7046 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7047 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7052 case AArch64ISD::LD4DUPpost: {
7053 if (VT == MVT::v8i8) {
7054 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7056 }
else if (VT == MVT::v16i8) {
7057 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7059 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7060 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7062 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7063 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7065 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7066 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7068 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7069 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7071 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7072 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7074 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7075 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7080 case AArch64ISD::LD1LANEpost: {
7081 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7082 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7084 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7085 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7086 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7088 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7090 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7092 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7094 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7099 case AArch64ISD::LD2LANEpost: {
7100 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7101 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7103 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7104 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7105 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7107 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7109 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7111 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7113 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7118 case AArch64ISD::LD3LANEpost: {
7119 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7120 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7122 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7123 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7124 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7126 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7128 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7130 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7132 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7137 case AArch64ISD::LD4LANEpost: {
7138 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7139 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7141 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7142 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7143 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7145 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7147 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7149 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7151 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7156 case AArch64ISD::ST2post: {
7157 VT =
Node->getOperand(1).getValueType();
7158 if (VT == MVT::v8i8) {
7159 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7161 }
else if (VT == MVT::v16i8) {
7162 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7164 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7165 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7167 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7168 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7170 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7171 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7173 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7174 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7176 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7177 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7179 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7180 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7185 case AArch64ISD::ST3post: {
7186 VT =
Node->getOperand(1).getValueType();
7187 if (VT == MVT::v8i8) {
7188 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7190 }
else if (VT == MVT::v16i8) {
7191 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7193 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7194 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7196 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7197 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7199 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7200 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7202 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7203 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7205 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7206 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7208 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7209 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7214 case AArch64ISD::ST4post: {
7215 VT =
Node->getOperand(1).getValueType();
7216 if (VT == MVT::v8i8) {
7217 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7219 }
else if (VT == MVT::v16i8) {
7220 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7222 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7223 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7225 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7226 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7228 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7229 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7231 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7232 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7234 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7235 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7237 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7238 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7243 case AArch64ISD::ST1x2post: {
7244 VT =
Node->getOperand(1).getValueType();
7245 if (VT == MVT::v8i8) {
7246 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7248 }
else if (VT == MVT::v16i8) {
7249 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7251 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7252 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7254 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7255 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7257 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7258 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7260 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7261 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7263 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7264 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7266 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7267 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7272 case AArch64ISD::ST1x3post: {
7273 VT =
Node->getOperand(1).getValueType();
7274 if (VT == MVT::v8i8) {
7275 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7277 }
else if (VT == MVT::v16i8) {
7278 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7280 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7281 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7283 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7284 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7286 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7287 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7289 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7290 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7292 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7293 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7295 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7296 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7301 case AArch64ISD::ST1x4post: {
7302 VT =
Node->getOperand(1).getValueType();
7303 if (VT == MVT::v8i8) {
7304 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7306 }
else if (VT == MVT::v16i8) {
7307 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7309 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7310 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7312 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7313 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7315 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7316 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7318 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7319 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7321 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7322 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7324 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7325 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7330 case AArch64ISD::ST2LANEpost: {
7331 VT =
Node->getOperand(1).getValueType();
7332 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7333 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7335 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7336 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7337 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7339 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7341 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7343 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7345 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7350 case AArch64ISD::ST3LANEpost: {
7351 VT =
Node->getOperand(1).getValueType();
7352 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7353 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7355 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7356 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7357 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7359 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7361 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7363 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7365 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7370 case AArch64ISD::ST4LANEpost: {
7371 VT =
Node->getOperand(1).getValueType();
7372 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7373 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7375 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7376 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7377 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7379 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7381 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7383 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7385 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7400 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7412 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7416 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7417 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7432 return MemIntr->getMemoryVT();
7439 DataVT = Load->getValueType(0);
7441 DataVT = Load->getValueType(0);
7443 DataVT = Store->getValue().getValueType();
7445 DataVT = Store->getValue().getValueType();
7452 const unsigned Opcode = Root->
getOpcode();
7456 case AArch64ISD::LD1_MERGE_ZERO:
7457 case AArch64ISD::LD1S_MERGE_ZERO:
7458 case AArch64ISD::LDNF1_MERGE_ZERO:
7459 case AArch64ISD::LDNF1S_MERGE_ZERO:
7461 case AArch64ISD::ST1_PRED:
7473 case Intrinsic::aarch64_sme_ldr:
7474 case Intrinsic::aarch64_sme_str:
7475 return MVT::nxv16i8;
7476 case Intrinsic::aarch64_sve_prf:
7481 case Intrinsic::aarch64_sve_ld2_sret:
7482 case Intrinsic::aarch64_sve_ld2q_sret:
7485 case Intrinsic::aarch64_sve_st2q:
7488 case Intrinsic::aarch64_sve_ld3_sret:
7489 case Intrinsic::aarch64_sve_ld3q_sret:
7492 case Intrinsic::aarch64_sve_st3q:
7495 case Intrinsic::aarch64_sve_ld4_sret:
7496 case Intrinsic::aarch64_sve_ld4q_sret:
7499 case Intrinsic::aarch64_sve_st4q:
7502 case Intrinsic::aarch64_sve_ld1udq:
7503 case Intrinsic::aarch64_sve_st1dq:
7504 return EVT(MVT::nxv1i64);
7505 case Intrinsic::aarch64_sve_ld1uwq:
7506 case Intrinsic::aarch64_sve_st1wq:
7507 return EVT(MVT::nxv1i32);
7514template <
int64_t Min,
int64_t Max>
7515bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7519 const DataLayout &
DL = CurDAG->getDataLayout();
7520 const MachineFrameInfo &MFI = MF->getFrameInfo();
7528 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7542 int64_t MulImm = std::numeric_limits<int64_t>::max();
7546 int64_t ByteOffset =
C->getSExtValue();
7547 const auto KnownVScale =
7550 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7553 MulImm = ByteOffset / KnownVScale;
7560 if ((MulImm % MemWidthBytes) != 0)
7563 int64_t
Offset = MulImm / MemWidthBytes;
7567 Base =
N.getOperand(0);
7576 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7582bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7601 int64_t ImmOff =
C->getSExtValue();
7602 unsigned Size = 1 << Scale;
7611 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7613 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7624 if (
C->getZExtValue() == Scale) {
7633bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7634 const AArch64TargetLowering *TLI =
7635 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7640bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7641 EVT VT =
N.getValueType();
7645bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7650 int64_t ImmOff =
C->getSExtValue();
7651 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7652 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7657 if (
SDValue C = MatchConstantOffset(
N)) {
7658 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7664 if (CurDAG->isBaseWithConstantOffset(
N)) {
7665 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7666 Base =
N.getOperand(0);
7674 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7678bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7698 uint64_t LowerBound = 0, UpperBound = 64;
7716 if (CN->getAPIntValue().uge(LowerBound) &&
7717 CN->getAPIntValue().ult(UpperBound)) {
7719 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7727template <
bool MatchCBB>
7734 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7736 Reg =
N.getOperand(0);
7738 SDLoc(
N), MVT::i32);
7746 Reg =
N.getOperand(0);
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const AArch64RegisterInfo * getRegisterInfo() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(SelectionDAG &DAG, SDValue N) const
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
uint64_t getScalarSizeInBits() const
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static MVT getVectorVT(MVT VT, unsigned NumElements)
bool hasScalableStackID(int ObjectIdx) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
unsigned getID() const
Return the register class ID number.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t parseGenericRegister(StringRef Name)
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static bool isSVELogicalImm(unsigned SizeInBits, uint64_t ImmVal, uint64_t &Encoding)
static bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static constexpr unsigned SVEBitsPerBlock
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
@ Undef
Value of the register doesn't matter.
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
unsigned getBitWidth() const
Get the bit width of this value.