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>
84 return SelectShiftedRegister(
N,
false,
Reg, Shift);
87 return SelectShiftedRegister(
N,
true,
Reg, Shift);
90 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
93 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
96 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
99 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
102 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
105 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
108 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
111 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
114 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
117 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
120 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
123 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
126 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
129 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
132 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
135 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
138 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
140 template <
unsigned Size,
unsigned Max>
144 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
147 int64_t
C = CI->getSExtValue();
155 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
162 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
168 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
173 N =
N->getOperand(0);
177 EVT VT =
N->getValueType(0);
178 EVT LVT =
N->getOperand(0).getValueType();
179 unsigned Index =
N->getConstantOperandVal(1);
183 Res =
N->getOperand(0);
188 if (
N.getOpcode() != AArch64ISD::VLSHR)
191 EVT VT =
Op.getValueType();
192 unsigned ShtAmt =
N->getConstantOperandVal(1);
197 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
199 Op.getOperand(1).getConstantOperandVal(0)
200 <<
Op.getOperand(1).getConstantOperandVal(1));
201 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
204 Op.getOperand(1).getConstantOperandVal(0));
208 if (Imm != 1ULL << (ShtAmt - 1))
211 Res1 =
Op.getOperand(0);
212 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
216 bool SelectDupZeroOrUndef(
SDValue N) {
217 switch(
N->getOpcode()) {
220 case AArch64ISD::DUP:
222 auto Opnd0 =
N->getOperand(0);
236 bool SelectAny(
SDValue) {
return true; }
239 switch(
N->getOpcode()) {
240 case AArch64ISD::DUP:
242 auto Opnd0 =
N->getOperand(0);
254 template <MVT::SimpleValueType VT,
bool Negate>
256 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
259 template <MVT::SimpleValueType VT,
bool Negate>
261 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
264 template <MVT::SimpleValueType VT>
266 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
269 template <MVT::SimpleValueType VT,
bool Invert = false>
271 return SelectSVELogicalImm(
N, VT, Imm, Invert);
274 template <MVT::SimpleValueType VT>
276 return SelectSVEArithImm(
N, VT, Imm);
279 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
281 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
288 EVT EltVT =
N->getValueType(0).getVectorElementType();
289 return SelectSVEShiftImm(
N->getOperand(0), 1,
295 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
302 MulImm = 1LL << MulImm;
304 if ((MulImm % std::abs(Scale)) != 0)
308 if ((MulImm >= Min) && (MulImm <= Max)) {
309 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
316 template <
signed Max,
signed Scale>
323 if (MulImm >= 0 && MulImm <= Max) {
325 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
332 template <
unsigned BaseReg,
unsigned Max>
340 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
363 const unsigned SubRegs[]);
365 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
367 bool tryIndexedLoad(
SDNode *
N);
369 void SelectPtrauthAuth(
SDNode *
N);
370 void SelectPtrauthResign(
SDNode *
N);
372 bool trySelectStackSlotTagP(
SDNode *
N);
375 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
377 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
379 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
380 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
381 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
382 unsigned Opc_rr,
unsigned Opc_ri,
383 bool IsIntr =
false);
384 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
385 unsigned Scale,
unsigned Opc_ri,
387 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
388 bool IsZmMulti,
unsigned Opcode,
389 bool HasPred =
false);
391 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
392 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
393 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
394 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
395 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
396 bool IsTupleInput,
unsigned Opc);
397 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
399 template <
unsigned MaxIdx,
unsigned Scale>
400 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
402 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
403 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
404 unsigned BaseReg = 0);
407 template <
int64_t Min,
int64_t Max>
411 template <
unsigned Scale>
413 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
416 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
419 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc);
421 template <
unsigned MaxIdx,
unsigned Scale>
426 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
427 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
428 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
429 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
430 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
431 unsigned Opc_rr,
unsigned Opc_ri);
432 std::tuple<unsigned, SDValue, SDValue>
433 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
437 bool tryBitfieldExtractOp(
SDNode *
N);
438 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
439 bool tryBitfieldInsertOp(
SDNode *
N);
440 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
441 bool tryShiftAmountMod(
SDNode *
N);
443 bool tryReadRegister(
SDNode *
N);
444 bool tryWriteRegister(
SDNode *
N);
446 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
447 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
452#include "AArch64GenDAGISel.inc"
460 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
462 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
475 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
476 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
477 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
480 template<
unsigned RegW
idth>
482 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
485 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
487 template<
unsigned RegW
idth>
489 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
495 bool SelectCMP_SWAP(
SDNode *
N);
506 bool AllowSaturation,
SDValue &Imm);
514 bool SelectAllActivePredicate(
SDValue N);
519 template <
bool MatchCBB>
529 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
533char AArch64DAGToDAGISelLegacy::ID = 0;
541 Imm =
C->getZExtValue();
558 return N->getOpcode() ==
Opc &&
569 return Imm == ImmExpected;
573bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
575 std::vector<SDValue> &OutOps) {
576 switch(ConstraintID) {
579 case InlineAsm::ConstraintCode::m:
580 case InlineAsm::ConstraintCode::o:
581 case InlineAsm::ConstraintCode::Q:
585 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
587 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
589 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
590 dl,
Op.getValueType(),
592 OutOps.push_back(NewOp);
611 uint64_t Immed =
N.getNode()->getAsZExtVal();
614 if (Immed >> 12 == 0) {
616 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
624 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
625 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
642 uint64_t Immed =
N.getNode()->getAsZExtVal();
650 if (
N.getValueType() == MVT::i32)
651 Immed = ~((uint32_t)Immed) + 1;
653 Immed = ~Immed + 1ULL;
654 if (Immed & 0xFFFFFFFFFF000000ULL)
657 Immed &= 0xFFFFFFULL;
658 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
665 switch (
N.getOpcode()) {
691 unsigned ShiftVal = CSD->getZExtValue();
709bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
712 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
717 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
741 EVT VT =
N.getValueType();
742 if (VT != MVT::i32 && VT != MVT::i64)
745 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
751 unsigned LHSOpcode =
LHS->getOpcode();
765 unsigned LowZBits, MaskLen;
769 unsigned BitWidth =
N.getValueSizeInBits();
776 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
779 NewShiftC = LowZBits - ShiftAmtC;
780 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
786 NewShiftC = LowZBits + ShiftAmtC;
799 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
801 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
805 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
807 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
808 NewShiftAmt, BitWidthMinus1),
811 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
825 SrcVT =
N.getOperand(0).getValueType();
827 if (!IsLoadStore && SrcVT == MVT::i8)
829 else if (!IsLoadStore && SrcVT == MVT::i16)
831 else if (SrcVT == MVT::i32)
833 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
838 EVT SrcVT =
N.getOperand(0).getValueType();
839 if (!IsLoadStore && SrcVT == MVT::i8)
841 else if (!IsLoadStore && SrcVT == MVT::i16)
843 else if (SrcVT == MVT::i32)
845 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
873bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
876 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
881 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
882 V.getConstantOperandVal(1) <= 4 &&
895bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
897 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
907 unsigned BitSize =
N.getValueSizeInBits();
908 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
911 Reg =
N.getOperand(0);
912 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
913 return isWorthFoldingALU(
N,
true);
924 if (
N.getValueType() == MVT::i32)
932template<
signed Low,
signed High,
signed Scale>
938 if ((MulImm % std::abs(Scale)) == 0) {
939 int64_t RDVLImm = MulImm / Scale;
940 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
941 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
950template <
signed Low,
signed High>
951bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
956 if (MulImm >=
Low && MulImm <=
High) {
957 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
981 unsigned ShiftVal = 0;
996 Reg =
N.getOperand(0).getOperand(0);
1002 Reg =
N.getOperand(0);
1007 unsigned Opc =
N.getOpcode();
1025 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1027 return isWorthFoldingALU(
N);
1034 unsigned ShiftVal = 0;
1048 Reg =
N.getOperand(0);
1049 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1051 return isWorthFoldingALU(
N);
1060 for (
auto *
User :
N->users()) {
1087bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1088 unsigned BW,
unsigned Size,
1092 const DataLayout &
DL = CurDAG->getDataLayout();
1093 const TargetLowering *TLI = getTargetLowering();
1097 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1103 if (CurDAG->isBaseWithConstantOffset(
N)) {
1106 int64_t RHSC =
RHS->getSExtValue();
1108 int64_t
Range = 0x1LL << (BW - 1);
1110 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1111 RHSC < (
Range << Scale)) {
1112 Base =
N.getOperand(0);
1117 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1122 uint64_t RHSC =
RHS->getZExtValue();
1124 uint64_t
Range = 0x1ULL << BW;
1126 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1127 Base =
N.getOperand(0);
1132 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1143 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1150bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1153 const DataLayout &
DL = CurDAG->getDataLayout();
1154 const TargetLowering *TLI = getTargetLowering();
1158 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1163 GlobalAddressSDNode *GAN =
1165 Base =
N.getOperand(0);
1175 if (CurDAG->isBaseWithConstantOffset(
N)) {
1177 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1180 Base =
N.getOperand(0);
1185 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1193 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1201 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1210bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1213 if (!CurDAG->isBaseWithConstantOffset(
N))
1216 int64_t RHSC =
RHS->getSExtValue();
1217 if (RHSC >= -256 && RHSC < 256) {
1218 Base =
N.getOperand(0);
1221 const TargetLowering *TLI = getTargetLowering();
1222 Base = CurDAG->getTargetFrameIndex(
1225 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1235 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1242bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1262 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1268 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1271 return isWorthFoldingAddr(
N,
Size);
1274bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1292 const SDNode *
Node =
N.getNode();
1293 for (SDNode *UI :
Node->users()) {
1299 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1302 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1305 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1310 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1313 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1318 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1322 if (IsExtendedRegisterWorthFolding &&
1329 if (isWorthFoldingAddr(
LHS,
Size))
1334 if (IsExtendedRegisterWorthFolding &&
1341 if (isWorthFoldingAddr(
RHS,
Size))
1353 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1356 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1358 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1359 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1363bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1376 const SDNode *
Node =
N.getNode();
1377 for (SDNode *UI :
Node->users()) {
1394 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1404 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1411 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1414 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1417 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1422 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1425 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1432 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1433 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1439 static const unsigned RegClassIDs[] = {
1440 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1441 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1442 AArch64::dsub2, AArch64::dsub3};
1448 static const unsigned RegClassIDs[] = {
1449 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1450 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1451 AArch64::qsub2, AArch64::qsub3};
1457 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1458 AArch64::ZPR3RegClassID,
1459 AArch64::ZPR4RegClassID};
1460 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1461 AArch64::zsub2, AArch64::zsub3};
1471 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1472 AArch64::ZPR4Mul4RegClassID};
1473 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1474 AArch64::zsub2, AArch64::zsub3};
1479 const unsigned RegClassIDs[],
1480 const unsigned SubRegs[]) {
1483 if (Regs.
size() == 1)
1494 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1497 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1498 Ops.push_back(Regs[i]);
1499 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1503 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1507void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1510 EVT VT =
N->getValueType(0);
1512 unsigned ExtOff = isExt;
1515 unsigned Vec0Off = ExtOff + 1;
1521 Ops.push_back(
N->getOperand(1));
1522 Ops.push_back(RegSeq);
1523 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1524 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1527static std::tuple<SDValue, SDValue>
1548 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1553 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1555 return std::make_tuple(
1560void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1565 SDValue AUTDisc =
N->getOperand(3);
1568 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1570 SDValue AUTAddrDisc, AUTConstDisc;
1571 std::tie(AUTConstDisc, AUTAddrDisc) =
1575 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1577 if (
N->getNumOperands() > 4)
1578 Ops.push_back(
N->getOperand(4));
1581 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1582 ReplaceNode(
N, AUT);
1584 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1585 AArch64::X16, Val,
SDValue());
1588 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1589 ReplaceNode(
N, AUT);
1593void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1605 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1606 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1608 SDValue AUTAddrDisc, AUTConstDisc;
1609 std::tie(AUTConstDisc, AUTAddrDisc) =
1612 SDValue PACAddrDisc, PACConstDisc;
1613 std::tie(PACConstDisc, PACAddrDisc) =
1616 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1617 AArch64::X16, Val,
SDValue());
1619 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1620 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1622 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1623 ReplaceNode(
N, AUTPAC);
1626bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1628 if (
LD->isUnindexed())
1630 EVT VT =
LD->getMemoryVT();
1631 EVT DstVT =
N->getValueType(0);
1635 int OffsetVal = (int)
OffsetOp->getZExtValue();
1640 unsigned Opcode = 0;
1643 bool InsertTo64 =
false;
1645 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1646 else if (VT == MVT::i32) {
1648 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1650 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1652 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1658 }
else if (VT == MVT::i16) {
1660 if (DstVT == MVT::i64)
1661 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1663 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1665 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1666 InsertTo64 = DstVT == MVT::i64;
1671 }
else if (VT == MVT::i8) {
1673 if (DstVT == MVT::i64)
1674 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1676 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1678 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1679 InsertTo64 = DstVT == MVT::i64;
1684 }
else if (VT == MVT::f16) {
1685 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1686 }
else if (VT == MVT::bf16) {
1687 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1688 }
else if (VT == MVT::f32) {
1689 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1690 }
else if (VT == MVT::f64 ||
1692 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1694 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1696 if (IsPre || OffsetVal != 8)
1700 Opcode = AArch64::LD1Onev8b_POST;
1703 Opcode = AArch64::LD1Onev4h_POST;
1706 Opcode = AArch64::LD1Onev2s_POST;
1709 Opcode = AArch64::LD1Onev1d_POST;
1715 if (IsPre || OffsetVal != 16)
1719 Opcode = AArch64::LD1Onev16b_POST;
1722 Opcode = AArch64::LD1Onev8h_POST;
1725 Opcode = AArch64::LD1Onev4s_POST;
1728 Opcode = AArch64::LD1Onev2d_POST;
1740 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1741 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1743 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1753 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1755 SDValue(CurDAG->getMachineNode(
1756 AArch64::SUBREG_TO_REG, dl, MVT::i64,
1757 CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal,
1762 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1765 CurDAG->RemoveDeadNode(
N);
1769void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1770 unsigned SubRegIdx) {
1772 EVT VT =
N->getValueType(0);
1778 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1780 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1782 for (
unsigned i = 0; i < NumVecs; ++i)
1784 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1791 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1795 CurDAG->RemoveDeadNode(
N);
1798void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1799 unsigned Opc,
unsigned SubRegIdx) {
1801 EVT VT =
N->getValueType(0);
1808 const EVT ResTys[] = {MVT::i64,
1809 MVT::Untyped, MVT::Other};
1811 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1819 ReplaceUses(
SDValue(
N, 0), SuperReg);
1821 for (
unsigned i = 0; i < NumVecs; ++i)
1823 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1827 CurDAG->RemoveDeadNode(
N);
1833std::tuple<unsigned, SDValue, SDValue>
1834AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1840 SDValue NewOffset = OldOffset;
1842 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1843 N, OldBase, NewBase, NewOffset);
1847 const bool IsRegReg =
1848 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1851 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
1864template <SelectTypeKind Kind>
1876 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
1881 if (EltVT != MVT::i1)
1885 if (EltVT == MVT::bf16)
1887 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
1917void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
1920 if (
Imm->getZExtValue() > 1)
1924 EVT VT =
N->getValueType(0);
1926 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1929 for (
unsigned I = 0;
I < 2; ++
I)
1930 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1931 AArch64::psub0 +
I,
DL, VT, SuperReg));
1933 CurDAG->RemoveDeadNode(
N);
1936void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
1938 EVT VT =
N->getValueType(0);
1942 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
1945 for (
unsigned I = 0;
I < 2; ++
I)
1946 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
1947 AArch64::psub0 +
I,
DL, VT, SuperReg));
1949 CurDAG->RemoveDeadNode(
N);
1952void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
1954 EVT VT =
N->getValueType(0);
1958 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
1960 for (
unsigned i = 0; i < NumVecs; ++i)
1961 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1962 AArch64::zsub0 + i,
DL, VT, SuperReg));
1964 CurDAG->RemoveDeadNode(
N);
1967void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
1970 EVT VT =
N->getValueType(0);
1972 Ops.push_back(
N->getOperand(0));
1975 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
1978 for (
unsigned i = 0; i < NumVecs; ++i)
1979 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
1980 AArch64::zsub0 + i,
DL, VT, SuperReg));
1983 unsigned ChainIdx = NumVecs;
1985 CurDAG->RemoveDeadNode(
N);
1988void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
1993 assert(Opcode != 0 &&
"Unexpected opcode");
1996 EVT VT =
N->getValueType(0);
1997 unsigned FirstVecIdx = HasPred ? 2 : 1;
1999 auto GetMultiVecOperand = [=](
unsigned StartIdx) {
2001 return createZMulTuple(Regs);
2004 SDValue Zdn = GetMultiVecOperand(FirstVecIdx);
2008 Zm = GetMultiVecOperand(NumVecs + FirstVecIdx);
2014 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
2015 N->getOperand(1), Zdn, Zm);
2017 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped, Zdn, Zm);
2019 for (
unsigned i = 0; i < NumVecs; ++i)
2020 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2021 AArch64::zsub0 + i,
DL, VT, SuperReg));
2023 CurDAG->RemoveDeadNode(
N);
2026void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2027 unsigned Scale,
unsigned Opc_ri,
2028 unsigned Opc_rr,
bool IsIntr) {
2029 assert(Scale < 5 &&
"Invalid scaling value.");
2031 EVT VT =
N->getValueType(0);
2038 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2039 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2045 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2047 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2049 for (
unsigned i = 0; i < NumVecs; ++i)
2050 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2051 AArch64::zsub0 + i,
DL, VT, SuperReg));
2054 unsigned ChainIdx = NumVecs;
2056 CurDAG->RemoveDeadNode(
N);
2059void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2064 assert(Scale < 4 &&
"Invalid scaling value.");
2066 EVT VT =
N->getValueType(0);
2074 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2080 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2082 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2084 for (
unsigned i = 0; i < NumVecs; ++i)
2085 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2086 AArch64::zsub0 + i,
DL, VT, SuperReg));
2089 unsigned ChainIdx = NumVecs;
2091 CurDAG->RemoveDeadNode(
N);
2094void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2096 if (
N->getValueType(0) != MVT::nxv4f32)
2098 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2101void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2102 unsigned NumOutVecs,
2106 if (
Imm->getZExtValue() > MaxImm)
2110 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2116 EVT VT =
Node->getValueType(0);
2119 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2122 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2123 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2124 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2127 unsigned ChainIdx = NumOutVecs;
2129 CurDAG->RemoveDeadNode(Node);
2132void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2133 unsigned NumOutVecs,
2136 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2141 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2145 EVT VT =
Node->getValueType(0);
2148 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2151 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2152 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2153 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2156 unsigned ChainIdx = NumOutVecs;
2158 CurDAG->RemoveDeadNode(Node);
2161void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2164 EVT VT =
N->getValueType(0);
2167 SDValue Zd = createZMulTuple(Regs);
2168 SDValue Zn =
N->getOperand(1 + NumVecs);
2175 for (
unsigned i = 0; i < NumVecs; ++i)
2176 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2177 AArch64::zsub0 + i,
DL, VT, SuperReg));
2179 CurDAG->RemoveDeadNode(
N);
2209template <
unsigned MaxIdx,
unsigned Scale>
2210void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2211 unsigned BaseReg,
unsigned Op) {
2212 unsigned TileNum = 0;
2213 if (BaseReg != AArch64::ZA)
2214 TileNum =
N->getConstantOperandVal(2);
2220 if (BaseReg == AArch64::ZA)
2225 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2231 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2233 EVT VT =
N->getValueType(0);
2234 for (
unsigned I = 0;
I < NumVecs; ++
I)
2236 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2239 unsigned ChainIdx = NumVecs;
2241 CurDAG->RemoveDeadNode(
N);
2244void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2245 unsigned Op,
unsigned MaxIdx,
2246 unsigned Scale,
unsigned BaseReg) {
2251 if (BaseReg != AArch64::ZA)
2255 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2262 if (BaseReg != AArch64::ZA )
2263 Ops.push_back(
N->getOperand(2));
2266 Ops.push_back(
N->getOperand(0));
2267 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2269 EVT VT =
N->getValueType(0);
2270 for (
unsigned I = 0;
I < NumVecs; ++
I)
2272 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2276 unsigned ChainIdx = NumVecs;
2278 CurDAG->RemoveDeadNode(
N);
2281void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2282 unsigned NumOutVecs,
2286 EVT VT =
N->getValueType(0);
2287 unsigned NumInVecs =
N->getNumOperands() - 1;
2291 assert((NumInVecs == 2 || NumInVecs == 4) &&
2292 "Don't know how to handle multi-register input!");
2294 Ops.push_back(createZMulTuple(Regs));
2297 for (
unsigned I = 0;
I < NumInVecs;
I++)
2298 Ops.push_back(
N->getOperand(1 +
I));
2301 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2304 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2305 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2306 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2307 CurDAG->RemoveDeadNode(
N);
2310void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2313 EVT VT =
N->getOperand(2)->getValueType(0);
2321 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2330void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2331 unsigned Scale,
unsigned Opc_rr,
2337 SDValue RegSeq = createZTuple(Regs);
2343 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2344 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2350 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2358 const DataLayout &
DL = CurDAG->getDataLayout();
2359 const TargetLowering *TLI = getTargetLowering();
2363 int FI = FINode->getIndex();
2365 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2372void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2375 EVT VT =
N->getOperand(2)->getValueType(0);
2376 const EVT ResTys[] = {MVT::i64,
2388 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2428void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2431 EVT VT =
N->getValueType(0);
2443 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2445 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2447 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2449 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2453 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2454 AArch64::qsub2, AArch64::qsub3 };
2455 for (
unsigned i = 0; i < NumVecs; ++i) {
2456 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2463 CurDAG->RemoveDeadNode(
N);
2466void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2469 EVT VT =
N->getValueType(0);
2481 const EVT ResTys[] = {MVT::i64,
2484 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2487 CurDAG->getTargetConstant(LaneNo, dl,
2492 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2504 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2505 AArch64::qsub2, AArch64::qsub3 };
2506 for (
unsigned i = 0; i < NumVecs; ++i) {
2507 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2517 CurDAG->RemoveDeadNode(
N);
2520void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2523 EVT VT =
N->getOperand(2)->getValueType(0);
2535 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2537 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2539 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2548void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2551 EVT VT =
N->getOperand(2)->getValueType(0);
2563 const EVT ResTys[] = {MVT::i64,
2566 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2568 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2572 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2583 unsigned &LSB,
unsigned &MSB,
2584 unsigned NumberOfIgnoredLowBits,
2585 bool BiggerPattern) {
2587 "N must be a AND operation to call this function");
2589 EVT VT =
N->getValueType(0);
2594 assert((VT == MVT::i32 || VT == MVT::i64) &&
2595 "Type checking must have been done before calling this function");
2609 const SDNode *Op0 =
N->getOperand(0).getNode();
2616 if (AndImm & (AndImm + 1))
2619 bool ClampMSB =
false;
2639 ClampMSB = (VT == MVT::i32);
2640 }
else if (BiggerPattern) {
2646 Opd0 =
N->getOperand(0);
2652 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2655 <<
": Found large shift immediate, this should not happen\n"));
2669 MSB = MSB > 31 ? 31 : MSB;
2671 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2676 SDValue &Opd0,
unsigned &Immr,
2680 EVT VT =
N->getValueType(0);
2682 assert((VT == MVT::i32 || VT == MVT::i64) &&
2683 "Type checking must have been done before calling this function");
2687 Op =
Op->getOperand(0);
2688 VT =
Op->getValueType(0);
2697 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2701 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2702 Opd0 =
Op.getOperand(0);
2704 Imms = ShiftImm + Width - 1;
2732 Opd0 =
N->getOperand(0).getOperand(0);
2742 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2749 unsigned &Immr,
unsigned &Imms,
2750 bool BiggerPattern) {
2752 "N must be a SHR/SRA operation to call this function");
2754 EVT VT =
N->getValueType(0);
2759 assert((VT == MVT::i32 || VT == MVT::i64) &&
2760 "Type checking must have been done before calling this function");
2770 Opd0 =
N->getOperand(0).getOperand(0);
2771 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2777 Opd0 =
N->getOperand(0).getOperand(0);
2780 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2781 }
else if (BiggerPattern) {
2785 Opd0 =
N->getOperand(0);
2794 <<
": Found large shift immediate, this should not happen\n"));
2803 "bad amount in shift node!");
2804 int immr = SrlImm - ShlImm;
2809 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2811 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2815bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2818 EVT VT =
N->getValueType(0);
2819 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2820 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2831 unsigned Immr = ShiftImm;
2833 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2834 CurDAG->getTargetConstant(Imms, dl, VT)};
2835 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2840 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2841 unsigned NumberOfIgnoredLowBits = 0,
2842 bool BiggerPattern =
false) {
2843 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2846 switch (
N->getOpcode()) {
2848 if (!
N->isMachineOpcode())
2853 NumberOfIgnoredLowBits, BiggerPattern);
2862 unsigned NOpc =
N->getMachineOpcode();
2866 case AArch64::SBFMWri:
2867 case AArch64::UBFMWri:
2868 case AArch64::SBFMXri:
2869 case AArch64::UBFMXri:
2871 Opd0 =
N->getOperand(0);
2872 Immr =
N->getConstantOperandVal(1);
2873 Imms =
N->getConstantOperandVal(2);
2880bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
2881 unsigned Opc, Immr, Imms;
2886 EVT VT =
N->getValueType(0);
2891 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
2892 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
2893 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
2895 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
2896 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
2902 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2903 CurDAG->getTargetConstant(Imms, dl, VT)};
2904 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
2913 unsigned NumberOfIgnoredHighBits,
EVT VT) {
2914 assert((VT == MVT::i32 || VT == MVT::i64) &&
2915 "i32 or i64 mask type expected!");
2919 APInt SignificantDstMask =
2923 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
2924 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
2957 APInt OpUsefulBits(UsefulBits);
2961 OpUsefulBits <<= MSB - Imm + 1;
2966 OpUsefulBits <<= Imm;
2968 OpUsefulBits <<= MSB + 1;
2971 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
2977 UsefulBits &= OpUsefulBits;
2994 APInt Mask(UsefulBits);
2995 Mask.clearAllBits();
3003 Mask.lshrInPlace(ShiftAmt);
3009 Mask.lshrInPlace(ShiftAmt);
3025 APInt OpUsefulBits(UsefulBits);
3039 OpUsefulBits <<= Width;
3042 if (
Op.getOperand(1) == Orig) {
3044 Mask = ResultUsefulBits & OpUsefulBits;
3048 if (
Op.getOperand(0) == Orig)
3050 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3056 OpUsefulBits <<= Width;
3058 OpUsefulBits <<= LSB;
3060 if (
Op.getOperand(1) == Orig) {
3062 Mask = ResultUsefulBits & OpUsefulBits;
3063 Mask.lshrInPlace(LSB);
3066 if (
Op.getOperand(0) == Orig)
3067 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3084 case AArch64::ANDSWri:
3085 case AArch64::ANDSXri:
3086 case AArch64::ANDWri:
3087 case AArch64::ANDXri:
3091 case AArch64::UBFMWri:
3092 case AArch64::UBFMXri:
3095 case AArch64::ORRWrs:
3096 case AArch64::ORRXrs:
3101 case AArch64::BFMWri:
3102 case AArch64::BFMXri:
3105 case AArch64::STRBBui:
3106 case AArch64::STURBBi:
3112 case AArch64::STRHHui:
3113 case AArch64::STURHHi:
3126 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3128 UsefulBits =
APInt(Bitwidth, 0);
3137 UsersUsefulBits |= UsefulBitsForUse;
3142 UsefulBits &= UsersUsefulBits;
3152 EVT VT =
Op.getValueType();
3155 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3158 if (ShlAmount > 0) {
3161 UBFMOpc, dl, VT,
Op,
3166 assert(ShlAmount < 0 &&
"expected right shift");
3167 int ShrAmount = -ShlAmount;
3179 const uint64_t NonZeroBits,
3186 const uint64_t NonZeroBits,
3193 bool BiggerPattern,
SDValue &Src,
3194 int &DstLSB,
int &Width) {
3195 EVT VT =
Op.getValueType();
3204 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3208 switch (
Op.getOpcode()) {
3213 NonZeroBits, Src, DstLSB, Width);
3216 NonZeroBits, Src, DstLSB, Width);
3229 EVT VT =
Op.getValueType();
3230 assert((VT == MVT::i32 || VT == MVT::i64) &&
3231 "Caller guarantees VT is one of i32 or i64");
3244 assert((~AndImm & NonZeroBits) == 0 &&
3245 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3274 if (!BiggerPattern && !AndOp0.
hasOneUse())
3293 <<
"Found large Width in bit-field-positioning -- this indicates no "
3294 "proper combining / constant folding was performed\n");
3303 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3318 "Op.getNode() should be a SHL node to call this function");
3320 "Op.getNode() should shift ShlImm to call this function");
3327 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3351 EVT VT =
Op.getValueType();
3352 assert((VT == MVT::i32 || VT == MVT::i64) &&
3353 "Caller guarantees that type is i32 or i64");
3360 if (!BiggerPattern && !
Op.hasOneUse())
3369 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3377 assert(VT == MVT::i32 || VT == MVT::i64);
3388 EVT VT =
N->getValueType(0);
3389 if (VT != MVT::i32 && VT != MVT::i64)
3407 if (!
And.hasOneUse() ||
3417 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3424 if ((OrImm & NotKnownZero) != 0) {
3436 unsigned ImmS = Width - 1;
3442 bool IsBFI = LSB != 0;
3447 unsigned OrChunks = 0, BFIChunks = 0;
3448 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3449 if (((OrImm >> Shift) & 0xFFFF) != 0)
3451 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3454 if (BFIChunks > OrChunks)
3460 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3468 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3477 if (!Dst.hasOneUse())
3480 EVT VT = Dst.getValueType();
3481 assert((VT == MVT::i32 || VT == MVT::i64) &&
3482 "Caller should guarantee that VT is one of i32 or i64");
3510 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3511 unsigned MaskWidth =
3514 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3520 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3521 ShiftedOperand =
SDValue(UBFMNode, 0);
3550 const bool BiggerPattern) {
3551 EVT VT =
N->getValueType(0);
3552 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3553 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3554 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3555 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3556 assert((VT == MVT::i32 || VT == MVT::i64) &&
3557 "Expect result type to be i32 or i64 since N is combinable to BFM");
3564 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3567 if (BiggerPattern) {
3590 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3652 EVT VT =
N->getValueType(0);
3653 if (VT != MVT::i32 && VT != MVT::i64)
3661 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3662 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3682 for (
int I = 0;
I < 4; ++
I) {
3685 unsigned ImmR, ImmS;
3686 bool BiggerPattern =
I / 2;
3687 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3689 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3695 NumberOfIgnoredLowBits, BiggerPattern)) {
3698 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3699 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3704 Width = ImmS - ImmR + 1;
3715 Src, DstLSB, Width)) {
3723 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3733 APInt BitsToBeInserted =
3736 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3760 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3793 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3795 if (Src->hasOneUse() &&
3798 Src = Src->getOperand(0);
3808 unsigned ImmS = Width - 1;
3814 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3822bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3831 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3844bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3848 EVT VT =
N->getValueType(0);
3849 if (VT != MVT::i32 && VT != MVT::i64)
3855 Op0, DstLSB, Width))
3861 unsigned ImmS = Width - 1;
3864 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
3865 CurDAG->getTargetConstant(ImmS,
DL, VT)};
3866 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3867 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3873bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3874 EVT VT =
N->getValueType(0);
3877 switch (
N->getOpcode()) {
3879 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
3882 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
3885 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
3888 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
3896 if (VT == MVT::i32) {
3899 }
else if (VT == MVT::i64) {
3905 SDValue ShiftAmt =
N->getOperand(1);
3925 (Add0Imm %
Size == 0)) {
3931 if (SubVT == MVT::i32) {
3932 NegOpc = AArch64::SUBWrr;
3933 ZeroReg = AArch64::WZR;
3935 assert(SubVT == MVT::i64);
3936 NegOpc = AArch64::SUBXrr;
3937 ZeroReg = AArch64::XZR;
3940 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3941 MachineSDNode *Neg =
3942 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
3943 NewShiftAmt =
SDValue(Neg, 0);
3951 if (SubVT == MVT::i32) {
3952 NotOpc = AArch64::ORNWrr;
3953 ZeroReg = AArch64::WZR;
3955 assert(SubVT == MVT::i64);
3956 NotOpc = AArch64::ORNXrr;
3957 ZeroReg = AArch64::XZR;
3960 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
3961 MachineSDNode *
Not =
3962 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
3963 NewShiftAmt =
SDValue(Not, 0);
3984 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
3985 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
3986 MachineSDNode *Ext = CurDAG->getMachineNode(
3987 AArch64::SUBREG_TO_REG,
DL, VT,
3988 CurDAG->getTargetConstant(0,
DL, MVT::i64), NewShiftAmt,
SubReg);
3989 NewShiftAmt =
SDValue(Ext, 0);
3993 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4000 bool isReciprocal) {
4003 FVal = CN->getValueAPF();
4006 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4035 if (!IsExact || !IntVal.isPowerOf2())
4037 unsigned FBits = IntVal.logBase2();
4041 if (FBits == 0 || FBits > RegWidth)
return false;
4047bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4048 unsigned RegWidth) {
4053bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4055 unsigned RegWidth) {
4065 RegString.
split(Fields,
':');
4067 if (Fields.
size() == 1)
4071 &&
"Invalid number of fields in read register string");
4074 bool AllIntFields =
true;
4078 AllIntFields &= !
Field.getAsInteger(10, IntField);
4079 Ops.push_back(IntField);
4083 "Unexpected non-integer value in special register string.");
4088 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) |
4089 (
Ops[3] << 3) | (
Ops[4]);
4096bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4098 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4101 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4103 unsigned Opcode64Bit = AArch64::MRS;
4108 const auto *TheReg =
4109 AArch64SysReg::lookupSysRegByName(RegString->getString());
4110 if (TheReg && TheReg->Readable &&
4111 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4112 Imm = TheReg->Encoding;
4118 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4119 Opcode64Bit = AArch64::ADR;
4127 SDValue InChain =
N->getOperand(0);
4128 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4129 if (!ReadIs128Bit) {
4130 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4131 {SysRegImm, InChain});
4133 SDNode *MRRS = CurDAG->getMachineNode(
4135 {MVT::Untyped , MVT::Other },
4136 {SysRegImm, InChain});
4140 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4142 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4148 ReplaceUses(
SDValue(
N, 2), OutChain);
4157bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4159 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4162 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4164 if (!WriteIs128Bit) {
4170 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4173 "Expected a constant integer expression.");
4174 unsigned Reg = PMapper->Encoding;
4175 uint64_t Immed =
N->getConstantOperandVal(2);
4176 CurDAG->SelectNodeTo(
4177 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4178 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4184 if (trySelectPState(
4185 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4186 AArch64::MSRpstateImm4))
4188 if (trySelectPState(
4189 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4190 AArch64::MSRpstateImm1))
4199 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4200 if (TheReg && TheReg->Writeable &&
4201 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4202 Imm = TheReg->Encoding;
4211 if (!WriteIs128Bit) {
4212 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4213 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4214 N->getOperand(2), InChain);
4218 SDNode *Pair = CurDAG->getMachineNode(
4219 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4220 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4223 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4225 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4227 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4228 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4236bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4241 if (Subtarget->hasLSE())
return false;
4243 if (MemTy == MVT::i8)
4244 Opcode = AArch64::CMP_SWAP_8;
4245 else if (MemTy == MVT::i16)
4246 Opcode = AArch64::CMP_SWAP_16;
4247 else if (MemTy == MVT::i32)
4248 Opcode = AArch64::CMP_SWAP_32;
4249 else if (MemTy == MVT::i64)
4250 Opcode = AArch64::CMP_SWAP_64;
4254 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4255 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4257 SDNode *CmpSwap = CurDAG->getMachineNode(
4259 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4266 CurDAG->RemoveDeadNode(
N);
4271bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4272 SDValue &Shift,
bool Negate) {
4286 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4293 if ((Val & ~0xff) == 0) {
4294 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4299 if ((Val & ~0xff00) == 0) {
4300 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4312bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4336 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4337 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4344 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4345 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4349 if (Val <= 65280 && Val % 256 == 0) {
4350 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4351 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4362bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4372 int32_t ImmVal, ShiftVal;
4377 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4378 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4382bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4384 int64_t ImmVal = CNode->getSExtValue();
4386 if (ImmVal >= -128 && ImmVal < 128) {
4387 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4394bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4396 uint64_t ImmVal = CNode->getZExtValue();
4406 ImmVal &= 0xFFFFFFFF;
4415 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4422bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4426 ImmVal = CI->getZExtValue();
4428 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4439 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4448bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4449 uint64_t
High,
bool AllowSaturation,
4452 uint64_t ImmVal = CN->getZExtValue();
4459 if (ImmVal >
High) {
4460 if (!AllowSaturation)
4465 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4472bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4486 const TargetLowering *TLI = getTargetLowering();
4489 SDValue FiOp = CurDAG->getTargetFrameIndex(
4491 int TagOffset =
N->getConstantOperandVal(3);
4493 SDNode *Out = CurDAG->getMachineNode(
4494 AArch64::TAGPstack,
DL, MVT::i64,
4495 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4496 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4497 ReplaceNode(
N, Out);
4501void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4503 "llvm.aarch64.tagp third argument must be an immediate");
4504 if (trySelectStackSlotTagP(
N))
4511 int TagOffset =
N->getConstantOperandVal(3);
4512 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4513 {
N->getOperand(1),
N->getOperand(2)});
4514 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4515 {
SDValue(N1, 0),
N->getOperand(2)});
4516 SDNode *N3 = CurDAG->getMachineNode(
4517 AArch64::ADDG,
DL, MVT::i64,
4518 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4519 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4523bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4527 if (
N->getConstantOperandVal(2) != 0)
4529 if (!
N->getOperand(0).isUndef())
4533 EVT VT =
N->getValueType(0);
4534 EVT InVT =
N->getOperand(1).getValueType();
4545 "Expected to insert into a packed scalable vector!");
4548 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4549 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4550 N->getOperand(1), RC));
4554bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4558 if (
N->getConstantOperandVal(1) != 0)
4562 EVT VT =
N->getValueType(0);
4563 EVT InVT =
N->getOperand(0).getValueType();
4574 "Expected to extract from a packed scalable vector!");
4577 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4578 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4579 N->getOperand(0), RC));
4583bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4589 EVT VT =
N->getValueType(0);
4602 (Subtarget->hasSVE2() ||
4603 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4604 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4607 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4611 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4612 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4613 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4620 bool IsXOROperand =
true;
4622 IsXOROperand =
false;
4628 APInt ShlAmt, ShrAmt;
4636 if (!IsXOROperand) {
4638 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4641 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4642 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4643 VT, Zero, MOVIV, ZSub);
4654 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4655 AArch64::XAR_ZZZI_D})) {
4656 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4681 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4691 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4699 bool IsXOROperand =
true;
4701 IsXOROperand =
false;
4704 R1 =
XOR.getOperand(0);
4705 R2 =
XOR.getOperand(1);
4715 if (ShAmt + HsAmt != VTSizeInBits)
4718 if (!IsXOROperand) {
4721 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4730 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4736 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4737 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4739 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4742 if (
R2.getValueType() == VT)
4743 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4751 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4756 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4762 SDNode *XAR =
nullptr;
4766 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4767 AArch64::XAR_ZZZI_D}))
4768 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4770 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4773 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4779 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4780 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4783 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4784 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4790 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4794 ReplaceNode(
N, XAR);
4798void AArch64DAGToDAGISel::Select(SDNode *Node) {
4800 if (
Node->isMachineOpcode()) {
4802 Node->setNodeId(-1);
4807 EVT VT =
Node->getValueType(0);
4809 switch (
Node->getOpcode()) {
4814 if (SelectCMP_SWAP(Node))
4819 case AArch64ISD::MRRS:
4820 if (tryReadRegister(Node))
4825 case AArch64ISD::MSRR:
4826 if (tryWriteRegister(Node))
4833 if (tryIndexedLoad(Node))
4842 if (tryBitfieldExtractOp(Node))
4844 if (tryBitfieldInsertInZeroOp(Node))
4849 if (tryShiftAmountMod(Node))
4854 if (tryBitfieldExtractOpFromSExt(Node))
4859 if (tryBitfieldInsertOp(Node))
4861 if (trySelectXAR(Node))
4866 if (trySelectCastScalableToFixedLengthVector(Node))
4872 if (trySelectCastFixedLengthToScalableVector(Node))
4881 if (ConstNode->
isZero()) {
4882 if (VT == MVT::i32) {
4884 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4885 ReplaceNode(Node,
New.getNode());
4887 }
else if (VT == MVT::i64) {
4889 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4890 ReplaceNode(Node,
New.getNode());
4901 const TargetLowering *TLI = getTargetLowering();
4902 SDValue TFI = CurDAG->getTargetFrameIndex(
4905 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4906 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4907 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4911 unsigned IntNo =
Node->getConstantOperandVal(1);
4915 case Intrinsic::aarch64_gcsss: {
4919 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4921 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4922 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4923 MVT::Other, Zero,
SDValue(SS1, 0));
4924 ReplaceNode(Node, SS2);
4927 case Intrinsic::aarch64_ldaxp:
4928 case Intrinsic::aarch64_ldxp: {
4930 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4935 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4936 MVT::Other, MemAddr, Chain);
4939 MachineMemOperand *MemOp =
4942 ReplaceNode(Node, Ld);
4945 case Intrinsic::aarch64_stlxp:
4946 case Intrinsic::aarch64_stxp: {
4948 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4956 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4958 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4960 MachineMemOperand *MemOp =
4964 ReplaceNode(Node, St);
4967 case Intrinsic::aarch64_neon_ld1x2:
4968 if (VT == MVT::v8i8) {
4969 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4971 }
else if (VT == MVT::v16i8) {
4972 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4974 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4975 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
4977 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
4978 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
4980 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
4981 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
4983 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
4984 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
4986 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
4987 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
4989 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
4990 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
4994 case Intrinsic::aarch64_neon_ld1x3:
4995 if (VT == MVT::v8i8) {
4996 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
4998 }
else if (VT == MVT::v16i8) {
4999 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5001 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5002 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5004 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5005 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5007 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5008 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5010 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5011 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5013 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5014 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5016 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5017 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5021 case Intrinsic::aarch64_neon_ld1x4:
5022 if (VT == MVT::v8i8) {
5023 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5025 }
else if (VT == MVT::v16i8) {
5026 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5028 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5029 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5031 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5032 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5034 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5035 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5037 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5038 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5040 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5041 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5043 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5044 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5048 case Intrinsic::aarch64_neon_ld2:
5049 if (VT == MVT::v8i8) {
5050 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5052 }
else if (VT == MVT::v16i8) {
5053 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5055 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5056 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5058 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5059 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5061 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5062 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5064 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5065 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5067 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5068 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5070 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5071 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5075 case Intrinsic::aarch64_neon_ld3:
5076 if (VT == MVT::v8i8) {
5077 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5079 }
else if (VT == MVT::v16i8) {
5080 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5082 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5083 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5085 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5086 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5088 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5089 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5091 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5092 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5094 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5095 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5097 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5098 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5102 case Intrinsic::aarch64_neon_ld4:
5103 if (VT == MVT::v8i8) {
5104 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5106 }
else if (VT == MVT::v16i8) {
5107 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5109 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5110 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5112 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5113 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5115 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5116 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5118 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5119 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5121 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5122 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5124 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5125 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5129 case Intrinsic::aarch64_neon_ld2r:
5130 if (VT == MVT::v8i8) {
5131 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5133 }
else if (VT == MVT::v16i8) {
5134 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5136 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5137 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5139 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5140 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5142 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5143 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5145 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5146 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5148 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5149 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5151 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5152 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5156 case Intrinsic::aarch64_neon_ld3r:
5157 if (VT == MVT::v8i8) {
5158 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5160 }
else if (VT == MVT::v16i8) {
5161 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5163 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5164 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5166 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5167 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5169 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5170 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5172 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5173 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5175 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5176 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5178 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5179 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5183 case Intrinsic::aarch64_neon_ld4r:
5184 if (VT == MVT::v8i8) {
5185 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5187 }
else if (VT == MVT::v16i8) {
5188 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5190 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5191 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5193 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5194 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5196 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5197 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5199 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5200 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5202 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5203 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5205 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5206 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5210 case Intrinsic::aarch64_neon_ld2lane:
5211 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5212 SelectLoadLane(Node, 2, AArch64::LD2i8);
5214 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5215 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5216 SelectLoadLane(Node, 2, AArch64::LD2i16);
5218 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5220 SelectLoadLane(Node, 2, AArch64::LD2i32);
5222 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5224 SelectLoadLane(Node, 2, AArch64::LD2i64);
5228 case Intrinsic::aarch64_neon_ld3lane:
5229 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5230 SelectLoadLane(Node, 3, AArch64::LD3i8);
5232 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5233 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5234 SelectLoadLane(Node, 3, AArch64::LD3i16);
5236 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5238 SelectLoadLane(Node, 3, AArch64::LD3i32);
5240 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5242 SelectLoadLane(Node, 3, AArch64::LD3i64);
5246 case Intrinsic::aarch64_neon_ld4lane:
5247 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5248 SelectLoadLane(Node, 4, AArch64::LD4i8);
5250 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5251 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5252 SelectLoadLane(Node, 4, AArch64::LD4i16);
5254 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5256 SelectLoadLane(Node, 4, AArch64::LD4i32);
5258 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5260 SelectLoadLane(Node, 4, AArch64::LD4i64);
5264 case Intrinsic::aarch64_ld64b:
5265 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5267 case Intrinsic::aarch64_sve_ld2q_sret: {
5268 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5271 case Intrinsic::aarch64_sve_ld3q_sret: {
5272 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5275 case Intrinsic::aarch64_sve_ld4q_sret: {
5276 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5279 case Intrinsic::aarch64_sve_ld2_sret: {
5280 if (VT == MVT::nxv16i8) {
5281 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5284 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5285 VT == MVT::nxv8bf16) {
5286 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5289 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5290 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5293 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5294 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5300 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5301 if (VT == MVT::nxv16i8) {
5302 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5303 SelectContiguousMultiVectorLoad(
5304 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5305 else if (Subtarget->hasSVE2p1())
5306 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5311 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5312 VT == MVT::nxv8bf16) {
5313 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5314 SelectContiguousMultiVectorLoad(
5315 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5316 else if (Subtarget->hasSVE2p1())
5317 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5322 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5323 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5324 SelectContiguousMultiVectorLoad(
5325 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5326 else if (Subtarget->hasSVE2p1())
5327 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5332 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5333 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5334 SelectContiguousMultiVectorLoad(
5335 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5336 else if (Subtarget->hasSVE2p1())
5337 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5345 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5346 if (VT == MVT::nxv16i8) {
5347 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5348 SelectContiguousMultiVectorLoad(
5349 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5350 else if (Subtarget->hasSVE2p1())
5351 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5356 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5357 VT == MVT::nxv8bf16) {
5358 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5359 SelectContiguousMultiVectorLoad(
5360 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5361 else if (Subtarget->hasSVE2p1())
5362 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5367 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5368 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5369 SelectContiguousMultiVectorLoad(
5370 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5371 else if (Subtarget->hasSVE2p1())
5372 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5377 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5378 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5379 SelectContiguousMultiVectorLoad(
5380 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5381 else if (Subtarget->hasSVE2p1())
5382 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5390 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5391 if (VT == MVT::nxv16i8) {
5392 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5393 SelectContiguousMultiVectorLoad(Node, 2, 0,
5394 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5395 AArch64::LDNT1B_2Z_PSEUDO);
5396 else if (Subtarget->hasSVE2p1())
5397 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5398 AArch64::LDNT1B_2Z);
5402 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5403 VT == MVT::nxv8bf16) {
5404 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5405 SelectContiguousMultiVectorLoad(Node, 2, 1,
5406 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5407 AArch64::LDNT1H_2Z_PSEUDO);
5408 else if (Subtarget->hasSVE2p1())
5409 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5410 AArch64::LDNT1H_2Z);
5414 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5415 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5416 SelectContiguousMultiVectorLoad(Node, 2, 2,
5417 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5418 AArch64::LDNT1W_2Z_PSEUDO);
5419 else if (Subtarget->hasSVE2p1())
5420 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5421 AArch64::LDNT1W_2Z);
5425 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5426 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5427 SelectContiguousMultiVectorLoad(Node, 2, 3,
5428 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5429 AArch64::LDNT1D_2Z_PSEUDO);
5430 else if (Subtarget->hasSVE2p1())
5431 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5432 AArch64::LDNT1D_2Z);
5439 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5440 if (VT == MVT::nxv16i8) {
5441 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5442 SelectContiguousMultiVectorLoad(Node, 4, 0,
5443 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5444 AArch64::LDNT1B_4Z_PSEUDO);
5445 else if (Subtarget->hasSVE2p1())
5446 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5447 AArch64::LDNT1B_4Z);
5451 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5452 VT == MVT::nxv8bf16) {
5453 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5454 SelectContiguousMultiVectorLoad(Node, 4, 1,
5455 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5456 AArch64::LDNT1H_4Z_PSEUDO);
5457 else if (Subtarget->hasSVE2p1())
5458 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5459 AArch64::LDNT1H_4Z);
5463 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5464 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5465 SelectContiguousMultiVectorLoad(Node, 4, 2,
5466 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5467 AArch64::LDNT1W_4Z_PSEUDO);
5468 else if (Subtarget->hasSVE2p1())
5469 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5470 AArch64::LDNT1W_4Z);
5474 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5475 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5476 SelectContiguousMultiVectorLoad(Node, 4, 3,
5477 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5478 AArch64::LDNT1D_4Z_PSEUDO);
5479 else if (Subtarget->hasSVE2p1())
5480 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5481 AArch64::LDNT1D_4Z);
5488 case Intrinsic::aarch64_sve_ld3_sret: {
5489 if (VT == MVT::nxv16i8) {
5490 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5493 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5494 VT == MVT::nxv8bf16) {
5495 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5498 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5499 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5502 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5503 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5509 case Intrinsic::aarch64_sve_ld4_sret: {
5510 if (VT == MVT::nxv16i8) {
5511 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5514 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5515 VT == MVT::nxv8bf16) {
5516 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5519 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5520 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5523 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5524 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5530 case Intrinsic::aarch64_sme_read_hor_vg2: {
5531 if (VT == MVT::nxv16i8) {
5532 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5533 AArch64::MOVA_2ZMXI_H_B);
5535 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5536 VT == MVT::nxv8bf16) {
5537 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5538 AArch64::MOVA_2ZMXI_H_H);
5540 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5541 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5542 AArch64::MOVA_2ZMXI_H_S);
5544 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5545 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5546 AArch64::MOVA_2ZMXI_H_D);
5551 case Intrinsic::aarch64_sme_read_ver_vg2: {
5552 if (VT == MVT::nxv16i8) {
5553 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5554 AArch64::MOVA_2ZMXI_V_B);
5556 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5557 VT == MVT::nxv8bf16) {
5558 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5559 AArch64::MOVA_2ZMXI_V_H);
5561 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5562 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5563 AArch64::MOVA_2ZMXI_V_S);
5565 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5566 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5567 AArch64::MOVA_2ZMXI_V_D);
5572 case Intrinsic::aarch64_sme_read_hor_vg4: {
5573 if (VT == MVT::nxv16i8) {
5574 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5575 AArch64::MOVA_4ZMXI_H_B);
5577 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5578 VT == MVT::nxv8bf16) {
5579 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5580 AArch64::MOVA_4ZMXI_H_H);
5582 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5583 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5584 AArch64::MOVA_4ZMXI_H_S);
5586 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5587 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5588 AArch64::MOVA_4ZMXI_H_D);
5593 case Intrinsic::aarch64_sme_read_ver_vg4: {
5594 if (VT == MVT::nxv16i8) {
5595 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5596 AArch64::MOVA_4ZMXI_V_B);
5598 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5599 VT == MVT::nxv8bf16) {
5600 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5601 AArch64::MOVA_4ZMXI_V_H);
5603 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5604 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5605 AArch64::MOVA_4ZMXI_V_S);
5607 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5608 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5609 AArch64::MOVA_4ZMXI_V_D);
5614 case Intrinsic::aarch64_sme_read_vg1x2: {
5615 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5616 AArch64::MOVA_VG2_2ZMXI);
5619 case Intrinsic::aarch64_sme_read_vg1x4: {
5620 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5621 AArch64::MOVA_VG4_4ZMXI);
5624 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5625 if (VT == MVT::nxv16i8) {
5626 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5628 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5629 VT == MVT::nxv8bf16) {
5630 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5632 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5633 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5635 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5636 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5641 case Intrinsic::aarch64_sme_readz_vert_x2: {
5642 if (VT == MVT::nxv16i8) {
5643 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5645 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5646 VT == MVT::nxv8bf16) {
5647 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5649 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5650 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5652 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5653 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5658 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5659 if (VT == MVT::nxv16i8) {
5660 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5662 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5663 VT == MVT::nxv8bf16) {
5664 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5666 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5667 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5669 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5670 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5675 case Intrinsic::aarch64_sme_readz_vert_x4: {
5676 if (VT == MVT::nxv16i8) {
5677 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5679 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5680 VT == MVT::nxv8bf16) {
5681 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5683 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5684 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5686 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5687 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5692 case Intrinsic::aarch64_sme_readz_x2: {
5693 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5697 case Intrinsic::aarch64_sme_readz_x4: {
5698 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5702 case Intrinsic::swift_async_context_addr: {
5705 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5707 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5708 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5709 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5711 ReplaceUses(
SDValue(Node, 0), Res);
5713 CurDAG->RemoveDeadNode(Node);
5715 auto &MF = CurDAG->getMachineFunction();
5716 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5717 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5720 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5722 Node->getValueType(0),
5723 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5724 AArch64::LUTI2_4ZTZI_S}))
5726 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5729 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5731 Node->getValueType(0),
5732 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5734 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5737 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5739 Node->getValueType(0),
5740 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5741 AArch64::LUTI2_2ZTZI_S}))
5743 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5746 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5748 Node->getValueType(0),
5749 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5750 AArch64::LUTI4_2ZTZI_S}))
5752 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5755 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5756 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5759 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5761 Node->getValueType(0),
5762 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5763 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5765 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5767 Node->getValueType(0),
5768 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5769 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5771 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5773 Node->getValueType(0),
5774 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5775 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5777 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5779 Node->getValueType(0),
5780 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5781 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5786 unsigned IntNo =
Node->getConstantOperandVal(0);
5790 case Intrinsic::aarch64_tagp:
5794 case Intrinsic::ptrauth_auth:
5795 SelectPtrauthAuth(Node);
5798 case Intrinsic::ptrauth_resign:
5799 SelectPtrauthResign(Node);
5802 case Intrinsic::aarch64_neon_tbl2:
5803 SelectTable(Node, 2,
5804 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5807 case Intrinsic::aarch64_neon_tbl3:
5808 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5809 : AArch64::TBLv16i8Three,
5812 case Intrinsic::aarch64_neon_tbl4:
5813 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5814 : AArch64::TBLv16i8Four,
5817 case Intrinsic::aarch64_neon_tbx2:
5818 SelectTable(Node, 2,
5819 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5822 case Intrinsic::aarch64_neon_tbx3:
5823 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5824 : AArch64::TBXv16i8Three,
5827 case Intrinsic::aarch64_neon_tbx4:
5828 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5829 : AArch64::TBXv16i8Four,
5832 case Intrinsic::aarch64_sve_srshl_single_x2:
5834 Node->getValueType(0),
5835 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5836 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5837 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5839 case Intrinsic::aarch64_sve_srshl_single_x4:
5841 Node->getValueType(0),
5842 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5843 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5844 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5846 case Intrinsic::aarch64_sve_urshl_single_x2:
5848 Node->getValueType(0),
5849 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5850 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5851 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5853 case Intrinsic::aarch64_sve_urshl_single_x4:
5855 Node->getValueType(0),
5856 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5857 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5858 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5860 case Intrinsic::aarch64_sve_srshl_x2:
5862 Node->getValueType(0),
5863 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5864 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5865 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5867 case Intrinsic::aarch64_sve_srshl_x4:
5869 Node->getValueType(0),
5870 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5871 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5872 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5874 case Intrinsic::aarch64_sve_urshl_x2:
5876 Node->getValueType(0),
5877 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5878 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5879 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5881 case Intrinsic::aarch64_sve_urshl_x4:
5883 Node->getValueType(0),
5884 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5885 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5886 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5888 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5890 Node->getValueType(0),
5891 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5892 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5893 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5895 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5897 Node->getValueType(0),
5898 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5899 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5900 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5902 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5904 Node->getValueType(0),
5905 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5906 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5907 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5909 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5911 Node->getValueType(0),
5912 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5913 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5914 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5916 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5918 Node->getValueType(0),
5919 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5920 AArch64::FSCALE_2ZZ_D}))
5921 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5923 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5925 Node->getValueType(0),
5926 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5927 AArch64::FSCALE_4ZZ_D}))
5928 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5930 case Intrinsic::aarch64_sme_fp8_scale_x2:
5932 Node->getValueType(0),
5933 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5934 AArch64::FSCALE_2Z2Z_D}))
5935 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5937 case Intrinsic::aarch64_sme_fp8_scale_x4:
5939 Node->getValueType(0),
5940 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5941 AArch64::FSCALE_4Z4Z_D}))
5942 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5944 case Intrinsic::aarch64_sve_whilege_x2:
5946 Node->getValueType(0),
5947 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5948 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5949 SelectWhilePair(Node,
Op);
5951 case Intrinsic::aarch64_sve_whilegt_x2:
5953 Node->getValueType(0),
5954 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5955 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5956 SelectWhilePair(Node,
Op);
5958 case Intrinsic::aarch64_sve_whilehi_x2:
5960 Node->getValueType(0),
5961 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5962 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5963 SelectWhilePair(Node,
Op);
5965 case Intrinsic::aarch64_sve_whilehs_x2:
5967 Node->getValueType(0),
5968 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5969 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5970 SelectWhilePair(Node,
Op);
5972 case Intrinsic::aarch64_sve_whilele_x2:
5974 Node->getValueType(0),
5975 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5976 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
5977 SelectWhilePair(Node,
Op);
5979 case Intrinsic::aarch64_sve_whilelo_x2:
5981 Node->getValueType(0),
5982 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
5983 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
5984 SelectWhilePair(Node,
Op);
5986 case Intrinsic::aarch64_sve_whilels_x2:
5988 Node->getValueType(0),
5989 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
5990 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
5991 SelectWhilePair(Node,
Op);
5993 case Intrinsic::aarch64_sve_whilelt_x2:
5995 Node->getValueType(0),
5996 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
5997 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
5998 SelectWhilePair(Node,
Op);
6000 case Intrinsic::aarch64_sve_smax_single_x2:
6002 Node->getValueType(0),
6003 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6004 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6005 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6007 case Intrinsic::aarch64_sve_umax_single_x2:
6009 Node->getValueType(0),
6010 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6011 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6012 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6014 case Intrinsic::aarch64_sve_fmax_single_x2:
6016 Node->getValueType(0),
6017 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6018 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6019 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6021 case Intrinsic::aarch64_sve_smax_single_x4:
6023 Node->getValueType(0),
6024 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6025 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6026 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6028 case Intrinsic::aarch64_sve_umax_single_x4:
6030 Node->getValueType(0),
6031 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6032 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6033 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6035 case Intrinsic::aarch64_sve_fmax_single_x4:
6037 Node->getValueType(0),
6038 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6039 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6040 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6042 case Intrinsic::aarch64_sve_smin_single_x2:
6044 Node->getValueType(0),
6045 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6046 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6047 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6049 case Intrinsic::aarch64_sve_umin_single_x2:
6051 Node->getValueType(0),
6052 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6053 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6054 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6056 case Intrinsic::aarch64_sve_fmin_single_x2:
6058 Node->getValueType(0),
6059 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6060 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6061 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6063 case Intrinsic::aarch64_sve_smin_single_x4:
6065 Node->getValueType(0),
6066 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6067 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6068 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6070 case Intrinsic::aarch64_sve_umin_single_x4:
6072 Node->getValueType(0),
6073 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6074 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6075 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6077 case Intrinsic::aarch64_sve_fmin_single_x4:
6079 Node->getValueType(0),
6080 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6081 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6082 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6084 case Intrinsic::aarch64_sve_smax_x2:
6086 Node->getValueType(0),
6087 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6088 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6089 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6091 case Intrinsic::aarch64_sve_umax_x2:
6093 Node->getValueType(0),
6094 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6095 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6096 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6098 case Intrinsic::aarch64_sve_fmax_x2:
6100 Node->getValueType(0),
6101 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6102 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6103 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6105 case Intrinsic::aarch64_sve_smax_x4:
6107 Node->getValueType(0),
6108 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6109 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6110 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6112 case Intrinsic::aarch64_sve_umax_x4:
6114 Node->getValueType(0),
6115 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6116 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6117 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6119 case Intrinsic::aarch64_sve_fmax_x4:
6121 Node->getValueType(0),
6122 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6123 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6124 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6126 case Intrinsic::aarch64_sme_famax_x2:
6128 Node->getValueType(0),
6129 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6130 AArch64::FAMAX_2Z2Z_D}))
6131 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6133 case Intrinsic::aarch64_sme_famax_x4:
6135 Node->getValueType(0),
6136 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6137 AArch64::FAMAX_4Z4Z_D}))
6138 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6140 case Intrinsic::aarch64_sme_famin_x2:
6142 Node->getValueType(0),
6143 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6144 AArch64::FAMIN_2Z2Z_D}))
6145 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6147 case Intrinsic::aarch64_sme_famin_x4:
6149 Node->getValueType(0),
6150 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6151 AArch64::FAMIN_4Z4Z_D}))
6152 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6154 case Intrinsic::aarch64_sve_smin_x2:
6156 Node->getValueType(0),
6157 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6158 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6159 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6161 case Intrinsic::aarch64_sve_umin_x2:
6163 Node->getValueType(0),
6164 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6165 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6166 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6168 case Intrinsic::aarch64_sve_fmin_x2:
6170 Node->getValueType(0),
6171 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6172 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6173 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6175 case Intrinsic::aarch64_sve_smin_x4:
6177 Node->getValueType(0),
6178 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6179 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6180 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6182 case Intrinsic::aarch64_sve_umin_x4:
6184 Node->getValueType(0),
6185 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6186 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6187 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6189 case Intrinsic::aarch64_sve_fmin_x4:
6191 Node->getValueType(0),
6192 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6193 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6194 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6196 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6198 Node->getValueType(0),
6199 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6200 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6201 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6203 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6205 Node->getValueType(0),
6206 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6207 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6208 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6210 case Intrinsic::aarch64_sve_fminnm_single_x2:
6212 Node->getValueType(0),
6213 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6214 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6215 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6217 case Intrinsic::aarch64_sve_fminnm_single_x4:
6219 Node->getValueType(0),
6220 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6221 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6222 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6224 case Intrinsic::aarch64_sve_fscale_single_x4:
6225 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6227 case Intrinsic::aarch64_sve_fscale_single_x2:
6228 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6230 case Intrinsic::aarch64_sve_fmul_single_x4:
6232 Node->getValueType(0),
6233 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6234 AArch64::FMUL_4ZZ_D}))
6235 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6237 case Intrinsic::aarch64_sve_fmul_single_x2:
6239 Node->getValueType(0),
6240 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6241 AArch64::FMUL_2ZZ_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6244 case Intrinsic::aarch64_sve_fmaxnm_x2:
6246 Node->getValueType(0),
6247 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6248 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6251 case Intrinsic::aarch64_sve_fmaxnm_x4:
6253 Node->getValueType(0),
6254 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6255 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6256 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6258 case Intrinsic::aarch64_sve_fminnm_x2:
6260 Node->getValueType(0),
6261 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6262 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6263 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6265 case Intrinsic::aarch64_sve_fminnm_x4:
6267 Node->getValueType(0),
6268 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6269 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6270 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6272 case Intrinsic::aarch64_sve_fscale_x4:
6273 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6275 case Intrinsic::aarch64_sve_fscale_x2:
6276 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6278 case Intrinsic::aarch64_sve_fmul_x4:
6280 Node->getValueType(0),
6281 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6282 AArch64::FMUL_4Z4Z_D}))
6283 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6285 case Intrinsic::aarch64_sve_fmul_x2:
6287 Node->getValueType(0),
6288 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6289 AArch64::FMUL_2Z2Z_D}))
6290 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6292 case Intrinsic::aarch64_sve_fcvtzs_x2:
6293 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6295 case Intrinsic::aarch64_sve_scvtf_x2:
6296 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6298 case Intrinsic::aarch64_sve_fcvtzu_x2:
6299 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6301 case Intrinsic::aarch64_sve_ucvtf_x2:
6302 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6304 case Intrinsic::aarch64_sve_fcvtzs_x4:
6305 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6307 case Intrinsic::aarch64_sve_scvtf_x4:
6308 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6310 case Intrinsic::aarch64_sve_fcvtzu_x4:
6311 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6313 case Intrinsic::aarch64_sve_ucvtf_x4:
6314 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6316 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6317 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6319 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6320 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6322 case Intrinsic::aarch64_sve_sclamp_single_x2:
6324 Node->getValueType(0),
6325 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6326 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6327 SelectClamp(Node, 2,
Op);
6329 case Intrinsic::aarch64_sve_uclamp_single_x2:
6331 Node->getValueType(0),
6332 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6333 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6334 SelectClamp(Node, 2,
Op);
6336 case Intrinsic::aarch64_sve_fclamp_single_x2:
6338 Node->getValueType(0),
6339 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6340 AArch64::FCLAMP_VG2_2Z2Z_D}))
6341 SelectClamp(Node, 2,
Op);
6343 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6344 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6346 case Intrinsic::aarch64_sve_sclamp_single_x4:
6348 Node->getValueType(0),
6349 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6350 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6351 SelectClamp(Node, 4,
Op);
6353 case Intrinsic::aarch64_sve_uclamp_single_x4:
6355 Node->getValueType(0),
6356 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6357 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6358 SelectClamp(Node, 4,
Op);
6360 case Intrinsic::aarch64_sve_fclamp_single_x4:
6362 Node->getValueType(0),
6363 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6364 AArch64::FCLAMP_VG4_4Z4Z_D}))
6365 SelectClamp(Node, 4,
Op);
6367 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6368 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6370 case Intrinsic::aarch64_sve_add_single_x2:
6372 Node->getValueType(0),
6373 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6374 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6375 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6377 case Intrinsic::aarch64_sve_add_single_x4:
6379 Node->getValueType(0),
6380 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6381 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6382 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6384 case Intrinsic::aarch64_sve_zip_x2:
6386 Node->getValueType(0),
6387 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6388 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6389 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6391 case Intrinsic::aarch64_sve_zipq_x2:
6392 SelectUnaryMultiIntrinsic(Node, 2,
false,
6393 AArch64::ZIP_VG2_2ZZZ_Q);
6395 case Intrinsic::aarch64_sve_zip_x4:
6397 Node->getValueType(0),
6398 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6399 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6400 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6402 case Intrinsic::aarch64_sve_zipq_x4:
6403 SelectUnaryMultiIntrinsic(Node, 4,
true,
6404 AArch64::ZIP_VG4_4Z4Z_Q);
6406 case Intrinsic::aarch64_sve_uzp_x2:
6408 Node->getValueType(0),
6409 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6410 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6411 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6413 case Intrinsic::aarch64_sve_uzpq_x2:
6414 SelectUnaryMultiIntrinsic(Node, 2,
false,
6415 AArch64::UZP_VG2_2ZZZ_Q);
6417 case Intrinsic::aarch64_sve_uzp_x4:
6419 Node->getValueType(0),
6420 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6421 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6422 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6424 case Intrinsic::aarch64_sve_uzpq_x4:
6425 SelectUnaryMultiIntrinsic(Node, 4,
true,
6426 AArch64::UZP_VG4_4Z4Z_Q);
6428 case Intrinsic::aarch64_sve_sel_x2:
6430 Node->getValueType(0),
6431 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6432 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6433 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6435 case Intrinsic::aarch64_sve_sel_x4:
6437 Node->getValueType(0),
6438 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6439 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6440 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6442 case Intrinsic::aarch64_sve_frinta_x2:
6443 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6445 case Intrinsic::aarch64_sve_frinta_x4:
6446 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6448 case Intrinsic::aarch64_sve_frintm_x2:
6449 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6451 case Intrinsic::aarch64_sve_frintm_x4:
6452 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6454 case Intrinsic::aarch64_sve_frintn_x2:
6455 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6457 case Intrinsic::aarch64_sve_frintn_x4:
6458 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6460 case Intrinsic::aarch64_sve_frintp_x2:
6461 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6463 case Intrinsic::aarch64_sve_frintp_x4:
6464 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6466 case Intrinsic::aarch64_sve_sunpk_x2:
6468 Node->getValueType(0),
6469 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6470 AArch64::SUNPK_VG2_2ZZ_D}))
6471 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6473 case Intrinsic::aarch64_sve_uunpk_x2:
6475 Node->getValueType(0),
6476 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6477 AArch64::UUNPK_VG2_2ZZ_D}))
6478 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6480 case Intrinsic::aarch64_sve_sunpk_x4:
6482 Node->getValueType(0),
6483 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6484 AArch64::SUNPK_VG4_4Z2Z_D}))
6485 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6487 case Intrinsic::aarch64_sve_uunpk_x4:
6489 Node->getValueType(0),
6490 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6491 AArch64::UUNPK_VG4_4Z2Z_D}))
6492 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6494 case Intrinsic::aarch64_sve_pext_x2: {
6496 Node->getValueType(0),
6497 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6498 AArch64::PEXT_2PCI_D}))
6499 SelectPExtPair(Node,
Op);
6506 unsigned IntNo =
Node->getConstantOperandVal(1);
6507 if (
Node->getNumOperands() >= 3)
6508 VT =
Node->getOperand(2)->getValueType(0);
6512 case Intrinsic::aarch64_neon_st1x2: {
6513 if (VT == MVT::v8i8) {
6514 SelectStore(Node, 2, AArch64::ST1Twov8b);
6516 }
else if (VT == MVT::v16i8) {
6517 SelectStore(Node, 2, AArch64::ST1Twov16b);
6519 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6520 VT == MVT::v4bf16) {
6521 SelectStore(Node, 2, AArch64::ST1Twov4h);
6523 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6524 VT == MVT::v8bf16) {
6525 SelectStore(Node, 2, AArch64::ST1Twov8h);
6527 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6528 SelectStore(Node, 2, AArch64::ST1Twov2s);
6530 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6531 SelectStore(Node, 2, AArch64::ST1Twov4s);
6533 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6534 SelectStore(Node, 2, AArch64::ST1Twov2d);
6536 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6537 SelectStore(Node, 2, AArch64::ST1Twov1d);
6542 case Intrinsic::aarch64_neon_st1x3: {
6543 if (VT == MVT::v8i8) {
6544 SelectStore(Node, 3, AArch64::ST1Threev8b);
6546 }
else if (VT == MVT::v16i8) {
6547 SelectStore(Node, 3, AArch64::ST1Threev16b);
6549 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6550 VT == MVT::v4bf16) {
6551 SelectStore(Node, 3, AArch64::ST1Threev4h);
6553 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6554 VT == MVT::v8bf16) {
6555 SelectStore(Node, 3, AArch64::ST1Threev8h);
6557 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6558 SelectStore(Node, 3, AArch64::ST1Threev2s);
6560 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6561 SelectStore(Node, 3, AArch64::ST1Threev4s);
6563 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6564 SelectStore(Node, 3, AArch64::ST1Threev2d);
6566 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6567 SelectStore(Node, 3, AArch64::ST1Threev1d);
6572 case Intrinsic::aarch64_neon_st1x4: {
6573 if (VT == MVT::v8i8) {
6574 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6576 }
else if (VT == MVT::v16i8) {
6577 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6579 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6580 VT == MVT::v4bf16) {
6581 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6583 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6584 VT == MVT::v8bf16) {
6585 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6587 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6588 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6590 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6591 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6593 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6594 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6596 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6597 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6602 case Intrinsic::aarch64_neon_st2: {
6603 if (VT == MVT::v8i8) {
6604 SelectStore(Node, 2, AArch64::ST2Twov8b);
6606 }
else if (VT == MVT::v16i8) {
6607 SelectStore(Node, 2, AArch64::ST2Twov16b);
6609 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6610 VT == MVT::v4bf16) {
6611 SelectStore(Node, 2, AArch64::ST2Twov4h);
6613 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6614 VT == MVT::v8bf16) {
6615 SelectStore(Node, 2, AArch64::ST2Twov8h);
6617 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6618 SelectStore(Node, 2, AArch64::ST2Twov2s);
6620 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6621 SelectStore(Node, 2, AArch64::ST2Twov4s);
6623 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6624 SelectStore(Node, 2, AArch64::ST2Twov2d);
6626 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6627 SelectStore(Node, 2, AArch64::ST1Twov1d);
6632 case Intrinsic::aarch64_neon_st3: {
6633 if (VT == MVT::v8i8) {
6634 SelectStore(Node, 3, AArch64::ST3Threev8b);
6636 }
else if (VT == MVT::v16i8) {
6637 SelectStore(Node, 3, AArch64::ST3Threev16b);
6639 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6640 VT == MVT::v4bf16) {
6641 SelectStore(Node, 3, AArch64::ST3Threev4h);
6643 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6644 VT == MVT::v8bf16) {
6645 SelectStore(Node, 3, AArch64::ST3Threev8h);
6647 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6648 SelectStore(Node, 3, AArch64::ST3Threev2s);
6650 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6651 SelectStore(Node, 3, AArch64::ST3Threev4s);
6653 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6654 SelectStore(Node, 3, AArch64::ST3Threev2d);
6656 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6657 SelectStore(Node, 3, AArch64::ST1Threev1d);
6662 case Intrinsic::aarch64_neon_st4: {
6663 if (VT == MVT::v8i8) {
6664 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6666 }
else if (VT == MVT::v16i8) {
6667 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6669 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6670 VT == MVT::v4bf16) {
6671 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6673 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6674 VT == MVT::v8bf16) {
6675 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6677 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6678 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6680 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6681 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6683 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6684 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6686 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6687 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6692 case Intrinsic::aarch64_neon_st2lane: {
6693 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6694 SelectStoreLane(Node, 2, AArch64::ST2i8);
6696 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6697 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6698 SelectStoreLane(Node, 2, AArch64::ST2i16);
6700 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6702 SelectStoreLane(Node, 2, AArch64::ST2i32);
6704 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6706 SelectStoreLane(Node, 2, AArch64::ST2i64);
6711 case Intrinsic::aarch64_neon_st3lane: {
6712 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6713 SelectStoreLane(Node, 3, AArch64::ST3i8);
6715 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6716 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6717 SelectStoreLane(Node, 3, AArch64::ST3i16);
6719 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6721 SelectStoreLane(Node, 3, AArch64::ST3i32);
6723 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6725 SelectStoreLane(Node, 3, AArch64::ST3i64);
6730 case Intrinsic::aarch64_neon_st4lane: {
6731 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6732 SelectStoreLane(Node, 4, AArch64::ST4i8);
6734 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6735 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6736 SelectStoreLane(Node, 4, AArch64::ST4i16);
6738 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6740 SelectStoreLane(Node, 4, AArch64::ST4i32);
6742 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6744 SelectStoreLane(Node, 4, AArch64::ST4i64);
6749 case Intrinsic::aarch64_sve_st2q: {
6750 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6753 case Intrinsic::aarch64_sve_st3q: {
6754 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6757 case Intrinsic::aarch64_sve_st4q: {
6758 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6761 case Intrinsic::aarch64_sve_st2: {
6762 if (VT == MVT::nxv16i8) {
6763 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6765 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6766 VT == MVT::nxv8bf16) {
6767 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6769 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6770 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6772 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6773 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6778 case Intrinsic::aarch64_sve_st3: {
6779 if (VT == MVT::nxv16i8) {
6780 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6782 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6783 VT == MVT::nxv8bf16) {
6784 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6786 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6787 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6789 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6790 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6795 case Intrinsic::aarch64_sve_st4: {
6796 if (VT == MVT::nxv16i8) {
6797 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6799 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6800 VT == MVT::nxv8bf16) {
6801 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6803 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6804 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6806 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6807 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6815 case AArch64ISD::LD2post: {
6816 if (VT == MVT::v8i8) {
6817 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6819 }
else if (VT == MVT::v16i8) {
6820 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6822 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6823 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6825 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6826 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6828 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6829 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6831 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6832 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6834 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6835 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6837 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6838 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6843 case AArch64ISD::LD3post: {
6844 if (VT == MVT::v8i8) {
6845 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6847 }
else if (VT == MVT::v16i8) {
6848 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6850 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6851 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6853 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6854 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6856 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6857 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6859 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6860 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6862 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6863 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6865 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6866 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6871 case AArch64ISD::LD4post: {
6872 if (VT == MVT::v8i8) {
6873 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6875 }
else if (VT == MVT::v16i8) {
6876 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6878 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6879 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6881 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6882 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6884 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6885 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6887 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6888 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6890 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6891 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6893 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6894 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6899 case AArch64ISD::LD1x2post: {
6900 if (VT == MVT::v8i8) {
6901 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6903 }
else if (VT == MVT::v16i8) {
6904 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6906 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6907 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6909 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6910 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6912 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6913 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6915 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6916 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6918 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6919 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6921 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6922 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6927 case AArch64ISD::LD1x3post: {
6928 if (VT == MVT::v8i8) {
6929 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6931 }
else if (VT == MVT::v16i8) {
6932 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6934 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6935 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6937 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6938 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6940 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6941 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6943 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6944 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6946 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6947 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6949 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6950 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6955 case AArch64ISD::LD1x4post: {
6956 if (VT == MVT::v8i8) {
6957 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6959 }
else if (VT == MVT::v16i8) {
6960 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6962 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6963 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6965 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6966 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6968 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6969 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6971 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6972 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6974 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6975 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6977 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6978 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
6983 case AArch64ISD::LD1DUPpost: {
6984 if (VT == MVT::v8i8) {
6985 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
6987 }
else if (VT == MVT::v16i8) {
6988 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
6990 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6991 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
6993 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6994 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
6996 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6997 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
6999 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7000 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7002 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7003 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7005 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7006 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7011 case AArch64ISD::LD2DUPpost: {
7012 if (VT == MVT::v8i8) {
7013 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7015 }
else if (VT == MVT::v16i8) {
7016 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7018 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7019 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7021 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7022 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7024 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7025 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7027 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7028 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7030 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7031 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7033 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7034 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7039 case AArch64ISD::LD3DUPpost: {
7040 if (VT == MVT::v8i8) {
7041 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7043 }
else if (VT == MVT::v16i8) {
7044 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7046 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7047 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7049 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7050 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7052 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7053 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7055 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7056 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7058 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7059 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7061 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7062 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7067 case AArch64ISD::LD4DUPpost: {
7068 if (VT == MVT::v8i8) {
7069 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7071 }
else if (VT == MVT::v16i8) {
7072 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7074 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7075 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7077 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7078 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7080 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7081 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7083 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7084 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7086 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7087 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7089 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7090 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7095 case AArch64ISD::LD1LANEpost: {
7096 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7097 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7099 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7100 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7101 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7103 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7105 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7107 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7109 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7114 case AArch64ISD::LD2LANEpost: {
7115 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7116 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7118 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7119 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7120 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7122 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7124 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7126 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7128 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7133 case AArch64ISD::LD3LANEpost: {
7134 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7135 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7137 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7138 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7139 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7141 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7143 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7145 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7147 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7152 case AArch64ISD::LD4LANEpost: {
7153 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7154 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7156 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7157 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7158 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7160 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7162 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7164 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7166 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7171 case AArch64ISD::ST2post: {
7172 VT =
Node->getOperand(1).getValueType();
7173 if (VT == MVT::v8i8) {
7174 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7176 }
else if (VT == MVT::v16i8) {
7177 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7179 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7180 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7182 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7183 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7185 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7186 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7188 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7189 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7191 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7192 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7194 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7195 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7200 case AArch64ISD::ST3post: {
7201 VT =
Node->getOperand(1).getValueType();
7202 if (VT == MVT::v8i8) {
7203 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7205 }
else if (VT == MVT::v16i8) {
7206 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7208 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7209 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7211 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7212 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7214 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7215 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7217 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7218 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7220 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7221 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7223 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7224 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7229 case AArch64ISD::ST4post: {
7230 VT =
Node->getOperand(1).getValueType();
7231 if (VT == MVT::v8i8) {
7232 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7234 }
else if (VT == MVT::v16i8) {
7235 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7237 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7238 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7240 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7241 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7243 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7244 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7246 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7247 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7249 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7250 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7252 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7253 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7258 case AArch64ISD::ST1x2post: {
7259 VT =
Node->getOperand(1).getValueType();
7260 if (VT == MVT::v8i8) {
7261 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7263 }
else if (VT == MVT::v16i8) {
7264 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7266 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7267 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7269 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7270 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7272 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7273 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7275 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7276 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7278 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7279 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7281 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7282 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7287 case AArch64ISD::ST1x3post: {
7288 VT =
Node->getOperand(1).getValueType();
7289 if (VT == MVT::v8i8) {
7290 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7292 }
else if (VT == MVT::v16i8) {
7293 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7295 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7296 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7298 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7299 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7301 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7302 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7304 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7305 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7307 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7308 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7310 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7311 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7316 case AArch64ISD::ST1x4post: {
7317 VT =
Node->getOperand(1).getValueType();
7318 if (VT == MVT::v8i8) {
7319 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7321 }
else if (VT == MVT::v16i8) {
7322 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7324 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7325 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7327 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7328 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7330 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7331 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7333 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7334 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7336 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7337 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7339 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7340 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7345 case AArch64ISD::ST2LANEpost: {
7346 VT =
Node->getOperand(1).getValueType();
7347 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7348 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7350 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7351 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7352 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7354 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7356 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7358 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7360 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7365 case AArch64ISD::ST3LANEpost: {
7366 VT =
Node->getOperand(1).getValueType();
7367 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7368 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7370 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7371 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7372 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7374 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7376 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7378 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7380 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7385 case AArch64ISD::ST4LANEpost: {
7386 VT =
Node->getOperand(1).getValueType();
7387 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7388 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7390 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7391 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7392 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7394 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7396 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7398 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7400 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7415 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7427 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7431 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7432 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7447 return MemIntr->getMemoryVT();
7454 DataVT = Load->getValueType(0);
7456 DataVT = Load->getValueType(0);
7458 DataVT = Store->getValue().getValueType();
7460 DataVT = Store->getValue().getValueType();
7467 const unsigned Opcode = Root->
getOpcode();
7471 case AArch64ISD::LD1_MERGE_ZERO:
7472 case AArch64ISD::LD1S_MERGE_ZERO:
7473 case AArch64ISD::LDNF1_MERGE_ZERO:
7474 case AArch64ISD::LDNF1S_MERGE_ZERO:
7476 case AArch64ISD::ST1_PRED:
7488 case Intrinsic::aarch64_sme_ldr:
7489 case Intrinsic::aarch64_sme_str:
7490 return MVT::nxv16i8;
7491 case Intrinsic::aarch64_sve_prf:
7496 case Intrinsic::aarch64_sve_ld2_sret:
7497 case Intrinsic::aarch64_sve_ld2q_sret:
7500 case Intrinsic::aarch64_sve_st2q:
7503 case Intrinsic::aarch64_sve_ld3_sret:
7504 case Intrinsic::aarch64_sve_ld3q_sret:
7507 case Intrinsic::aarch64_sve_st3q:
7510 case Intrinsic::aarch64_sve_ld4_sret:
7511 case Intrinsic::aarch64_sve_ld4q_sret:
7514 case Intrinsic::aarch64_sve_st4q:
7517 case Intrinsic::aarch64_sve_ld1udq:
7518 case Intrinsic::aarch64_sve_st1dq:
7519 return EVT(MVT::nxv1i64);
7520 case Intrinsic::aarch64_sve_ld1uwq:
7521 case Intrinsic::aarch64_sve_st1wq:
7522 return EVT(MVT::nxv1i32);
7529template <
int64_t Min,
int64_t Max>
7530bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7534 const DataLayout &
DL = CurDAG->getDataLayout();
7535 const MachineFrameInfo &MFI = MF->getFrameInfo();
7543 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7557 int64_t MulImm = std::numeric_limits<int64_t>::max();
7561 int64_t ByteOffset =
C->getSExtValue();
7562 const auto KnownVScale =
7565 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7568 MulImm = ByteOffset / KnownVScale;
7575 if ((MulImm % MemWidthBytes) != 0)
7578 int64_t
Offset = MulImm / MemWidthBytes;
7582 Base =
N.getOperand(0);
7591 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7597bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7616 int64_t ImmOff =
C->getSExtValue();
7617 unsigned Size = 1 << Scale;
7626 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7628 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7639 if (
C->getZExtValue() == Scale) {
7648bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7649 const AArch64TargetLowering *TLI =
7650 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7655bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7656 EVT VT =
N.getValueType();
7660bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7665 int64_t ImmOff =
C->getSExtValue();
7666 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7667 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7672 if (
SDValue C = MatchConstantOffset(
N)) {
7673 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7679 if (CurDAG->isBaseWithConstantOffset(
N)) {
7680 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7681 Base =
N.getOperand(0);
7689 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7693bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7713 uint64_t LowerBound = 0, UpperBound = 64;
7731 if (CN->getAPIntValue().uge(LowerBound) &&
7732 CN->getAPIntValue().ult(UpperBound)) {
7734 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7742template <
bool MatchCBB>
7749 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7751 Reg =
N.getOperand(0);
7753 SDLoc(
N), MVT::i32);
7761 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
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
unsigned getBitWidth() const
Get the bit width of this value.