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 ImmVal |= ImmVal << 8;
4440 ImmVal |= ImmVal << 16;
4441 ImmVal |= ImmVal << 32;
4445 ImmVal |= ImmVal << 16;
4446 ImmVal |= ImmVal << 32;
4449 ImmVal &= 0xFFFFFFFF;
4450 ImmVal |= ImmVal << 32;
4462 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4471bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4472 uint64_t
High,
bool AllowSaturation,
4475 uint64_t ImmVal = CN->getZExtValue();
4482 if (ImmVal >
High) {
4483 if (!AllowSaturation)
4488 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4495bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4509 const TargetLowering *TLI = getTargetLowering();
4512 SDValue FiOp = CurDAG->getTargetFrameIndex(
4514 int TagOffset =
N->getConstantOperandVal(3);
4516 SDNode *Out = CurDAG->getMachineNode(
4517 AArch64::TAGPstack,
DL, MVT::i64,
4518 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4519 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4520 ReplaceNode(
N, Out);
4524void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4526 "llvm.aarch64.tagp third argument must be an immediate");
4527 if (trySelectStackSlotTagP(
N))
4534 int TagOffset =
N->getConstantOperandVal(3);
4535 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4536 {
N->getOperand(1),
N->getOperand(2)});
4537 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4538 {
SDValue(N1, 0),
N->getOperand(2)});
4539 SDNode *N3 = CurDAG->getMachineNode(
4540 AArch64::ADDG,
DL, MVT::i64,
4541 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4542 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4546bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4550 if (
N->getConstantOperandVal(2) != 0)
4552 if (!
N->getOperand(0).isUndef())
4556 EVT VT =
N->getValueType(0);
4557 EVT InVT =
N->getOperand(1).getValueType();
4568 "Expected to insert into a packed scalable vector!");
4571 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4572 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4573 N->getOperand(1), RC));
4577bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4581 if (
N->getConstantOperandVal(1) != 0)
4585 EVT VT =
N->getValueType(0);
4586 EVT InVT =
N->getOperand(0).getValueType();
4597 "Expected to extract from a packed scalable vector!");
4600 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4601 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4602 N->getOperand(0), RC));
4606bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4612 EVT VT =
N->getValueType(0);
4625 (Subtarget->hasSVE2() ||
4626 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4627 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4630 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4634 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4635 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4636 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4643 bool IsXOROperand =
true;
4645 IsXOROperand =
false;
4651 APInt ShlAmt, ShrAmt;
4659 if (!IsXOROperand) {
4661 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4664 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4665 SDNode *SubRegToReg = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL,
4666 VT, Zero, MOVIV, ZSub);
4677 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4678 AArch64::XAR_ZZZI_D})) {
4679 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4704 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4714 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4722 bool IsXOROperand =
true;
4724 IsXOROperand =
false;
4727 R1 =
XOR.getOperand(0);
4728 R2 =
XOR.getOperand(1);
4738 if (ShAmt + HsAmt != VTSizeInBits)
4741 if (!IsXOROperand) {
4744 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4753 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4759 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4760 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4762 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4765 if (
R2.getValueType() == VT)
4766 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4774 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT, Undef,
4779 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4785 SDNode *XAR =
nullptr;
4789 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4790 AArch64::XAR_ZZZI_D}))
4791 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
4793 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
4796 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
4802 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4803 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
4806 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4807 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4813 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
4817 ReplaceNode(
N, XAR);
4821void AArch64DAGToDAGISel::Select(SDNode *Node) {
4823 if (
Node->isMachineOpcode()) {
4825 Node->setNodeId(-1);
4830 EVT VT =
Node->getValueType(0);
4832 switch (
Node->getOpcode()) {
4837 if (SelectCMP_SWAP(Node))
4842 case AArch64ISD::MRRS:
4843 if (tryReadRegister(Node))
4848 case AArch64ISD::MSRR:
4849 if (tryWriteRegister(Node))
4856 if (tryIndexedLoad(Node))
4865 if (tryBitfieldExtractOp(Node))
4867 if (tryBitfieldInsertInZeroOp(Node))
4872 if (tryShiftAmountMod(Node))
4877 if (tryBitfieldExtractOpFromSExt(Node))
4882 if (tryBitfieldInsertOp(Node))
4884 if (trySelectXAR(Node))
4889 if (trySelectCastScalableToFixedLengthVector(Node))
4895 if (trySelectCastFixedLengthToScalableVector(Node))
4904 if (ConstNode->
isZero()) {
4905 if (VT == MVT::i32) {
4907 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
4908 ReplaceNode(Node,
New.getNode());
4910 }
else if (VT == MVT::i64) {
4912 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
4913 ReplaceNode(Node,
New.getNode());
4924 const TargetLowering *TLI = getTargetLowering();
4925 SDValue TFI = CurDAG->getTargetFrameIndex(
4928 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
4929 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
4930 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
4934 unsigned IntNo =
Node->getConstantOperandVal(1);
4938 case Intrinsic::aarch64_gcsss: {
4942 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
4944 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
4945 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
4946 MVT::Other, Zero,
SDValue(SS1, 0));
4947 ReplaceNode(Node, SS2);
4950 case Intrinsic::aarch64_ldaxp:
4951 case Intrinsic::aarch64_ldxp: {
4953 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
4958 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
4959 MVT::Other, MemAddr, Chain);
4962 MachineMemOperand *MemOp =
4965 ReplaceNode(Node, Ld);
4968 case Intrinsic::aarch64_stlxp:
4969 case Intrinsic::aarch64_stxp: {
4971 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
4979 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
4981 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
4983 MachineMemOperand *MemOp =
4987 ReplaceNode(Node, St);
4990 case Intrinsic::aarch64_neon_ld1x2:
4991 if (VT == MVT::v8i8) {
4992 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
4994 }
else if (VT == MVT::v16i8) {
4995 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
4997 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
4998 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5000 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5001 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5003 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5004 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5006 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5007 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5009 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5010 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5012 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5013 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5017 case Intrinsic::aarch64_neon_ld1x3:
5018 if (VT == MVT::v8i8) {
5019 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5021 }
else if (VT == MVT::v16i8) {
5022 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5024 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5025 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5027 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5028 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5030 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5031 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5033 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5034 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5036 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5037 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5039 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5040 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5044 case Intrinsic::aarch64_neon_ld1x4:
5045 if (VT == MVT::v8i8) {
5046 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5048 }
else if (VT == MVT::v16i8) {
5049 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5051 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5052 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5054 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5055 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5057 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5058 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5060 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5061 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5063 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5064 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5066 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5067 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5071 case Intrinsic::aarch64_neon_ld2:
5072 if (VT == MVT::v8i8) {
5073 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5075 }
else if (VT == MVT::v16i8) {
5076 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5078 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5079 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5081 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5082 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5084 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5085 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5087 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5088 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5090 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5091 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5093 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5094 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5098 case Intrinsic::aarch64_neon_ld3:
5099 if (VT == MVT::v8i8) {
5100 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5102 }
else if (VT == MVT::v16i8) {
5103 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5105 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5106 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5108 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5109 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5111 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5112 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5114 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5115 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5117 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5118 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5120 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5121 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5125 case Intrinsic::aarch64_neon_ld4:
5126 if (VT == MVT::v8i8) {
5127 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5129 }
else if (VT == MVT::v16i8) {
5130 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5132 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5133 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5135 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5136 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5138 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5139 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5141 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5142 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5144 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5145 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5147 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5148 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5152 case Intrinsic::aarch64_neon_ld2r:
5153 if (VT == MVT::v8i8) {
5154 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5156 }
else if (VT == MVT::v16i8) {
5157 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5159 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5160 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5162 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5163 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5165 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5166 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5168 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5169 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5171 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5172 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5174 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5175 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5179 case Intrinsic::aarch64_neon_ld3r:
5180 if (VT == MVT::v8i8) {
5181 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5183 }
else if (VT == MVT::v16i8) {
5184 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5186 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5187 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5189 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5190 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5192 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5193 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5195 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5196 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5198 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5199 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5201 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5202 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5206 case Intrinsic::aarch64_neon_ld4r:
5207 if (VT == MVT::v8i8) {
5208 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5210 }
else if (VT == MVT::v16i8) {
5211 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5213 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5214 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5216 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5217 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5219 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5220 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5222 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5223 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5225 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5226 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5228 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5229 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5233 case Intrinsic::aarch64_neon_ld2lane:
5234 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5235 SelectLoadLane(Node, 2, AArch64::LD2i8);
5237 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5238 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5239 SelectLoadLane(Node, 2, AArch64::LD2i16);
5241 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5243 SelectLoadLane(Node, 2, AArch64::LD2i32);
5245 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5247 SelectLoadLane(Node, 2, AArch64::LD2i64);
5251 case Intrinsic::aarch64_neon_ld3lane:
5252 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5253 SelectLoadLane(Node, 3, AArch64::LD3i8);
5255 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5256 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5257 SelectLoadLane(Node, 3, AArch64::LD3i16);
5259 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5261 SelectLoadLane(Node, 3, AArch64::LD3i32);
5263 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5265 SelectLoadLane(Node, 3, AArch64::LD3i64);
5269 case Intrinsic::aarch64_neon_ld4lane:
5270 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5271 SelectLoadLane(Node, 4, AArch64::LD4i8);
5273 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5274 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5275 SelectLoadLane(Node, 4, AArch64::LD4i16);
5277 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5279 SelectLoadLane(Node, 4, AArch64::LD4i32);
5281 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5283 SelectLoadLane(Node, 4, AArch64::LD4i64);
5287 case Intrinsic::aarch64_ld64b:
5288 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5290 case Intrinsic::aarch64_sve_ld2q_sret: {
5291 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5294 case Intrinsic::aarch64_sve_ld3q_sret: {
5295 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5298 case Intrinsic::aarch64_sve_ld4q_sret: {
5299 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5302 case Intrinsic::aarch64_sve_ld2_sret: {
5303 if (VT == MVT::nxv16i8) {
5304 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5307 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5308 VT == MVT::nxv8bf16) {
5309 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5312 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5313 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5316 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5317 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5323 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5324 if (VT == MVT::nxv16i8) {
5325 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5326 SelectContiguousMultiVectorLoad(
5327 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5328 else if (Subtarget->hasSVE2p1())
5329 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5334 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5335 VT == MVT::nxv8bf16) {
5336 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5337 SelectContiguousMultiVectorLoad(
5338 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5339 else if (Subtarget->hasSVE2p1())
5340 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5345 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5346 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5347 SelectContiguousMultiVectorLoad(
5348 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5349 else if (Subtarget->hasSVE2p1())
5350 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5355 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5356 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5357 SelectContiguousMultiVectorLoad(
5358 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5359 else if (Subtarget->hasSVE2p1())
5360 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5368 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5369 if (VT == MVT::nxv16i8) {
5370 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5371 SelectContiguousMultiVectorLoad(
5372 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5373 else if (Subtarget->hasSVE2p1())
5374 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5379 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5380 VT == MVT::nxv8bf16) {
5381 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5382 SelectContiguousMultiVectorLoad(
5383 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5384 else if (Subtarget->hasSVE2p1())
5385 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5390 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5391 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5392 SelectContiguousMultiVectorLoad(
5393 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5394 else if (Subtarget->hasSVE2p1())
5395 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5400 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5401 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5402 SelectContiguousMultiVectorLoad(
5403 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5404 else if (Subtarget->hasSVE2p1())
5405 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5413 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5414 if (VT == MVT::nxv16i8) {
5415 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5416 SelectContiguousMultiVectorLoad(Node, 2, 0,
5417 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5418 AArch64::LDNT1B_2Z_PSEUDO);
5419 else if (Subtarget->hasSVE2p1())
5420 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5421 AArch64::LDNT1B_2Z);
5425 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5426 VT == MVT::nxv8bf16) {
5427 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5428 SelectContiguousMultiVectorLoad(Node, 2, 1,
5429 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5430 AArch64::LDNT1H_2Z_PSEUDO);
5431 else if (Subtarget->hasSVE2p1())
5432 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5433 AArch64::LDNT1H_2Z);
5437 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5438 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5439 SelectContiguousMultiVectorLoad(Node, 2, 2,
5440 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5441 AArch64::LDNT1W_2Z_PSEUDO);
5442 else if (Subtarget->hasSVE2p1())
5443 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5444 AArch64::LDNT1W_2Z);
5448 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5449 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5450 SelectContiguousMultiVectorLoad(Node, 2, 3,
5451 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5452 AArch64::LDNT1D_2Z_PSEUDO);
5453 else if (Subtarget->hasSVE2p1())
5454 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5455 AArch64::LDNT1D_2Z);
5462 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5463 if (VT == MVT::nxv16i8) {
5464 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5465 SelectContiguousMultiVectorLoad(Node, 4, 0,
5466 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5467 AArch64::LDNT1B_4Z_PSEUDO);
5468 else if (Subtarget->hasSVE2p1())
5469 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5470 AArch64::LDNT1B_4Z);
5474 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5475 VT == MVT::nxv8bf16) {
5476 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5477 SelectContiguousMultiVectorLoad(Node, 4, 1,
5478 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5479 AArch64::LDNT1H_4Z_PSEUDO);
5480 else if (Subtarget->hasSVE2p1())
5481 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5482 AArch64::LDNT1H_4Z);
5486 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5487 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5488 SelectContiguousMultiVectorLoad(Node, 4, 2,
5489 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5490 AArch64::LDNT1W_4Z_PSEUDO);
5491 else if (Subtarget->hasSVE2p1())
5492 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5493 AArch64::LDNT1W_4Z);
5497 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5498 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5499 SelectContiguousMultiVectorLoad(Node, 4, 3,
5500 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5501 AArch64::LDNT1D_4Z_PSEUDO);
5502 else if (Subtarget->hasSVE2p1())
5503 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5504 AArch64::LDNT1D_4Z);
5511 case Intrinsic::aarch64_sve_ld3_sret: {
5512 if (VT == MVT::nxv16i8) {
5513 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5516 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5517 VT == MVT::nxv8bf16) {
5518 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5521 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5522 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5525 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5526 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5532 case Intrinsic::aarch64_sve_ld4_sret: {
5533 if (VT == MVT::nxv16i8) {
5534 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5537 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5538 VT == MVT::nxv8bf16) {
5539 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5542 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5543 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5546 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5547 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5553 case Intrinsic::aarch64_sme_read_hor_vg2: {
5554 if (VT == MVT::nxv16i8) {
5555 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5556 AArch64::MOVA_2ZMXI_H_B);
5558 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5559 VT == MVT::nxv8bf16) {
5560 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5561 AArch64::MOVA_2ZMXI_H_H);
5563 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5564 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5565 AArch64::MOVA_2ZMXI_H_S);
5567 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5568 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5569 AArch64::MOVA_2ZMXI_H_D);
5574 case Intrinsic::aarch64_sme_read_ver_vg2: {
5575 if (VT == MVT::nxv16i8) {
5576 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5577 AArch64::MOVA_2ZMXI_V_B);
5579 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5580 VT == MVT::nxv8bf16) {
5581 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5582 AArch64::MOVA_2ZMXI_V_H);
5584 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5585 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5586 AArch64::MOVA_2ZMXI_V_S);
5588 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5589 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5590 AArch64::MOVA_2ZMXI_V_D);
5595 case Intrinsic::aarch64_sme_read_hor_vg4: {
5596 if (VT == MVT::nxv16i8) {
5597 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5598 AArch64::MOVA_4ZMXI_H_B);
5600 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5601 VT == MVT::nxv8bf16) {
5602 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5603 AArch64::MOVA_4ZMXI_H_H);
5605 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5606 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5607 AArch64::MOVA_4ZMXI_H_S);
5609 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5610 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5611 AArch64::MOVA_4ZMXI_H_D);
5616 case Intrinsic::aarch64_sme_read_ver_vg4: {
5617 if (VT == MVT::nxv16i8) {
5618 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5619 AArch64::MOVA_4ZMXI_V_B);
5621 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5622 VT == MVT::nxv8bf16) {
5623 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5624 AArch64::MOVA_4ZMXI_V_H);
5626 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5627 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5628 AArch64::MOVA_4ZMXI_V_S);
5630 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5631 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5632 AArch64::MOVA_4ZMXI_V_D);
5637 case Intrinsic::aarch64_sme_read_vg1x2: {
5638 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5639 AArch64::MOVA_VG2_2ZMXI);
5642 case Intrinsic::aarch64_sme_read_vg1x4: {
5643 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5644 AArch64::MOVA_VG4_4ZMXI);
5647 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5648 if (VT == MVT::nxv16i8) {
5649 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5651 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5652 VT == MVT::nxv8bf16) {
5653 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5655 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5656 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5658 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5659 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5664 case Intrinsic::aarch64_sme_readz_vert_x2: {
5665 if (VT == MVT::nxv16i8) {
5666 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5668 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5669 VT == MVT::nxv8bf16) {
5670 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5672 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5673 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5675 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5676 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5681 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5682 if (VT == MVT::nxv16i8) {
5683 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5685 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5686 VT == MVT::nxv8bf16) {
5687 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5689 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5690 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5692 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5693 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5698 case Intrinsic::aarch64_sme_readz_vert_x4: {
5699 if (VT == MVT::nxv16i8) {
5700 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5702 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5703 VT == MVT::nxv8bf16) {
5704 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5706 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5707 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5709 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5710 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5715 case Intrinsic::aarch64_sme_readz_x2: {
5716 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5720 case Intrinsic::aarch64_sme_readz_x4: {
5721 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5725 case Intrinsic::swift_async_context_addr: {
5728 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5730 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5731 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5732 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5734 ReplaceUses(
SDValue(Node, 0), Res);
5736 CurDAG->RemoveDeadNode(Node);
5738 auto &MF = CurDAG->getMachineFunction();
5739 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5740 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5743 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5745 Node->getValueType(0),
5746 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5747 AArch64::LUTI2_4ZTZI_S}))
5749 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5752 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5754 Node->getValueType(0),
5755 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5757 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5760 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5762 Node->getValueType(0),
5763 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5764 AArch64::LUTI2_2ZTZI_S}))
5766 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5769 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5771 Node->getValueType(0),
5772 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5773 AArch64::LUTI4_2ZTZI_S}))
5775 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5778 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5779 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5782 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5784 Node->getValueType(0),
5785 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5786 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5788 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
5790 Node->getValueType(0),
5791 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
5792 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5794 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
5796 Node->getValueType(0),
5797 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
5798 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5800 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
5802 Node->getValueType(0),
5803 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
5804 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5809 unsigned IntNo =
Node->getConstantOperandVal(0);
5813 case Intrinsic::aarch64_tagp:
5817 case Intrinsic::ptrauth_auth:
5818 SelectPtrauthAuth(Node);
5821 case Intrinsic::ptrauth_resign:
5822 SelectPtrauthResign(Node);
5825 case Intrinsic::aarch64_neon_tbl2:
5826 SelectTable(Node, 2,
5827 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
5830 case Intrinsic::aarch64_neon_tbl3:
5831 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
5832 : AArch64::TBLv16i8Three,
5835 case Intrinsic::aarch64_neon_tbl4:
5836 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
5837 : AArch64::TBLv16i8Four,
5840 case Intrinsic::aarch64_neon_tbx2:
5841 SelectTable(Node, 2,
5842 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
5845 case Intrinsic::aarch64_neon_tbx3:
5846 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
5847 : AArch64::TBXv16i8Three,
5850 case Intrinsic::aarch64_neon_tbx4:
5851 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
5852 : AArch64::TBXv16i8Four,
5855 case Intrinsic::aarch64_sve_srshl_single_x2:
5857 Node->getValueType(0),
5858 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
5859 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
5860 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5862 case Intrinsic::aarch64_sve_srshl_single_x4:
5864 Node->getValueType(0),
5865 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
5866 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
5867 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5869 case Intrinsic::aarch64_sve_urshl_single_x2:
5871 Node->getValueType(0),
5872 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
5873 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
5874 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5876 case Intrinsic::aarch64_sve_urshl_single_x4:
5878 Node->getValueType(0),
5879 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
5880 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
5881 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5883 case Intrinsic::aarch64_sve_srshl_x2:
5885 Node->getValueType(0),
5886 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
5887 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
5888 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5890 case Intrinsic::aarch64_sve_srshl_x4:
5892 Node->getValueType(0),
5893 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
5894 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
5895 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5897 case Intrinsic::aarch64_sve_urshl_x2:
5899 Node->getValueType(0),
5900 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
5901 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
5902 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5904 case Intrinsic::aarch64_sve_urshl_x4:
5906 Node->getValueType(0),
5907 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
5908 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
5909 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5911 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
5913 Node->getValueType(0),
5914 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
5915 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
5916 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5918 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
5920 Node->getValueType(0),
5921 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
5922 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
5923 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5925 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
5927 Node->getValueType(0),
5928 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
5929 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
5930 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5932 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
5934 Node->getValueType(0),
5935 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
5936 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
5937 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5939 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
5941 Node->getValueType(0),
5942 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
5943 AArch64::FSCALE_2ZZ_D}))
5944 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
5946 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
5948 Node->getValueType(0),
5949 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
5950 AArch64::FSCALE_4ZZ_D}))
5951 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
5953 case Intrinsic::aarch64_sme_fp8_scale_x2:
5955 Node->getValueType(0),
5956 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
5957 AArch64::FSCALE_2Z2Z_D}))
5958 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
5960 case Intrinsic::aarch64_sme_fp8_scale_x4:
5962 Node->getValueType(0),
5963 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
5964 AArch64::FSCALE_4Z4Z_D}))
5965 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
5967 case Intrinsic::aarch64_sve_whilege_x2:
5969 Node->getValueType(0),
5970 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
5971 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
5972 SelectWhilePair(Node,
Op);
5974 case Intrinsic::aarch64_sve_whilegt_x2:
5976 Node->getValueType(0),
5977 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
5978 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
5979 SelectWhilePair(Node,
Op);
5981 case Intrinsic::aarch64_sve_whilehi_x2:
5983 Node->getValueType(0),
5984 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
5985 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
5986 SelectWhilePair(Node,
Op);
5988 case Intrinsic::aarch64_sve_whilehs_x2:
5990 Node->getValueType(0),
5991 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
5992 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
5993 SelectWhilePair(Node,
Op);
5995 case Intrinsic::aarch64_sve_whilele_x2:
5997 Node->getValueType(0),
5998 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
5999 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6000 SelectWhilePair(Node,
Op);
6002 case Intrinsic::aarch64_sve_whilelo_x2:
6004 Node->getValueType(0),
6005 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6006 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6007 SelectWhilePair(Node,
Op);
6009 case Intrinsic::aarch64_sve_whilels_x2:
6011 Node->getValueType(0),
6012 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6013 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6014 SelectWhilePair(Node,
Op);
6016 case Intrinsic::aarch64_sve_whilelt_x2:
6018 Node->getValueType(0),
6019 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6020 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6021 SelectWhilePair(Node,
Op);
6023 case Intrinsic::aarch64_sve_smax_single_x2:
6025 Node->getValueType(0),
6026 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6027 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6028 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6030 case Intrinsic::aarch64_sve_umax_single_x2:
6032 Node->getValueType(0),
6033 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6034 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6035 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6037 case Intrinsic::aarch64_sve_fmax_single_x2:
6039 Node->getValueType(0),
6040 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6041 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6042 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6044 case Intrinsic::aarch64_sve_smax_single_x4:
6046 Node->getValueType(0),
6047 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6048 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6049 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6051 case Intrinsic::aarch64_sve_umax_single_x4:
6053 Node->getValueType(0),
6054 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6055 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6056 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6058 case Intrinsic::aarch64_sve_fmax_single_x4:
6060 Node->getValueType(0),
6061 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6062 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6063 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6065 case Intrinsic::aarch64_sve_smin_single_x2:
6067 Node->getValueType(0),
6068 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6069 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6070 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6072 case Intrinsic::aarch64_sve_umin_single_x2:
6074 Node->getValueType(0),
6075 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6076 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6077 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6079 case Intrinsic::aarch64_sve_fmin_single_x2:
6081 Node->getValueType(0),
6082 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6083 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6084 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6086 case Intrinsic::aarch64_sve_smin_single_x4:
6088 Node->getValueType(0),
6089 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6090 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6091 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6093 case Intrinsic::aarch64_sve_umin_single_x4:
6095 Node->getValueType(0),
6096 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6097 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6098 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6100 case Intrinsic::aarch64_sve_fmin_single_x4:
6102 Node->getValueType(0),
6103 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6104 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6105 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6107 case Intrinsic::aarch64_sve_smax_x2:
6109 Node->getValueType(0),
6110 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6111 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6112 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6114 case Intrinsic::aarch64_sve_umax_x2:
6116 Node->getValueType(0),
6117 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6118 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6119 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6121 case Intrinsic::aarch64_sve_fmax_x2:
6123 Node->getValueType(0),
6124 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6125 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6126 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6128 case Intrinsic::aarch64_sve_smax_x4:
6130 Node->getValueType(0),
6131 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6132 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6133 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6135 case Intrinsic::aarch64_sve_umax_x4:
6137 Node->getValueType(0),
6138 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6139 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6140 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6142 case Intrinsic::aarch64_sve_fmax_x4:
6144 Node->getValueType(0),
6145 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6146 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6147 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6149 case Intrinsic::aarch64_sme_famax_x2:
6151 Node->getValueType(0),
6152 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6153 AArch64::FAMAX_2Z2Z_D}))
6154 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6156 case Intrinsic::aarch64_sme_famax_x4:
6158 Node->getValueType(0),
6159 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6160 AArch64::FAMAX_4Z4Z_D}))
6161 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6163 case Intrinsic::aarch64_sme_famin_x2:
6165 Node->getValueType(0),
6166 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6167 AArch64::FAMIN_2Z2Z_D}))
6168 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6170 case Intrinsic::aarch64_sme_famin_x4:
6172 Node->getValueType(0),
6173 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6174 AArch64::FAMIN_4Z4Z_D}))
6175 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6177 case Intrinsic::aarch64_sve_smin_x2:
6179 Node->getValueType(0),
6180 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6181 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6182 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6184 case Intrinsic::aarch64_sve_umin_x2:
6186 Node->getValueType(0),
6187 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6188 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6189 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6191 case Intrinsic::aarch64_sve_fmin_x2:
6193 Node->getValueType(0),
6194 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6195 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6196 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6198 case Intrinsic::aarch64_sve_smin_x4:
6200 Node->getValueType(0),
6201 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6202 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6203 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6205 case Intrinsic::aarch64_sve_umin_x4:
6207 Node->getValueType(0),
6208 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6209 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6210 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6212 case Intrinsic::aarch64_sve_fmin_x4:
6214 Node->getValueType(0),
6215 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6216 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6217 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6219 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6221 Node->getValueType(0),
6222 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6223 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6224 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6226 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6228 Node->getValueType(0),
6229 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6230 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6231 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6233 case Intrinsic::aarch64_sve_fminnm_single_x2:
6235 Node->getValueType(0),
6236 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6237 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6238 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6240 case Intrinsic::aarch64_sve_fminnm_single_x4:
6242 Node->getValueType(0),
6243 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6244 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6245 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6247 case Intrinsic::aarch64_sve_fscale_single_x4:
6248 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6250 case Intrinsic::aarch64_sve_fscale_single_x2:
6251 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6253 case Intrinsic::aarch64_sve_fmul_single_x4:
6255 Node->getValueType(0),
6256 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6257 AArch64::FMUL_4ZZ_D}))
6258 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6260 case Intrinsic::aarch64_sve_fmul_single_x2:
6262 Node->getValueType(0),
6263 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6264 AArch64::FMUL_2ZZ_D}))
6265 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6267 case Intrinsic::aarch64_sve_fmaxnm_x2:
6269 Node->getValueType(0),
6270 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6271 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6272 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6274 case Intrinsic::aarch64_sve_fmaxnm_x4:
6276 Node->getValueType(0),
6277 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6278 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6279 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6281 case Intrinsic::aarch64_sve_fminnm_x2:
6283 Node->getValueType(0),
6284 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6285 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6286 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6288 case Intrinsic::aarch64_sve_fminnm_x4:
6290 Node->getValueType(0),
6291 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6292 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6293 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6295 case Intrinsic::aarch64_sve_fscale_x4:
6296 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6298 case Intrinsic::aarch64_sve_fscale_x2:
6299 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6301 case Intrinsic::aarch64_sve_fmul_x4:
6303 Node->getValueType(0),
6304 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6305 AArch64::FMUL_4Z4Z_D}))
6306 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6308 case Intrinsic::aarch64_sve_fmul_x2:
6310 Node->getValueType(0),
6311 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6312 AArch64::FMUL_2Z2Z_D}))
6313 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6315 case Intrinsic::aarch64_sve_fcvtzs_x2:
6316 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6318 case Intrinsic::aarch64_sve_scvtf_x2:
6319 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6321 case Intrinsic::aarch64_sve_fcvtzu_x2:
6322 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6324 case Intrinsic::aarch64_sve_ucvtf_x2:
6325 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6327 case Intrinsic::aarch64_sve_fcvtzs_x4:
6328 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6330 case Intrinsic::aarch64_sve_scvtf_x4:
6331 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6333 case Intrinsic::aarch64_sve_fcvtzu_x4:
6334 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6336 case Intrinsic::aarch64_sve_ucvtf_x4:
6337 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6339 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6340 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6342 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6343 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6345 case Intrinsic::aarch64_sve_sclamp_single_x2:
6347 Node->getValueType(0),
6348 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6349 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6350 SelectClamp(Node, 2,
Op);
6352 case Intrinsic::aarch64_sve_uclamp_single_x2:
6354 Node->getValueType(0),
6355 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6356 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6357 SelectClamp(Node, 2,
Op);
6359 case Intrinsic::aarch64_sve_fclamp_single_x2:
6361 Node->getValueType(0),
6362 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6363 AArch64::FCLAMP_VG2_2Z2Z_D}))
6364 SelectClamp(Node, 2,
Op);
6366 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6367 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6369 case Intrinsic::aarch64_sve_sclamp_single_x4:
6371 Node->getValueType(0),
6372 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6373 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6374 SelectClamp(Node, 4,
Op);
6376 case Intrinsic::aarch64_sve_uclamp_single_x4:
6378 Node->getValueType(0),
6379 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6380 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6381 SelectClamp(Node, 4,
Op);
6383 case Intrinsic::aarch64_sve_fclamp_single_x4:
6385 Node->getValueType(0),
6386 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6387 AArch64::FCLAMP_VG4_4Z4Z_D}))
6388 SelectClamp(Node, 4,
Op);
6390 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6391 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6393 case Intrinsic::aarch64_sve_add_single_x2:
6395 Node->getValueType(0),
6396 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6397 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6398 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6400 case Intrinsic::aarch64_sve_add_single_x4:
6402 Node->getValueType(0),
6403 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6404 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6405 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6407 case Intrinsic::aarch64_sve_zip_x2:
6409 Node->getValueType(0),
6410 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6411 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6412 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6414 case Intrinsic::aarch64_sve_zipq_x2:
6415 SelectUnaryMultiIntrinsic(Node, 2,
false,
6416 AArch64::ZIP_VG2_2ZZZ_Q);
6418 case Intrinsic::aarch64_sve_zip_x4:
6420 Node->getValueType(0),
6421 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6422 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6423 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6425 case Intrinsic::aarch64_sve_zipq_x4:
6426 SelectUnaryMultiIntrinsic(Node, 4,
true,
6427 AArch64::ZIP_VG4_4Z4Z_Q);
6429 case Intrinsic::aarch64_sve_uzp_x2:
6431 Node->getValueType(0),
6432 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6433 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6434 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6436 case Intrinsic::aarch64_sve_uzpq_x2:
6437 SelectUnaryMultiIntrinsic(Node, 2,
false,
6438 AArch64::UZP_VG2_2ZZZ_Q);
6440 case Intrinsic::aarch64_sve_uzp_x4:
6442 Node->getValueType(0),
6443 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6444 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6445 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6447 case Intrinsic::aarch64_sve_uzpq_x4:
6448 SelectUnaryMultiIntrinsic(Node, 4,
true,
6449 AArch64::UZP_VG4_4Z4Z_Q);
6451 case Intrinsic::aarch64_sve_sel_x2:
6453 Node->getValueType(0),
6454 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6455 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6456 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6458 case Intrinsic::aarch64_sve_sel_x4:
6460 Node->getValueType(0),
6461 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6462 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6463 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6465 case Intrinsic::aarch64_sve_frinta_x2:
6466 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6468 case Intrinsic::aarch64_sve_frinta_x4:
6469 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6471 case Intrinsic::aarch64_sve_frintm_x2:
6472 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6474 case Intrinsic::aarch64_sve_frintm_x4:
6475 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6477 case Intrinsic::aarch64_sve_frintn_x2:
6478 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6480 case Intrinsic::aarch64_sve_frintn_x4:
6481 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6483 case Intrinsic::aarch64_sve_frintp_x2:
6484 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6486 case Intrinsic::aarch64_sve_frintp_x4:
6487 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6489 case Intrinsic::aarch64_sve_sunpk_x2:
6491 Node->getValueType(0),
6492 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6493 AArch64::SUNPK_VG2_2ZZ_D}))
6494 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6496 case Intrinsic::aarch64_sve_uunpk_x2:
6498 Node->getValueType(0),
6499 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6500 AArch64::UUNPK_VG2_2ZZ_D}))
6501 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6503 case Intrinsic::aarch64_sve_sunpk_x4:
6505 Node->getValueType(0),
6506 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6507 AArch64::SUNPK_VG4_4Z2Z_D}))
6508 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6510 case Intrinsic::aarch64_sve_uunpk_x4:
6512 Node->getValueType(0),
6513 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6514 AArch64::UUNPK_VG4_4Z2Z_D}))
6515 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6517 case Intrinsic::aarch64_sve_pext_x2: {
6519 Node->getValueType(0),
6520 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6521 AArch64::PEXT_2PCI_D}))
6522 SelectPExtPair(Node,
Op);
6529 unsigned IntNo =
Node->getConstantOperandVal(1);
6530 if (
Node->getNumOperands() >= 3)
6531 VT =
Node->getOperand(2)->getValueType(0);
6535 case Intrinsic::aarch64_neon_st1x2: {
6536 if (VT == MVT::v8i8) {
6537 SelectStore(Node, 2, AArch64::ST1Twov8b);
6539 }
else if (VT == MVT::v16i8) {
6540 SelectStore(Node, 2, AArch64::ST1Twov16b);
6542 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6543 VT == MVT::v4bf16) {
6544 SelectStore(Node, 2, AArch64::ST1Twov4h);
6546 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6547 VT == MVT::v8bf16) {
6548 SelectStore(Node, 2, AArch64::ST1Twov8h);
6550 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6551 SelectStore(Node, 2, AArch64::ST1Twov2s);
6553 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6554 SelectStore(Node, 2, AArch64::ST1Twov4s);
6556 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6557 SelectStore(Node, 2, AArch64::ST1Twov2d);
6559 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6560 SelectStore(Node, 2, AArch64::ST1Twov1d);
6565 case Intrinsic::aarch64_neon_st1x3: {
6566 if (VT == MVT::v8i8) {
6567 SelectStore(Node, 3, AArch64::ST1Threev8b);
6569 }
else if (VT == MVT::v16i8) {
6570 SelectStore(Node, 3, AArch64::ST1Threev16b);
6572 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6573 VT == MVT::v4bf16) {
6574 SelectStore(Node, 3, AArch64::ST1Threev4h);
6576 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6577 VT == MVT::v8bf16) {
6578 SelectStore(Node, 3, AArch64::ST1Threev8h);
6580 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6581 SelectStore(Node, 3, AArch64::ST1Threev2s);
6583 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6584 SelectStore(Node, 3, AArch64::ST1Threev4s);
6586 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6587 SelectStore(Node, 3, AArch64::ST1Threev2d);
6589 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6590 SelectStore(Node, 3, AArch64::ST1Threev1d);
6595 case Intrinsic::aarch64_neon_st1x4: {
6596 if (VT == MVT::v8i8) {
6597 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6599 }
else if (VT == MVT::v16i8) {
6600 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6602 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6603 VT == MVT::v4bf16) {
6604 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6606 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6607 VT == MVT::v8bf16) {
6608 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6610 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6611 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6613 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6614 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6616 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6617 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6619 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6620 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6625 case Intrinsic::aarch64_neon_st2: {
6626 if (VT == MVT::v8i8) {
6627 SelectStore(Node, 2, AArch64::ST2Twov8b);
6629 }
else if (VT == MVT::v16i8) {
6630 SelectStore(Node, 2, AArch64::ST2Twov16b);
6632 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6633 VT == MVT::v4bf16) {
6634 SelectStore(Node, 2, AArch64::ST2Twov4h);
6636 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6637 VT == MVT::v8bf16) {
6638 SelectStore(Node, 2, AArch64::ST2Twov8h);
6640 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6641 SelectStore(Node, 2, AArch64::ST2Twov2s);
6643 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6644 SelectStore(Node, 2, AArch64::ST2Twov4s);
6646 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6647 SelectStore(Node, 2, AArch64::ST2Twov2d);
6649 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6650 SelectStore(Node, 2, AArch64::ST1Twov1d);
6655 case Intrinsic::aarch64_neon_st3: {
6656 if (VT == MVT::v8i8) {
6657 SelectStore(Node, 3, AArch64::ST3Threev8b);
6659 }
else if (VT == MVT::v16i8) {
6660 SelectStore(Node, 3, AArch64::ST3Threev16b);
6662 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6663 VT == MVT::v4bf16) {
6664 SelectStore(Node, 3, AArch64::ST3Threev4h);
6666 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6667 VT == MVT::v8bf16) {
6668 SelectStore(Node, 3, AArch64::ST3Threev8h);
6670 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6671 SelectStore(Node, 3, AArch64::ST3Threev2s);
6673 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6674 SelectStore(Node, 3, AArch64::ST3Threev4s);
6676 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6677 SelectStore(Node, 3, AArch64::ST3Threev2d);
6679 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6680 SelectStore(Node, 3, AArch64::ST1Threev1d);
6685 case Intrinsic::aarch64_neon_st4: {
6686 if (VT == MVT::v8i8) {
6687 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6689 }
else if (VT == MVT::v16i8) {
6690 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6692 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6693 VT == MVT::v4bf16) {
6694 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6696 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6697 VT == MVT::v8bf16) {
6698 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6700 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6701 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6703 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6704 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6706 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6707 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6709 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6710 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6715 case Intrinsic::aarch64_neon_st2lane: {
6716 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6717 SelectStoreLane(Node, 2, AArch64::ST2i8);
6719 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6720 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6721 SelectStoreLane(Node, 2, AArch64::ST2i16);
6723 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6725 SelectStoreLane(Node, 2, AArch64::ST2i32);
6727 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6729 SelectStoreLane(Node, 2, AArch64::ST2i64);
6734 case Intrinsic::aarch64_neon_st3lane: {
6735 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6736 SelectStoreLane(Node, 3, AArch64::ST3i8);
6738 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6739 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6740 SelectStoreLane(Node, 3, AArch64::ST3i16);
6742 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6744 SelectStoreLane(Node, 3, AArch64::ST3i32);
6746 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6748 SelectStoreLane(Node, 3, AArch64::ST3i64);
6753 case Intrinsic::aarch64_neon_st4lane: {
6754 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6755 SelectStoreLane(Node, 4, AArch64::ST4i8);
6757 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6758 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6759 SelectStoreLane(Node, 4, AArch64::ST4i16);
6761 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6763 SelectStoreLane(Node, 4, AArch64::ST4i32);
6765 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6767 SelectStoreLane(Node, 4, AArch64::ST4i64);
6772 case Intrinsic::aarch64_sve_st2q: {
6773 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
6776 case Intrinsic::aarch64_sve_st3q: {
6777 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
6780 case Intrinsic::aarch64_sve_st4q: {
6781 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
6784 case Intrinsic::aarch64_sve_st2: {
6785 if (VT == MVT::nxv16i8) {
6786 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
6788 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6789 VT == MVT::nxv8bf16) {
6790 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
6792 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6793 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
6795 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6796 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
6801 case Intrinsic::aarch64_sve_st3: {
6802 if (VT == MVT::nxv16i8) {
6803 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
6805 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6806 VT == MVT::nxv8bf16) {
6807 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
6809 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6810 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
6812 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6813 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
6818 case Intrinsic::aarch64_sve_st4: {
6819 if (VT == MVT::nxv16i8) {
6820 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
6822 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6823 VT == MVT::nxv8bf16) {
6824 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
6826 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6827 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
6829 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6830 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
6838 case AArch64ISD::LD2post: {
6839 if (VT == MVT::v8i8) {
6840 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
6842 }
else if (VT == MVT::v16i8) {
6843 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
6845 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6846 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
6848 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6849 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
6851 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6852 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
6854 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6855 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
6857 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6858 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6860 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6861 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
6866 case AArch64ISD::LD3post: {
6867 if (VT == MVT::v8i8) {
6868 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
6870 }
else if (VT == MVT::v16i8) {
6871 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
6873 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6874 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
6876 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6877 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
6879 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6880 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
6882 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6883 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
6885 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6886 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6888 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6889 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
6894 case AArch64ISD::LD4post: {
6895 if (VT == MVT::v8i8) {
6896 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
6898 }
else if (VT == MVT::v16i8) {
6899 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
6901 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6902 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
6904 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6905 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
6907 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6908 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
6910 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6911 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
6913 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6914 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
6916 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6917 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
6922 case AArch64ISD::LD1x2post: {
6923 if (VT == MVT::v8i8) {
6924 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
6926 }
else if (VT == MVT::v16i8) {
6927 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
6929 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6930 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
6932 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6933 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
6935 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6936 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
6938 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6939 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
6941 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6942 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
6944 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6945 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
6950 case AArch64ISD::LD1x3post: {
6951 if (VT == MVT::v8i8) {
6952 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
6954 }
else if (VT == MVT::v16i8) {
6955 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
6957 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6958 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
6960 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6961 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
6963 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6964 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
6966 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6967 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
6969 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6970 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
6972 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6973 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
6978 case AArch64ISD::LD1x4post: {
6979 if (VT == MVT::v8i8) {
6980 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
6982 }
else if (VT == MVT::v16i8) {
6983 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
6985 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
6986 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
6988 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
6989 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
6991 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6992 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
6994 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6995 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
6997 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6998 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7000 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7001 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7006 case AArch64ISD::LD1DUPpost: {
7007 if (VT == MVT::v8i8) {
7008 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7010 }
else if (VT == MVT::v16i8) {
7011 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7013 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7014 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7016 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7017 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7019 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7020 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7022 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7023 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7025 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7026 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7028 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7029 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7034 case AArch64ISD::LD2DUPpost: {
7035 if (VT == MVT::v8i8) {
7036 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7038 }
else if (VT == MVT::v16i8) {
7039 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7041 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7042 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7044 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7045 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7047 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7048 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7050 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7051 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7053 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7054 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7056 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7057 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7062 case AArch64ISD::LD3DUPpost: {
7063 if (VT == MVT::v8i8) {
7064 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7066 }
else if (VT == MVT::v16i8) {
7067 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7069 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7070 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7072 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7073 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7075 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7076 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7078 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7079 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7081 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7082 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7084 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7085 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7090 case AArch64ISD::LD4DUPpost: {
7091 if (VT == MVT::v8i8) {
7092 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7094 }
else if (VT == MVT::v16i8) {
7095 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7097 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7098 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7100 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7101 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7103 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7104 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7106 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7107 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7109 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7110 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7112 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7113 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7118 case AArch64ISD::LD1LANEpost: {
7119 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7120 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7122 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7123 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7124 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7126 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7128 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7130 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7132 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7137 case AArch64ISD::LD2LANEpost: {
7138 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7139 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7141 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7142 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7143 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7145 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7147 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7149 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7151 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7156 case AArch64ISD::LD3LANEpost: {
7157 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7158 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7160 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7161 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7162 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7164 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7166 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7168 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7170 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7175 case AArch64ISD::LD4LANEpost: {
7176 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7177 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7179 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7180 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7181 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7183 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7185 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7187 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7189 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7194 case AArch64ISD::ST2post: {
7195 VT =
Node->getOperand(1).getValueType();
7196 if (VT == MVT::v8i8) {
7197 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7199 }
else if (VT == MVT::v16i8) {
7200 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7202 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7203 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7205 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7206 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7208 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7209 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7211 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7212 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7214 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7215 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7217 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7218 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7223 case AArch64ISD::ST3post: {
7224 VT =
Node->getOperand(1).getValueType();
7225 if (VT == MVT::v8i8) {
7226 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7228 }
else if (VT == MVT::v16i8) {
7229 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7231 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7232 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7234 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7235 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7237 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7238 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7240 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7241 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7243 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7244 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7246 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7247 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7252 case AArch64ISD::ST4post: {
7253 VT =
Node->getOperand(1).getValueType();
7254 if (VT == MVT::v8i8) {
7255 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7257 }
else if (VT == MVT::v16i8) {
7258 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7260 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7261 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7263 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7264 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7266 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7267 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7269 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7270 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7272 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7273 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7275 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7276 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7281 case AArch64ISD::ST1x2post: {
7282 VT =
Node->getOperand(1).getValueType();
7283 if (VT == MVT::v8i8) {
7284 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7286 }
else if (VT == MVT::v16i8) {
7287 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7289 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7290 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7292 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7293 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7295 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7296 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7298 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7299 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7301 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7302 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7304 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7305 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7310 case AArch64ISD::ST1x3post: {
7311 VT =
Node->getOperand(1).getValueType();
7312 if (VT == MVT::v8i8) {
7313 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7315 }
else if (VT == MVT::v16i8) {
7316 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7318 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7319 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7321 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7322 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7324 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7325 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7327 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7328 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7330 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7331 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7333 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7334 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7339 case AArch64ISD::ST1x4post: {
7340 VT =
Node->getOperand(1).getValueType();
7341 if (VT == MVT::v8i8) {
7342 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7344 }
else if (VT == MVT::v16i8) {
7345 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7347 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7348 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7350 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7351 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7353 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7354 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7356 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7357 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7359 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7360 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7362 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7363 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7368 case AArch64ISD::ST2LANEpost: {
7369 VT =
Node->getOperand(1).getValueType();
7370 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7371 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7373 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7374 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7375 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7377 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7379 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7381 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7383 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7388 case AArch64ISD::ST3LANEpost: {
7389 VT =
Node->getOperand(1).getValueType();
7390 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7391 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7393 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7394 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7395 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7397 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7399 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7401 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7403 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7408 case AArch64ISD::ST4LANEpost: {
7409 VT =
Node->getOperand(1).getValueType();
7410 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7411 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7413 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7414 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7415 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7417 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7419 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7421 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7423 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7438 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7450 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7454 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7455 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7470 return MemIntr->getMemoryVT();
7477 DataVT = Load->getValueType(0);
7479 DataVT = Load->getValueType(0);
7481 DataVT = Store->getValue().getValueType();
7483 DataVT = Store->getValue().getValueType();
7490 const unsigned Opcode = Root->
getOpcode();
7494 case AArch64ISD::LD1_MERGE_ZERO:
7495 case AArch64ISD::LD1S_MERGE_ZERO:
7496 case AArch64ISD::LDNF1_MERGE_ZERO:
7497 case AArch64ISD::LDNF1S_MERGE_ZERO:
7499 case AArch64ISD::ST1_PRED:
7511 case Intrinsic::aarch64_sme_ldr:
7512 case Intrinsic::aarch64_sme_str:
7513 return MVT::nxv16i8;
7514 case Intrinsic::aarch64_sve_prf:
7519 case Intrinsic::aarch64_sve_ld2_sret:
7520 case Intrinsic::aarch64_sve_ld2q_sret:
7523 case Intrinsic::aarch64_sve_st2q:
7526 case Intrinsic::aarch64_sve_ld3_sret:
7527 case Intrinsic::aarch64_sve_ld3q_sret:
7530 case Intrinsic::aarch64_sve_st3q:
7533 case Intrinsic::aarch64_sve_ld4_sret:
7534 case Intrinsic::aarch64_sve_ld4q_sret:
7537 case Intrinsic::aarch64_sve_st4q:
7540 case Intrinsic::aarch64_sve_ld1udq:
7541 case Intrinsic::aarch64_sve_st1dq:
7542 return EVT(MVT::nxv1i64);
7543 case Intrinsic::aarch64_sve_ld1uwq:
7544 case Intrinsic::aarch64_sve_st1wq:
7545 return EVT(MVT::nxv1i32);
7552template <
int64_t Min,
int64_t Max>
7553bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7557 const DataLayout &
DL = CurDAG->getDataLayout();
7558 const MachineFrameInfo &MFI = MF->getFrameInfo();
7566 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7580 int64_t MulImm = std::numeric_limits<int64_t>::max();
7584 int64_t ByteOffset =
C->getSExtValue();
7585 const auto KnownVScale =
7588 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7591 MulImm = ByteOffset / KnownVScale;
7598 if ((MulImm % MemWidthBytes) != 0)
7601 int64_t
Offset = MulImm / MemWidthBytes;
7605 Base =
N.getOperand(0);
7614 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7620bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7639 int64_t ImmOff =
C->getSExtValue();
7640 unsigned Size = 1 << Scale;
7649 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7651 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7662 if (
C->getZExtValue() == Scale) {
7671bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7672 const AArch64TargetLowering *TLI =
7673 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7678bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7679 EVT VT =
N.getValueType();
7683bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7688 int64_t ImmOff =
C->getSExtValue();
7689 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7690 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7695 if (
SDValue C = MatchConstantOffset(
N)) {
7696 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7702 if (CurDAG->isBaseWithConstantOffset(
N)) {
7703 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7704 Base =
N.getOperand(0);
7712 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7716bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
7736 uint64_t LowerBound = 0, UpperBound = 64;
7754 if (CN->getAPIntValue().uge(LowerBound) &&
7755 CN->getAPIntValue().ult(UpperBound)) {
7757 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
7765template <
bool MatchCBB>
7772 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
7774 Reg =
N.getOperand(0);
7776 SDLoc(
N), MVT::i32);
7784 Reg =
N.getOperand(0);
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const AArch64RegisterInfo * getRegisterInfo() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(SelectionDAG &DAG, SDValue N) const
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
uint64_t getScalarSizeInBits() const
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static MVT getVectorVT(MVT VT, unsigned NumElements)
bool hasScalableStackID(int ObjectIdx) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
unsigned getID() const
Return the register class ID number.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t parseGenericRegister(StringRef Name)
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t &Encoding)
processLogicalImmediate - Determine if an immediate value can be encoded as the immediate operand of ...
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static constexpr unsigned SVEBitsPerBlock
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ 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.