23#include "llvm/IR/IntrinsicsAArch64.h"
32#define DEBUG_TYPE "aarch64-isel"
33#define PASS_NAME "AArch64 Instruction Selection"
36#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
37#pragma inline_depth(0)
53 AArch64DAGToDAGISel() =
delete;
65 void PreprocessISelDAG()
override;
69 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
71 std::vector<SDValue> &OutOps)
override;
73 template <
signed Low,
signed High,
signed Scale>
76 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,
418 void SelectMultiVectorLuti6LaneX4(
SDNode *
Node,
unsigned NumIndexVecs);
420 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc,
423 template <
unsigned MaxIdx,
unsigned Scale>
428 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
429 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
430 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
431 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
432 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
433 unsigned Opc_rr,
unsigned Opc_ri);
434 std::tuple<unsigned, SDValue, SDValue>
435 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
439 bool tryBitfieldExtractOp(
SDNode *
N);
440 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
441 bool tryBitfieldInsertOp(
SDNode *
N);
442 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
443 bool tryShiftAmountMod(
SDNode *
N);
445 bool tryReadRegister(
SDNode *
N);
446 bool tryWriteRegister(
SDNode *
N);
448 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
449 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
456#include "AArch64GenDAGISel.inc"
464 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
466 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
479 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
480 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
481 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
484 template<
unsigned RegW
idth>
486 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
488 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
490 template <
unsigned RegW
idth>
492 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
494 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
496 template<
unsigned RegW
idth>
498 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
504 template <
unsigned FloatW
idth>
506 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
512 bool SelectCMP_SWAP(
SDNode *
N);
531 bool AllowSaturation,
SDValue &Imm);
539 bool SelectAllActivePredicate(
SDValue N);
544 template <
bool MatchCBB>
554 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
558char AArch64DAGToDAGISelLegacy::ID = 0;
564 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
570 auto getFloatVT = [&](
EVT VT) {
572 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
573 return VT.changeElementType(*(DAG.
getContext()),
574 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
579 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
580 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
584 EVT OrigVT =
N.getValueType(0);
593 Imm =
C->getZExtValue();
610 return N->getOpcode() ==
Opc &&
621 return Imm == ImmExpected;
626 assert(RegWidth == 32 || RegWidth == 64);
628 return APInt(RegWidth,
635 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
636 if (
N->getOpcode() == AArch64ISD::NVCAST)
637 N =
N->getOperand(0);
638 unsigned SplatWidth =
N.getScalarValueSizeInBits();
639 if (
N.getOpcode() == AArch64ISD::FMOV)
641 if (
N->getOpcode() == AArch64ISD::MOVI)
642 return APInt(SplatWidth,
N.getConstantOperandVal(0));
643 if (
N->getOpcode() == AArch64ISD::MOVIshift)
644 return APInt(SplatWidth,
N.getConstantOperandVal(0)
645 <<
N.getConstantOperandVal(1));
646 if (
N->getOpcode() == AArch64ISD::MVNIshift)
647 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
648 <<
N.getConstantOperandVal(1));
649 if (
N->getOpcode() == AArch64ISD::MOVIedit)
651 N.getConstantOperandVal(0)));
652 if (
N->getOpcode() == AArch64ISD::DUP)
654 return Const->getAPIntValue().trunc(SplatWidth);
663 unsigned SplatWidth =
N.getScalarValueSizeInBits();
665 if (SplatVal->getBitWidth() <= SplatWidth)
667 if (SplatVal->isSplat(SplatWidth))
668 return SplatVal->trunc(SplatWidth);
673bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
680 ImmVal->getZExtValue(), Encoding))
683 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
687bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(
SDValue N,
SDValue &Imm,
690 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
691 N.getValueType().getScalarType().getSimpleVT(),
697bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(
SDValue N,
700 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal, Imm);
704bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
706 std::vector<SDValue> &OutOps) {
707 switch(ConstraintID) {
710 case InlineAsm::ConstraintCode::m:
711 case InlineAsm::ConstraintCode::o:
712 case InlineAsm::ConstraintCode::Q:
716 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
718 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
720 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
721 dl,
Op.getValueType(),
723 OutOps.push_back(NewOp);
742 uint64_t Immed =
N.getNode()->getAsZExtVal();
752 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
753 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
770 uint64_t Immed =
N.getNode()->getAsZExtVal();
778 if (
N.getValueType() == MVT::i32)
779 Immed = ~((uint32_t)Immed) + 1;
781 Immed = ~Immed + 1ULL;
782 if (Immed & 0xFFFFFFFFFF000000ULL)
785 Immed &= 0xFFFFFFULL;
786 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
793 switch (
N.getOpcode()) {
819 unsigned ShiftVal = CSD->getZExtValue();
837bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
840 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
845 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
869 EVT VT =
N.getValueType();
870 if (VT != MVT::i32 && VT != MVT::i64)
873 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
879 unsigned LHSOpcode =
LHS->getOpcode();
893 unsigned LowZBits, MaskLen;
897 unsigned BitWidth =
N.getValueSizeInBits();
904 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
907 NewShiftC = LowZBits - ShiftAmtC;
908 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
914 NewShiftC = LowZBits + ShiftAmtC;
927 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
929 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
933 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
935 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
936 NewShiftAmt, BitWidthMinus1),
939 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
953 SrcVT =
N.getOperand(0).getValueType();
955 if (!IsLoadStore && SrcVT == MVT::i8)
957 else if (!IsLoadStore && SrcVT == MVT::i16)
959 else if (SrcVT == MVT::i32)
961 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
966 EVT SrcVT =
N.getOperand(0).getValueType();
967 if (!IsLoadStore && SrcVT == MVT::i8)
969 else if (!IsLoadStore && SrcVT == MVT::i16)
971 else if (SrcVT == MVT::i32)
973 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1001bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
1004 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1009 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1010 V.getConstantOperandVal(1) <= 4 &&
1023bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
1025 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1035 unsigned BitSize =
N.getValueSizeInBits();
1036 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1039 Reg =
N.getOperand(0);
1040 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1041 return isWorthFoldingALU(
N,
true);
1052 if (
N.getValueType() == MVT::i32)
1060template<
signed Low,
signed High,
signed Scale>
1066 if ((MulImm % std::abs(Scale)) == 0) {
1067 int64_t RDVLImm = MulImm / Scale;
1068 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1069 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1078template <
signed Low,
signed High>
1079bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
1084 if (MulImm >=
Low && MulImm <=
High) {
1085 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1096 unsigned ShiftVal = 0;
1111 Reg =
N.getOperand(0).getOperand(0);
1123 Op =
Op->getOperand(0);
1125 Op.getOperand(0).getValueType().isFixedLengthVector())
1129 Reg =
N.getOperand(0);
1134 unsigned Opc =
N.getOpcode();
1152 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1154 return isWorthFoldingALU(
N);
1161 unsigned ShiftVal = 0;
1175 Reg =
N.getOperand(0);
1176 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1178 return isWorthFoldingALU(
N);
1187 for (
auto *
User :
N->users()) {
1214bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1215 unsigned BW,
unsigned Size,
1219 const DataLayout &
DL = CurDAG->getDataLayout();
1220 const TargetLowering *TLI = getTargetLowering();
1224 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1230 if (CurDAG->isBaseWithConstantOffset(
N)) {
1233 int64_t RHSC =
RHS->getSExtValue();
1235 int64_t
Range = 0x1LL << (BW - 1);
1237 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1238 RHSC < (
Range << Scale)) {
1239 Base =
N.getOperand(0);
1244 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1249 uint64_t RHSC =
RHS->getZExtValue();
1251 uint64_t
Range = 0x1ULL << BW;
1253 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1254 Base =
N.getOperand(0);
1259 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1270 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1277bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1280 const DataLayout &
DL = CurDAG->getDataLayout();
1281 const TargetLowering *TLI = getTargetLowering();
1285 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1290 GlobalAddressSDNode *GAN =
1292 Base =
N.getOperand(0);
1302 if (CurDAG->isBaseWithConstantOffset(
N)) {
1304 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1307 Base =
N.getOperand(0);
1312 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1320 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1328 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1337bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1340 if (!CurDAG->isBaseWithConstantOffset(
N))
1343 int64_t RHSC =
RHS->getSExtValue();
1344 if (RHSC >= -256 && RHSC < 256) {
1345 Base =
N.getOperand(0);
1348 const TargetLowering *TLI = getTargetLowering();
1349 Base = CurDAG->getTargetFrameIndex(
1352 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1362 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1369bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1389 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1395 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1398 return isWorthFoldingAddr(
N,
Size);
1401bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1419 const SDNode *
Node =
N.getNode();
1420 for (SDNode *UI :
Node->users()) {
1426 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1429 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1432 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1437 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1440 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1445 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1449 if (IsExtendedRegisterWorthFolding &&
1456 if (isWorthFoldingAddr(
LHS,
Size))
1461 if (IsExtendedRegisterWorthFolding &&
1468 if (isWorthFoldingAddr(
RHS,
Size))
1480 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1483 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1485 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1486 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1490bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1503 const SDNode *
Node =
N.getNode();
1504 for (SDNode *UI :
Node->users()) {
1521 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1531 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1538 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1541 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1544 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1549 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1552 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1559 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1560 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1566 static const unsigned RegClassIDs[] = {
1567 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1568 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1569 AArch64::dsub2, AArch64::dsub3};
1575 static const unsigned RegClassIDs[] = {
1576 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1577 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1578 AArch64::qsub2, AArch64::qsub3};
1584 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1585 AArch64::ZPR3RegClassID,
1586 AArch64::ZPR4RegClassID};
1587 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1588 AArch64::zsub2, AArch64::zsub3};
1598 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1599 AArch64::ZPR4Mul4RegClassID};
1600 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1601 AArch64::zsub2, AArch64::zsub3};
1606 const unsigned RegClassIDs[],
1607 const unsigned SubRegs[]) {
1610 if (Regs.
size() == 1)
1621 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1624 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1625 Ops.push_back(Regs[i]);
1626 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1630 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1634void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1637 EVT VT =
N->getValueType(0);
1639 unsigned ExtOff = isExt;
1642 unsigned Vec0Off = ExtOff + 1;
1648 Ops.push_back(
N->getOperand(1));
1649 Ops.push_back(RegSeq);
1650 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1651 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1654static std::tuple<SDValue, SDValue>
1675 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1680 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1682 return std::make_tuple(
1687void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1692 SDValue AUTDisc =
N->getOperand(3);
1695 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1697 SDValue AUTAddrDisc, AUTConstDisc;
1698 std::tie(AUTConstDisc, AUTAddrDisc) =
1702 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1704 if (
N->getNumOperands() > 4)
1705 Ops.push_back(
N->getOperand(4));
1708 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1709 ReplaceNode(
N, AUT);
1711 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1712 AArch64::X16, Val,
SDValue());
1715 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1716 ReplaceNode(
N, AUT);
1720void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1730 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1735 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1736 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1738 SDValue AUTAddrDisc, AUTConstDisc;
1739 std::tie(AUTConstDisc, AUTAddrDisc) =
1742 SDValue PACAddrDisc, PACConstDisc;
1743 std::tie(PACConstDisc, PACAddrDisc) =
1746 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1747 AArch64::X16, Val,
SDValue());
1750 SDValue Addend =
N->getOperand(OffsetBase + 6);
1751 SDValue IncomingChain =
N->getOperand(0);
1752 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1753 PACKey, PACConstDisc, PACAddrDisc,
1754 Addend, IncomingChain, X16Copy.
getValue(1)};
1756 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1757 MVT::i64, MVT::Other,
Ops);
1758 ReplaceNode(
N, AUTRELLOADPAC);
1760 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1761 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1763 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1764 ReplaceNode(
N, AUTPAC);
1768bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1770 if (
LD->isUnindexed())
1772 EVT VT =
LD->getMemoryVT();
1773 EVT DstVT =
N->getValueType(0);
1777 int OffsetVal = (int)
OffsetOp->getZExtValue();
1782 unsigned Opcode = 0;
1785 bool InsertTo64 =
false;
1787 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1788 else if (VT == MVT::i32) {
1790 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1792 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1794 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1800 }
else if (VT == MVT::i16) {
1802 if (DstVT == MVT::i64)
1803 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1805 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1807 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1808 InsertTo64 = DstVT == MVT::i64;
1813 }
else if (VT == MVT::i8) {
1815 if (DstVT == MVT::i64)
1816 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1818 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1820 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1821 InsertTo64 = DstVT == MVT::i64;
1826 }
else if (VT == MVT::f16) {
1827 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1828 }
else if (VT == MVT::bf16) {
1829 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1830 }
else if (VT == MVT::f32) {
1831 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1832 }
else if (VT == MVT::f64 ||
1834 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1836 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1838 if (IsPre || OffsetVal != 8)
1842 Opcode = AArch64::LD1Onev8b_POST;
1845 Opcode = AArch64::LD1Onev4h_POST;
1848 Opcode = AArch64::LD1Onev2s_POST;
1851 Opcode = AArch64::LD1Onev1d_POST;
1857 if (IsPre || OffsetVal != 16)
1861 Opcode = AArch64::LD1Onev16b_POST;
1864 Opcode = AArch64::LD1Onev8h_POST;
1867 Opcode = AArch64::LD1Onev4s_POST;
1870 Opcode = AArch64::LD1Onev2d_POST;
1882 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1883 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1885 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1895 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1896 LoadedVal =
SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
1897 MVT::i64, LoadedVal, SubReg),
1901 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1904 CurDAG->RemoveDeadNode(
N);
1908void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1909 unsigned SubRegIdx) {
1911 EVT VT =
N->getValueType(0);
1917 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1919 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1921 for (
unsigned i = 0; i < NumVecs; ++i)
1923 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1930 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1934 CurDAG->RemoveDeadNode(
N);
1937void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1938 unsigned Opc,
unsigned SubRegIdx) {
1940 EVT VT =
N->getValueType(0);
1947 const EVT ResTys[] = {MVT::i64,
1948 MVT::Untyped, MVT::Other};
1950 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1958 ReplaceUses(
SDValue(
N, 0), SuperReg);
1960 for (
unsigned i = 0; i < NumVecs; ++i)
1962 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1970 CurDAG->RemoveDeadNode(
N);
1976std::tuple<unsigned, SDValue, SDValue>
1977AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1983 SDValue NewOffset = OldOffset;
1985 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1986 N, OldBase, NewBase, NewOffset);
1990 const bool IsRegReg =
1991 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1994 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2007template <SelectTypeKind Kind>
2019 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2024 if (EltVT != MVT::i1)
2028 if (EltVT == MVT::bf16)
2030 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2060void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2063 if (
Imm->getZExtValue() > 1)
2067 EVT VT =
N->getValueType(0);
2069 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2072 for (
unsigned I = 0;
I < 2; ++
I)
2073 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2074 AArch64::psub0 +
I,
DL, VT, SuperReg));
2076 CurDAG->RemoveDeadNode(
N);
2079void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2081 EVT VT =
N->getValueType(0);
2085 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2088 for (
unsigned I = 0;
I < 2; ++
I)
2089 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2090 AArch64::psub0 +
I,
DL, VT, SuperReg));
2092 CurDAG->RemoveDeadNode(
N);
2095void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2097 EVT VT =
N->getValueType(0);
2101 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2103 for (
unsigned i = 0; i < NumVecs; ++i)
2104 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2105 AArch64::zsub0 + i,
DL, VT, SuperReg));
2107 CurDAG->RemoveDeadNode(
N);
2110void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2113 EVT VT =
N->getValueType(0);
2115 Ops.push_back(
N->getOperand(0));
2118 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2121 for (
unsigned i = 0; i < NumVecs; ++i)
2122 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2123 AArch64::zsub0 + i,
DL, VT, SuperReg));
2126 unsigned ChainIdx = NumVecs;
2128 CurDAG->RemoveDeadNode(
N);
2131void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2136 assert(Opcode != 0 &&
"Unexpected opcode");
2139 EVT VT =
N->getValueType(0);
2140 SDUse *OpsIter =
N->op_begin() + 1;
2143 auto GetMultiVecOperand = [&]() {
2146 return createZMulTuple(Regs);
2150 Ops.push_back(*OpsIter++);
2152 Ops.push_back(GetMultiVecOperand());
2154 Ops.push_back(GetMultiVecOperand());
2156 Ops.push_back(*OpsIter++);
2159 Ops.append(OpsIter,
N->op_end());
2161 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2163 for (
unsigned i = 0; i < NumVecs; ++i)
2164 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2165 AArch64::zsub0 + i,
DL, VT, SuperReg));
2167 CurDAG->RemoveDeadNode(
N);
2170void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2171 unsigned Scale,
unsigned Opc_ri,
2172 unsigned Opc_rr,
bool IsIntr) {
2173 assert(Scale < 5 &&
"Invalid scaling value.");
2175 EVT VT =
N->getValueType(0);
2182 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2183 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2189 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2191 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2193 for (
unsigned i = 0; i < NumVecs; ++i)
2194 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2195 AArch64::zsub0 + i,
DL, VT, SuperReg));
2198 unsigned ChainIdx = NumVecs;
2200 CurDAG->RemoveDeadNode(
N);
2203void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2208 assert(Scale < 4 &&
"Invalid scaling value.");
2210 EVT VT =
N->getValueType(0);
2218 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2224 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2226 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2228 for (
unsigned i = 0; i < NumVecs; ++i)
2229 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2230 AArch64::zsub0 + i,
DL, VT, SuperReg));
2233 unsigned ChainIdx = NumVecs;
2235 CurDAG->RemoveDeadNode(
N);
2238void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2240 if (
N->getValueType(0) != MVT::nxv4f32)
2242 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2245void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2246 unsigned NumOutVecs,
2250 if (
Imm->getZExtValue() > MaxImm)
2254 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2260 EVT VT =
Node->getValueType(0);
2263 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2266 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2267 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2268 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2271 unsigned ChainIdx = NumOutVecs;
2273 CurDAG->RemoveDeadNode(Node);
2276void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2277 unsigned NumIndexVecs) {
2278 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2279 "unexpected number of index vectors");
2281 constexpr unsigned FirstIndexOp = 3;
2282 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2284 if (!Imm ||
Imm->getZExtValue() > 1)
2290 unsigned Lane =
Imm->getZExtValue();
2291 unsigned IndexOp = FirstIndexOp;
2292 if (NumIndexVecs == 3)
2295 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2297 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2298 SDValue Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2301 EVT VT =
Node->getValueType(0);
2303 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2306 for (
unsigned I = 0;
I < 4; ++
I)
2307 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2308 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2310 CurDAG->RemoveDeadNode(Node);
2313void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2314 unsigned NumOutVecs,
2316 unsigned NumInVecs) {
2317 assert((NumInVecs == 2 || NumInVecs == 3) &&
2318 "unexpected number of input vectors");
2321 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2325 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2329 EVT VT =
Node->getValueType(0);
2332 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2335 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2336 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2337 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2340 CurDAG->RemoveDeadNode(Node);
2343void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2346 EVT VT =
N->getValueType(0);
2349 SDValue Zd = createZMulTuple(Regs);
2350 SDValue Zn =
N->getOperand(1 + NumVecs);
2351 SDValue Zm =
N->getOperand(2 + NumVecs);
2357 for (
unsigned i = 0; i < NumVecs; ++i)
2358 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2359 AArch64::zsub0 + i,
DL, VT, SuperReg));
2361 CurDAG->RemoveDeadNode(
N);
2391template <
unsigned MaxIdx,
unsigned Scale>
2392void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2393 unsigned BaseReg,
unsigned Op) {
2394 unsigned TileNum = 0;
2395 if (BaseReg != AArch64::ZA)
2396 TileNum =
N->getConstantOperandVal(2);
2402 if (BaseReg == AArch64::ZA)
2407 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2411 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2413 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2415 EVT VT =
N->getValueType(0);
2416 for (
unsigned I = 0;
I < NumVecs; ++
I)
2418 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2421 unsigned ChainIdx = NumVecs;
2423 CurDAG->RemoveDeadNode(
N);
2426void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2427 unsigned Op,
unsigned MaxIdx,
2428 unsigned Scale,
unsigned BaseReg) {
2433 if (BaseReg != AArch64::ZA)
2437 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2444 if (BaseReg != AArch64::ZA )
2445 Ops.push_back(
N->getOperand(2));
2448 Ops.push_back(
N->getOperand(0));
2449 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2451 EVT VT =
N->getValueType(0);
2452 for (
unsigned I = 0;
I < NumVecs; ++
I)
2454 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2458 unsigned ChainIdx = NumVecs;
2460 CurDAG->RemoveDeadNode(
N);
2463void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2464 unsigned NumOutVecs,
2468 EVT VT =
N->getValueType(0);
2469 unsigned NumInVecs =
N->getNumOperands() - 1;
2473 assert((NumInVecs == 2 || NumInVecs == 4) &&
2474 "Don't know how to handle multi-register input!");
2476 Ops.push_back(createZMulTuple(Regs));
2479 for (
unsigned I = 0;
I < NumInVecs;
I++)
2480 Ops.push_back(
N->getOperand(1 +
I));
2483 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2486 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2487 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2488 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2489 CurDAG->RemoveDeadNode(
N);
2492void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2495 EVT VT =
N->getOperand(2)->getValueType(0);
2503 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2512void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2513 unsigned Scale,
unsigned Opc_rr,
2519 SDValue RegSeq = createZTuple(Regs);
2525 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2526 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2532 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2540 const DataLayout &
DL = CurDAG->getDataLayout();
2541 const TargetLowering *TLI = getTargetLowering();
2545 int FI = FINode->getIndex();
2547 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2554void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2557 EVT VT =
N->getOperand(2)->getValueType(0);
2558 const EVT ResTys[] = {MVT::i64,
2570 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2614void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2617 EVT VT =
N->getValueType(0);
2629 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2631 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2633 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2635 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2639 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2640 AArch64::qsub2, AArch64::qsub3 };
2641 for (
unsigned i = 0; i < NumVecs; ++i) {
2642 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2649 CurDAG->RemoveDeadNode(
N);
2652void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2655 EVT VT =
N->getValueType(0);
2667 const EVT ResTys[] = {MVT::i64,
2670 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2673 CurDAG->getTargetConstant(LaneNo, dl,
2678 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2690 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2691 AArch64::qsub2, AArch64::qsub3 };
2692 for (
unsigned i = 0; i < NumVecs; ++i) {
2693 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2703 CurDAG->RemoveDeadNode(
N);
2706void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2709 EVT VT =
N->getOperand(2)->getValueType(0);
2721 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2723 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2725 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2734void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2737 EVT VT =
N->getOperand(2)->getValueType(0);
2749 const EVT ResTys[] = {MVT::i64,
2752 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2754 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2758 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2769 unsigned &LSB,
unsigned &MSB,
2770 unsigned NumberOfIgnoredLowBits,
2771 bool BiggerPattern) {
2773 "N must be a AND operation to call this function");
2775 EVT VT =
N->getValueType(0);
2780 assert((VT == MVT::i32 || VT == MVT::i64) &&
2781 "Type checking must have been done before calling this function");
2795 const SDNode *Op0 =
N->getOperand(0).getNode();
2802 if (AndImm & (AndImm + 1))
2805 bool ClampMSB =
false;
2825 ClampMSB = (VT == MVT::i32);
2826 }
else if (BiggerPattern) {
2832 Opd0 =
N->getOperand(0);
2838 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2841 <<
": Found large shift immediate, this should not happen\n"));
2855 MSB = MSB > 31 ? 31 : MSB;
2857 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2862 SDValue &Opd0,
unsigned &Immr,
2866 EVT VT =
N->getValueType(0);
2868 assert((VT == MVT::i32 || VT == MVT::i64) &&
2869 "Type checking must have been done before calling this function");
2873 Op =
Op->getOperand(0);
2874 VT =
Op->getValueType(0);
2883 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2887 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2888 Opd0 =
Op.getOperand(0);
2890 Imms = ShiftImm + Width - 1;
2918 Opd0 =
N->getOperand(0).getOperand(0);
2928 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2935 unsigned &Immr,
unsigned &Imms,
2936 bool BiggerPattern) {
2938 "N must be a SHR/SRA operation to call this function");
2940 EVT VT =
N->getValueType(0);
2945 assert((VT == MVT::i32 || VT == MVT::i64) &&
2946 "Type checking must have been done before calling this function");
2956 Opd0 =
N->getOperand(0).getOperand(0);
2957 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2963 Opd0 =
N->getOperand(0).getOperand(0);
2966 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2967 }
else if (BiggerPattern) {
2971 Opd0 =
N->getOperand(0);
2980 <<
": Found large shift immediate, this should not happen\n"));
2989 "bad amount in shift node!");
2990 int immr = SrlImm - ShlImm;
2995 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2997 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3001bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
3004 EVT VT =
N->getValueType(0);
3005 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
3006 if (VT != MVT::i64 || NarrowVT != MVT::i32)
3017 unsigned Immr = ShiftImm;
3019 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3020 CurDAG->getTargetConstant(Imms, dl, VT)};
3021 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
3026 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3027 unsigned NumberOfIgnoredLowBits = 0,
3028 bool BiggerPattern =
false) {
3029 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3032 switch (
N->getOpcode()) {
3034 if (!
N->isMachineOpcode())
3039 NumberOfIgnoredLowBits, BiggerPattern);
3048 unsigned NOpc =
N->getMachineOpcode();
3052 case AArch64::SBFMWri:
3053 case AArch64::UBFMWri:
3054 case AArch64::SBFMXri:
3055 case AArch64::UBFMXri:
3057 Opd0 =
N->getOperand(0);
3058 Immr =
N->getConstantOperandVal(1);
3059 Imms =
N->getConstantOperandVal(2);
3066bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3067 unsigned Opc, Immr, Imms;
3072 EVT VT =
N->getValueType(0);
3077 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3078 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3079 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3081 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3082 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3088 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3089 CurDAG->getTargetConstant(Imms, dl, VT)};
3090 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3099 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3100 assert((VT == MVT::i32 || VT == MVT::i64) &&
3101 "i32 or i64 mask type expected!");
3105 APInt SignificantDstMask =
3109 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3110 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3143 APInt OpUsefulBits(UsefulBits);
3147 OpUsefulBits <<= MSB - Imm + 1;
3152 OpUsefulBits <<= Imm;
3154 OpUsefulBits <<= MSB + 1;
3157 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
3163 UsefulBits &= OpUsefulBits;
3180 APInt Mask(UsefulBits);
3181 Mask.clearAllBits();
3189 Mask.lshrInPlace(ShiftAmt);
3195 Mask.lshrInPlace(ShiftAmt);
3211 APInt OpUsefulBits(UsefulBits);
3225 OpUsefulBits <<= Width;
3228 if (
Op.getOperand(1) == Orig) {
3230 Mask = ResultUsefulBits & OpUsefulBits;
3234 if (
Op.getOperand(0) == Orig)
3236 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3242 OpUsefulBits <<= Width;
3244 OpUsefulBits <<= LSB;
3246 if (
Op.getOperand(1) == Orig) {
3248 Mask = ResultUsefulBits & OpUsefulBits;
3249 Mask.lshrInPlace(LSB);
3252 if (
Op.getOperand(0) == Orig)
3253 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3270 case AArch64::ANDSWri:
3271 case AArch64::ANDSXri:
3272 case AArch64::ANDWri:
3273 case AArch64::ANDXri:
3277 case AArch64::UBFMWri:
3278 case AArch64::UBFMXri:
3281 case AArch64::ORRWrs:
3282 case AArch64::ORRXrs:
3287 case AArch64::BFMWri:
3288 case AArch64::BFMXri:
3291 case AArch64::STRBBui:
3292 case AArch64::STURBBi:
3298 case AArch64::STRHHui:
3299 case AArch64::STURHHi:
3312 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3314 UsefulBits =
APInt(Bitwidth, 0);
3323 UsersUsefulBits |= UsefulBitsForUse;
3328 UsefulBits &= UsersUsefulBits;
3338 EVT VT =
Op.getValueType();
3341 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3344 if (ShlAmount > 0) {
3347 UBFMOpc, dl, VT,
Op,
3352 assert(ShlAmount < 0 &&
"expected right shift");
3353 int ShrAmount = -ShlAmount;
3365 const uint64_t NonZeroBits,
3372 const uint64_t NonZeroBits,
3379 bool BiggerPattern,
SDValue &Src,
3380 int &DstLSB,
int &Width) {
3381 EVT VT =
Op.getValueType();
3390 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3394 switch (
Op.getOpcode()) {
3399 NonZeroBits, Src, DstLSB, Width);
3402 NonZeroBits, Src, DstLSB, Width);
3415 EVT VT =
Op.getValueType();
3416 assert((VT == MVT::i32 || VT == MVT::i64) &&
3417 "Caller guarantees VT is one of i32 or i64");
3430 assert((~AndImm & NonZeroBits) == 0 &&
3431 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3460 if (!BiggerPattern && !AndOp0.
hasOneUse())
3479 <<
"Found large Width in bit-field-positioning -- this indicates no "
3480 "proper combining / constant folding was performed\n");
3489 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3504 "Op.getNode() should be a SHL node to call this function");
3506 "Op.getNode() should shift ShlImm to call this function");
3513 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3537 EVT VT =
Op.getValueType();
3538 assert((VT == MVT::i32 || VT == MVT::i64) &&
3539 "Caller guarantees that type is i32 or i64");
3546 if (!BiggerPattern && !
Op.hasOneUse())
3555 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3563 assert(VT == MVT::i32 || VT == MVT::i64);
3574 EVT VT =
N->getValueType(0);
3575 if (VT != MVT::i32 && VT != MVT::i64)
3593 if (!
And.hasOneUse() ||
3603 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3610 if ((OrImm & NotKnownZero) != 0) {
3622 unsigned ImmS = Width - 1;
3628 bool IsBFI = LSB != 0;
3633 unsigned OrChunks = 0, BFIChunks = 0;
3634 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3635 if (((OrImm >> Shift) & 0xFFFF) != 0)
3637 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3640 if (BFIChunks > OrChunks)
3646 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3654 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3663 if (!Dst.hasOneUse())
3666 EVT VT = Dst.getValueType();
3667 assert((VT == MVT::i32 || VT == MVT::i64) &&
3668 "Caller should guarantee that VT is one of i32 or i64");
3696 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3697 unsigned MaskWidth =
3700 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3706 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3707 ShiftedOperand =
SDValue(UBFMNode, 0);
3736 const bool BiggerPattern) {
3737 EVT VT =
N->getValueType(0);
3738 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3739 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3740 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3741 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3742 assert((VT == MVT::i32 || VT == MVT::i64) &&
3743 "Expect result type to be i32 or i64 since N is combinable to BFM");
3750 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3753 if (BiggerPattern) {
3776 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3838 EVT VT =
N->getValueType(0);
3839 if (VT != MVT::i32 && VT != MVT::i64)
3847 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3848 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3868 for (
int I = 0;
I < 4; ++
I) {
3871 unsigned ImmR, ImmS;
3872 bool BiggerPattern =
I / 2;
3873 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3875 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3881 NumberOfIgnoredLowBits, BiggerPattern)) {
3884 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3885 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3890 Width = ImmS - ImmR + 1;
3901 Src, DstLSB, Width)) {
3909 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3919 APInt BitsToBeInserted =
3922 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3946 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3979 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3981 if (Src->hasOneUse() &&
3984 Src = Src->getOperand(0);
3994 unsigned ImmS = Width - 1;
4000 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4008bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4017 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4030bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4034 EVT VT =
N->getValueType(0);
4035 if (VT != MVT::i32 && VT != MVT::i64)
4041 Op0, DstLSB, Width))
4047 unsigned ImmS = Width - 1;
4050 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4051 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4052 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4053 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4059bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4060 EVT VT =
N->getValueType(0);
4063 switch (
N->getOpcode()) {
4065 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4068 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4071 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4074 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4082 if (VT == MVT::i32) {
4085 }
else if (VT == MVT::i64) {
4091 SDValue ShiftAmt =
N->getOperand(1);
4111 (Add0Imm %
Size == 0)) {
4117 if (SubVT == MVT::i32) {
4118 NegOpc = AArch64::SUBWrr;
4119 ZeroReg = AArch64::WZR;
4121 assert(SubVT == MVT::i64);
4122 NegOpc = AArch64::SUBXrr;
4123 ZeroReg = AArch64::XZR;
4126 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4127 MachineSDNode *Neg =
4128 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4129 NewShiftAmt =
SDValue(Neg, 0);
4137 if (SubVT == MVT::i32) {
4138 NotOpc = AArch64::ORNWrr;
4139 ZeroReg = AArch64::WZR;
4141 assert(SubVT == MVT::i64);
4142 NotOpc = AArch64::ORNXrr;
4143 ZeroReg = AArch64::XZR;
4146 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4147 MachineSDNode *
Not =
4148 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4149 NewShiftAmt =
SDValue(Not, 0);
4170 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4171 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4172 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4173 NewShiftAmt, SubReg);
4174 NewShiftAmt =
SDValue(Ext, 0);
4178 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4185 bool isReciprocal) {
4188 FVal = CN->getValueAPF();
4191 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4201 if (
unsigned FBits =
4214 bool isReciprocal) {
4215 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4216 N.getValueType().getScalarSizeInBits() ==
4217 N.getOperand(0).getValueType().getScalarSizeInBits())
4218 N =
N.getOperand(0);
4220 auto ImmToFloat = [RegWidth](
APInt Imm) {
4234 switch (
N->getOpcode()) {
4235 case AArch64ISD::MOVIshift:
4236 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4237 <<
N.getConstantOperandVal(1)));
4239 case AArch64ISD::FMOV:
4240 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4242 case AArch64ISD::DUP:
4244 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4252 if (
unsigned FBits =
4261bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4262 unsigned RegWidth) {
4267bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
4268 unsigned RegWidth) {
4270 CurDAG,
N, FixedPos, RegWidth,
false);
4273bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(
SDValue N,
4275 unsigned RegWidth) {
4277 CurDAG,
N, FixedPos, RegWidth,
true);
4280bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4282 unsigned RegWidth) {
4292 RegString.
split(Fields,
':');
4294 if (Fields.
size() == 1)
4298 &&
"Invalid number of fields in read register string");
4301 bool AllIntFields =
true;
4305 AllIntFields &= !
Field.getAsInteger(10, IntField);
4306 Ops.push_back(IntField);
4310 "Unexpected non-integer value in special register string.");
4315 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4323bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4325 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4328 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4330 unsigned Opcode64Bit = AArch64::MRS;
4335 const auto *TheReg =
4336 AArch64SysReg::lookupSysRegByName(RegString->getString());
4337 if (TheReg && TheReg->Readable &&
4338 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4339 Imm = TheReg->Encoding;
4345 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4346 Opcode64Bit = AArch64::ADR;
4355 RegString->getString());
4356 unsigned PseudoOp = 0;
4357 if (AArch64::GPR64RegClass.
contains(PReg))
4358 PseudoOp = AArch64::READ_REGISTER_GPR64;
4359 else if (AArch64::FPR64RegClass.
contains(PReg))
4360 PseudoOp = AArch64::READ_REGISTER_FPR64;
4361 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4362 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4363 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4372 SDValue InChain =
N->getOperand(0);
4373 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4374 if (!ReadIs128Bit) {
4375 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4376 {SysRegImm, InChain});
4378 SDNode *MRRS = CurDAG->getMachineNode(
4380 {MVT::Untyped , MVT::Other },
4381 {SysRegImm, InChain});
4385 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4387 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4393 ReplaceUses(
SDValue(
N, 2), OutChain);
4402bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4404 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4407 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4409 if (!WriteIs128Bit) {
4415 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4418 "Expected a constant integer expression.");
4419 unsigned Reg = PMapper->Encoding;
4420 uint64_t Immed =
N->getConstantOperandVal(2);
4421 CurDAG->SelectNodeTo(
4422 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4423 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4429 if (trySelectPState(
4430 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4431 AArch64::MSRpstateImm4))
4433 if (trySelectPState(
4434 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4435 AArch64::MSRpstateImm1))
4444 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4445 if (TheReg && TheReg->Writeable &&
4446 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4447 Imm = TheReg->Encoding;
4457 RegString->getString());
4458 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4459 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4460 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4461 N->getOperand(2).getValueType() == MVT::i64) {
4463 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4464 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4465 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4466 MVT::Other, {RegOp,
Copy});
4468 CurDAG->RemoveDeadNode(
N);
4476 if (!WriteIs128Bit) {
4477 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4478 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4479 N->getOperand(2), InChain);
4483 SDNode *Pair = CurDAG->getMachineNode(
4484 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4485 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4488 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4490 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4492 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4493 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4501bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4506 if (Subtarget->hasLSE())
return false;
4508 if (MemTy == MVT::i8)
4509 Opcode = AArch64::CMP_SWAP_8;
4510 else if (MemTy == MVT::i16)
4511 Opcode = AArch64::CMP_SWAP_16;
4512 else if (MemTy == MVT::i32)
4513 Opcode = AArch64::CMP_SWAP_32;
4514 else if (MemTy == MVT::i64)
4515 Opcode = AArch64::CMP_SWAP_64;
4519 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4520 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4522 SDNode *CmpSwap = CurDAG->getMachineNode(
4524 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4531 CurDAG->RemoveDeadNode(
N);
4536bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4537 SDValue &Shift,
bool Negate) {
4544 return SelectSVEAddSubImm(SDLoc(
N), Val, VT, Imm, Shift, Negate);
4547bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4556 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4563 if ((Val & ~0xff) == 0) {
4564 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4569 if ((Val & ~0xff00) == 0) {
4570 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4582bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4606 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4607 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4614 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4615 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4619 if (Val <= 65280 && Val % 256 == 0) {
4620 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4621 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4632bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4642 int32_t ImmVal, ShiftVal;
4647 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4648 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4652bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4654 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(), Imm);
4658bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4661 if (ImmVal >= -128 && ImmVal < 128) {
4662 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4668bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4670 uint64_t ImmVal = CNode->getZExtValue();
4680 ImmVal &= 0xFFFFFFFF;
4689 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4696bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4700 ImmVal = CI->getZExtValue();
4702 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4713 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4722bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4723 uint64_t
High,
bool AllowSaturation,
4726 uint64_t ImmVal = CN->getZExtValue();
4733 if (ImmVal >
High) {
4734 if (!AllowSaturation)
4739 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4746bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4760 const TargetLowering *TLI = getTargetLowering();
4763 SDValue FiOp = CurDAG->getTargetFrameIndex(
4765 int TagOffset =
N->getConstantOperandVal(3);
4767 SDNode *Out = CurDAG->getMachineNode(
4768 AArch64::TAGPstack,
DL, MVT::i64,
4769 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4770 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4771 ReplaceNode(
N, Out);
4775void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4777 "llvm.aarch64.tagp third argument must be an immediate");
4778 if (trySelectStackSlotTagP(
N))
4785 int TagOffset =
N->getConstantOperandVal(3);
4786 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4787 {
N->getOperand(1),
N->getOperand(2)});
4788 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4789 {
SDValue(N1, 0),
N->getOperand(2)});
4790 SDNode *N3 = CurDAG->getMachineNode(
4791 AArch64::ADDG,
DL, MVT::i64,
4792 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4793 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4797bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4801 if (
N->getConstantOperandVal(2) != 0)
4803 if (!
N->getOperand(0).isUndef())
4807 EVT VT =
N->getValueType(0);
4808 EVT InVT =
N->getOperand(1).getValueType();
4819 "Expected to insert into a packed scalable vector!");
4822 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4823 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4824 N->getOperand(1), RC));
4828bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4832 if (
N->getConstantOperandVal(1) != 0)
4836 EVT VT =
N->getValueType(0);
4837 EVT InVT =
N->getOperand(0).getValueType();
4848 "Expected to extract from a packed scalable vector!");
4851 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4852 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4853 N->getOperand(0), RC));
4857bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4863 EVT VT =
N->getValueType(0);
4876 (Subtarget->hasSVE2() ||
4877 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4878 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4881 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4885 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4886 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4887 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4894 bool IsXOROperand =
true;
4896 IsXOROperand =
false;
4902 APInt ShlAmt, ShrAmt;
4910 if (!IsXOROperand) {
4912 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4915 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4916 SDNode *SubRegToReg =
4917 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
4928 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4929 AArch64::XAR_ZZZI_D})) {
4930 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4955 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4965 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4973 bool IsXOROperand =
true;
4975 IsXOROperand =
false;
4978 R1 =
XOR.getOperand(0);
4979 R2 =
XOR.getOperand(1);
4989 if (ShAmt + HsAmt != VTSizeInBits)
4992 if (!IsXOROperand) {
4995 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5004 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5010 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5011 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5013 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5016 if (
R2.getValueType() == VT)
5017 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5022 SDValue SubReg = CurDAG->getTargetConstant(
5025 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5030 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5036 SDNode *XAR =
nullptr;
5040 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5041 AArch64::XAR_ZZZI_D}))
5042 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5044 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5047 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5053 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5054 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5057 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5058 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5061 SDValue SubReg = CurDAG->getTargetConstant(
5064 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5068 ReplaceNode(
N, XAR);
5075 assert(VT == MVT::i32 || VT == MVT::i64);
5077 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5080void AArch64DAGToDAGISel::Select(SDNode *Node) {
5082 if (
Node->isMachineOpcode()) {
5084 Node->setNodeId(-1);
5089 EVT VT =
Node->getValueType(0);
5091 switch (
Node->getOpcode()) {
5096 if (SelectCMP_SWAP(Node))
5101 case AArch64ISD::MRRS:
5102 if (tryReadRegister(Node))
5107 case AArch64ISD::MSRR:
5108 if (tryWriteRegister(Node))
5115 if (tryIndexedLoad(Node))
5124 if (tryBitfieldExtractOp(Node))
5126 if (tryBitfieldInsertInZeroOp(Node))
5131 if (tryShiftAmountMod(Node))
5136 if (tryBitfieldExtractOpFromSExt(Node))
5141 if (tryBitfieldInsertOp(Node))
5143 if (trySelectXAR(Node))
5148 if (trySelectCastScalableToFixedLengthVector(Node))
5154 if (trySelectCastFixedLengthToScalableVector(Node))
5163 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5174 const TargetLowering *TLI = getTargetLowering();
5175 SDValue TFI = CurDAG->getTargetFrameIndex(
5178 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5179 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5180 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5184 unsigned IntNo =
Node->getConstantOperandVal(1);
5188 case Intrinsic::aarch64_gcsss: {
5192 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5194 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5195 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5196 MVT::Other, Zero,
SDValue(SS1, 0));
5197 ReplaceNode(Node, SS2);
5200 case Intrinsic::aarch64_ldaxp:
5201 case Intrinsic::aarch64_ldxp: {
5203 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5208 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5209 MVT::Other, MemAddr, Chain);
5212 MachineMemOperand *MemOp =
5215 ReplaceNode(Node, Ld);
5218 case Intrinsic::aarch64_stlxp:
5219 case Intrinsic::aarch64_stxp: {
5221 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5229 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5231 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5233 MachineMemOperand *MemOp =
5237 ReplaceNode(Node, St);
5240 case Intrinsic::aarch64_neon_ld1x2:
5241 if (VT == MVT::v8i8) {
5242 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5244 }
else if (VT == MVT::v16i8) {
5245 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5247 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5248 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5250 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5251 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5253 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5254 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5256 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5257 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5259 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5260 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5262 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5263 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5267 case Intrinsic::aarch64_neon_ld1x3:
5268 if (VT == MVT::v8i8) {
5269 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5271 }
else if (VT == MVT::v16i8) {
5272 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5274 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5275 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5277 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5278 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5280 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5281 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5283 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5284 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5286 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5287 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5289 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5290 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5294 case Intrinsic::aarch64_neon_ld1x4:
5295 if (VT == MVT::v8i8) {
5296 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5298 }
else if (VT == MVT::v16i8) {
5299 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5301 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5302 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5304 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5305 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5307 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5308 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5310 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5311 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5313 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5314 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5316 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5317 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5321 case Intrinsic::aarch64_neon_ld2:
5322 if (VT == MVT::v8i8) {
5323 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5325 }
else if (VT == MVT::v16i8) {
5326 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5328 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5329 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5331 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5332 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5334 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5335 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5337 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5338 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5340 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5341 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5343 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5344 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5348 case Intrinsic::aarch64_neon_ld3:
5349 if (VT == MVT::v8i8) {
5350 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5352 }
else if (VT == MVT::v16i8) {
5353 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5355 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5356 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5358 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5359 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5361 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5362 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5364 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5365 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5367 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5368 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5370 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5371 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5375 case Intrinsic::aarch64_neon_ld4:
5376 if (VT == MVT::v8i8) {
5377 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5379 }
else if (VT == MVT::v16i8) {
5380 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5382 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5383 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5385 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5386 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5388 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5389 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5391 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5392 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5394 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5395 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5397 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5398 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5402 case Intrinsic::aarch64_neon_ld2r:
5403 if (VT == MVT::v8i8) {
5404 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5406 }
else if (VT == MVT::v16i8) {
5407 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5409 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5410 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5412 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5413 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5415 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5416 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5418 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5419 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5421 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5422 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5424 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5425 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5429 case Intrinsic::aarch64_neon_ld3r:
5430 if (VT == MVT::v8i8) {
5431 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5433 }
else if (VT == MVT::v16i8) {
5434 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5436 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5437 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5439 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5440 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5442 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5443 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5445 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5446 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5448 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5449 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5451 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5452 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5456 case Intrinsic::aarch64_neon_ld4r:
5457 if (VT == MVT::v8i8) {
5458 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5460 }
else if (VT == MVT::v16i8) {
5461 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5463 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5464 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5466 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5467 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5469 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5470 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5472 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5473 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5475 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5476 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5478 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5479 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5483 case Intrinsic::aarch64_neon_ld2lane:
5484 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5485 SelectLoadLane(Node, 2, AArch64::LD2i8);
5487 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5488 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5489 SelectLoadLane(Node, 2, AArch64::LD2i16);
5491 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5493 SelectLoadLane(Node, 2, AArch64::LD2i32);
5495 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5497 SelectLoadLane(Node, 2, AArch64::LD2i64);
5501 case Intrinsic::aarch64_neon_ld3lane:
5502 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5503 SelectLoadLane(Node, 3, AArch64::LD3i8);
5505 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5506 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5507 SelectLoadLane(Node, 3, AArch64::LD3i16);
5509 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5511 SelectLoadLane(Node, 3, AArch64::LD3i32);
5513 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5515 SelectLoadLane(Node, 3, AArch64::LD3i64);
5519 case Intrinsic::aarch64_neon_ld4lane:
5520 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5521 SelectLoadLane(Node, 4, AArch64::LD4i8);
5523 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5524 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5525 SelectLoadLane(Node, 4, AArch64::LD4i16);
5527 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5529 SelectLoadLane(Node, 4, AArch64::LD4i32);
5531 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5533 SelectLoadLane(Node, 4, AArch64::LD4i64);
5537 case Intrinsic::aarch64_ld64b:
5538 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5540 case Intrinsic::aarch64_sve_ld2q_sret: {
5541 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5544 case Intrinsic::aarch64_sve_ld3q_sret: {
5545 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5548 case Intrinsic::aarch64_sve_ld4q_sret: {
5549 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5552 case Intrinsic::aarch64_sve_ld2_sret: {
5553 if (VT == MVT::nxv16i8) {
5554 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5557 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5558 VT == MVT::nxv8bf16) {
5559 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5562 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5563 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5566 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5567 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5573 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5574 if (VT == MVT::nxv16i8) {
5575 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5576 SelectContiguousMultiVectorLoad(
5577 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5578 else if (Subtarget->hasSVE2p1())
5579 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5584 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5585 VT == MVT::nxv8bf16) {
5586 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5587 SelectContiguousMultiVectorLoad(
5588 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5589 else if (Subtarget->hasSVE2p1())
5590 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5595 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5596 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5597 SelectContiguousMultiVectorLoad(
5598 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5599 else if (Subtarget->hasSVE2p1())
5600 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5605 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5606 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5607 SelectContiguousMultiVectorLoad(
5608 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5609 else if (Subtarget->hasSVE2p1())
5610 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5618 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5619 if (VT == MVT::nxv16i8) {
5620 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5621 SelectContiguousMultiVectorLoad(
5622 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5623 else if (Subtarget->hasSVE2p1())
5624 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5629 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5630 VT == MVT::nxv8bf16) {
5631 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5632 SelectContiguousMultiVectorLoad(
5633 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5634 else if (Subtarget->hasSVE2p1())
5635 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5640 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5641 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5642 SelectContiguousMultiVectorLoad(
5643 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5644 else if (Subtarget->hasSVE2p1())
5645 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5650 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5651 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5652 SelectContiguousMultiVectorLoad(
5653 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5654 else if (Subtarget->hasSVE2p1())
5655 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5663 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5664 if (VT == MVT::nxv16i8) {
5665 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5666 SelectContiguousMultiVectorLoad(Node, 2, 0,
5667 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5668 AArch64::LDNT1B_2Z_PSEUDO);
5669 else if (Subtarget->hasSVE2p1())
5670 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5671 AArch64::LDNT1B_2Z);
5675 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5676 VT == MVT::nxv8bf16) {
5677 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5678 SelectContiguousMultiVectorLoad(Node, 2, 1,
5679 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5680 AArch64::LDNT1H_2Z_PSEUDO);
5681 else if (Subtarget->hasSVE2p1())
5682 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5683 AArch64::LDNT1H_2Z);
5687 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5688 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5689 SelectContiguousMultiVectorLoad(Node, 2, 2,
5690 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5691 AArch64::LDNT1W_2Z_PSEUDO);
5692 else if (Subtarget->hasSVE2p1())
5693 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5694 AArch64::LDNT1W_2Z);
5698 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5699 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5700 SelectContiguousMultiVectorLoad(Node, 2, 3,
5701 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5702 AArch64::LDNT1D_2Z_PSEUDO);
5703 else if (Subtarget->hasSVE2p1())
5704 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5705 AArch64::LDNT1D_2Z);
5712 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5713 if (VT == MVT::nxv16i8) {
5714 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5715 SelectContiguousMultiVectorLoad(Node, 4, 0,
5716 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5717 AArch64::LDNT1B_4Z_PSEUDO);
5718 else if (Subtarget->hasSVE2p1())
5719 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5720 AArch64::LDNT1B_4Z);
5724 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5725 VT == MVT::nxv8bf16) {
5726 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5727 SelectContiguousMultiVectorLoad(Node, 4, 1,
5728 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5729 AArch64::LDNT1H_4Z_PSEUDO);
5730 else if (Subtarget->hasSVE2p1())
5731 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5732 AArch64::LDNT1H_4Z);
5736 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5737 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5738 SelectContiguousMultiVectorLoad(Node, 4, 2,
5739 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5740 AArch64::LDNT1W_4Z_PSEUDO);
5741 else if (Subtarget->hasSVE2p1())
5742 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5743 AArch64::LDNT1W_4Z);
5747 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5748 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5749 SelectContiguousMultiVectorLoad(Node, 4, 3,
5750 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5751 AArch64::LDNT1D_4Z_PSEUDO);
5752 else if (Subtarget->hasSVE2p1())
5753 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5754 AArch64::LDNT1D_4Z);
5761 case Intrinsic::aarch64_sve_ld3_sret: {
5762 if (VT == MVT::nxv16i8) {
5763 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5766 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5767 VT == MVT::nxv8bf16) {
5768 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5771 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5772 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5775 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5776 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5782 case Intrinsic::aarch64_sve_ld4_sret: {
5783 if (VT == MVT::nxv16i8) {
5784 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5787 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5788 VT == MVT::nxv8bf16) {
5789 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5792 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5793 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5796 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5797 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5803 case Intrinsic::aarch64_sme_read_hor_vg2: {
5804 if (VT == MVT::nxv16i8) {
5805 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5806 AArch64::MOVA_2ZMXI_H_B);
5808 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5809 VT == MVT::nxv8bf16) {
5810 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5811 AArch64::MOVA_2ZMXI_H_H);
5813 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5814 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5815 AArch64::MOVA_2ZMXI_H_S);
5817 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5818 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5819 AArch64::MOVA_2ZMXI_H_D);
5824 case Intrinsic::aarch64_sme_read_ver_vg2: {
5825 if (VT == MVT::nxv16i8) {
5826 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5827 AArch64::MOVA_2ZMXI_V_B);
5829 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5830 VT == MVT::nxv8bf16) {
5831 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5832 AArch64::MOVA_2ZMXI_V_H);
5834 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5835 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5836 AArch64::MOVA_2ZMXI_V_S);
5838 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5839 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5840 AArch64::MOVA_2ZMXI_V_D);
5845 case Intrinsic::aarch64_sme_read_hor_vg4: {
5846 if (VT == MVT::nxv16i8) {
5847 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5848 AArch64::MOVA_4ZMXI_H_B);
5850 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5851 VT == MVT::nxv8bf16) {
5852 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5853 AArch64::MOVA_4ZMXI_H_H);
5855 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5856 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5857 AArch64::MOVA_4ZMXI_H_S);
5859 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5860 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5861 AArch64::MOVA_4ZMXI_H_D);
5866 case Intrinsic::aarch64_sme_read_ver_vg4: {
5867 if (VT == MVT::nxv16i8) {
5868 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5869 AArch64::MOVA_4ZMXI_V_B);
5871 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5872 VT == MVT::nxv8bf16) {
5873 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5874 AArch64::MOVA_4ZMXI_V_H);
5876 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5877 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5878 AArch64::MOVA_4ZMXI_V_S);
5880 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5881 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5882 AArch64::MOVA_4ZMXI_V_D);
5887 case Intrinsic::aarch64_sme_read_vg1x2: {
5888 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5889 AArch64::MOVA_VG2_2ZMXI);
5892 case Intrinsic::aarch64_sme_read_vg1x4: {
5893 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5894 AArch64::MOVA_VG4_4ZMXI);
5897 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5898 if (VT == MVT::nxv16i8) {
5899 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5901 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5902 VT == MVT::nxv8bf16) {
5903 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5905 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5906 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5908 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5909 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5914 case Intrinsic::aarch64_sme_readz_vert_x2: {
5915 if (VT == MVT::nxv16i8) {
5916 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5918 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5919 VT == MVT::nxv8bf16) {
5920 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5922 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5923 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5925 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5926 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5931 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5932 if (VT == MVT::nxv16i8) {
5933 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5935 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5936 VT == MVT::nxv8bf16) {
5937 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5939 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5940 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5942 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5943 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5948 case Intrinsic::aarch64_sme_readz_vert_x4: {
5949 if (VT == MVT::nxv16i8) {
5950 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5952 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5953 VT == MVT::nxv8bf16) {
5954 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5956 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5957 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5959 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5960 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5965 case Intrinsic::aarch64_sme_readz_x2: {
5966 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5970 case Intrinsic::aarch64_sme_readz_x4: {
5971 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5975 case Intrinsic::swift_async_context_addr: {
5978 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5980 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5981 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5982 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5984 ReplaceUses(
SDValue(Node, 0), Res);
5986 CurDAG->RemoveDeadNode(Node);
5988 auto &MF = CurDAG->getMachineFunction();
5989 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5990 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5993 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5995 Node->getValueType(0),
5996 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5997 AArch64::LUTI2_4ZTZI_S}))
5999 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6002 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6004 Node->getValueType(0),
6005 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6007 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6010 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6012 Node->getValueType(0),
6013 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6014 AArch64::LUTI2_2ZTZI_S}))
6016 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6019 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6021 Node->getValueType(0),
6022 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6023 AArch64::LUTI4_2ZTZI_S}))
6025 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6028 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6029 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6032 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6033 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6036 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6038 Node->getValueType(0),
6039 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6040 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6042 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6044 Node->getValueType(0),
6045 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6046 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6048 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6050 Node->getValueType(0),
6051 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6052 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6054 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6056 Node->getValueType(0),
6057 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6058 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6060 case Intrinsic::ptrauth_resign_load_relative:
6061 SelectPtrauthResign(Node);
6066 unsigned IntNo =
Node->getConstantOperandVal(0);
6070 case Intrinsic::aarch64_tagp:
6074 case Intrinsic::ptrauth_auth:
6075 SelectPtrauthAuth(Node);
6078 case Intrinsic::ptrauth_resign:
6079 SelectPtrauthResign(Node);
6082 case Intrinsic::aarch64_neon_tbl2:
6083 SelectTable(Node, 2,
6084 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6087 case Intrinsic::aarch64_neon_tbl3:
6088 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6089 : AArch64::TBLv16i8Three,
6092 case Intrinsic::aarch64_neon_tbl4:
6093 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6094 : AArch64::TBLv16i8Four,
6097 case Intrinsic::aarch64_neon_tbx2:
6098 SelectTable(Node, 2,
6099 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6102 case Intrinsic::aarch64_neon_tbx3:
6103 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6104 : AArch64::TBXv16i8Three,
6107 case Intrinsic::aarch64_neon_tbx4:
6108 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6109 : AArch64::TBXv16i8Four,
6112 case Intrinsic::aarch64_sve_srshl_single_x2:
6114 Node->getValueType(0),
6115 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6116 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6117 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6119 case Intrinsic::aarch64_sve_srshl_single_x4:
6121 Node->getValueType(0),
6122 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6123 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6124 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6126 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6127 SelectMultiVectorLuti6LaneX4(Node, 2);
6129 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6130 SelectMultiVectorLuti6LaneX4(Node, 3);
6132 case Intrinsic::aarch64_sve_urshl_single_x2:
6134 Node->getValueType(0),
6135 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6136 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6137 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6139 case Intrinsic::aarch64_sve_urshl_single_x4:
6141 Node->getValueType(0),
6142 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6143 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6144 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6146 case Intrinsic::aarch64_sve_srshl_x2:
6148 Node->getValueType(0),
6149 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6150 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6151 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6153 case Intrinsic::aarch64_sve_srshl_x4:
6155 Node->getValueType(0),
6156 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6157 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6158 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6160 case Intrinsic::aarch64_sve_urshl_x2:
6162 Node->getValueType(0),
6163 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6164 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6165 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6167 case Intrinsic::aarch64_sve_urshl_x4:
6169 Node->getValueType(0),
6170 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6171 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6172 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6174 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6176 Node->getValueType(0),
6177 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6178 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6179 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6181 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6183 Node->getValueType(0),
6184 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6185 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6186 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6188 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6190 Node->getValueType(0),
6191 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6192 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6193 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6195 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6197 Node->getValueType(0),
6198 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6199 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6200 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6202 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6204 Node->getValueType(0),
6205 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6206 AArch64::FSCALE_2ZZ_D}))
6207 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6209 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6211 Node->getValueType(0),
6212 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6213 AArch64::FSCALE_4ZZ_D}))
6214 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6216 case Intrinsic::aarch64_sme_fp8_scale_x2:
6218 Node->getValueType(0),
6219 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6220 AArch64::FSCALE_2Z2Z_D}))
6221 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6223 case Intrinsic::aarch64_sme_fp8_scale_x4:
6225 Node->getValueType(0),
6226 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6227 AArch64::FSCALE_4Z4Z_D}))
6228 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6230 case Intrinsic::aarch64_sve_whilege_x2:
6232 Node->getValueType(0),
6233 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6234 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6235 SelectWhilePair(Node,
Op);
6237 case Intrinsic::aarch64_sve_whilegt_x2:
6239 Node->getValueType(0),
6240 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6241 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6242 SelectWhilePair(Node,
Op);
6244 case Intrinsic::aarch64_sve_whilehi_x2:
6246 Node->getValueType(0),
6247 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6248 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6249 SelectWhilePair(Node,
Op);
6251 case Intrinsic::aarch64_sve_whilehs_x2:
6253 Node->getValueType(0),
6254 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6255 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6256 SelectWhilePair(Node,
Op);
6258 case Intrinsic::aarch64_sve_whilele_x2:
6260 Node->getValueType(0),
6261 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6262 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6263 SelectWhilePair(Node,
Op);
6265 case Intrinsic::aarch64_sve_whilelo_x2:
6267 Node->getValueType(0),
6268 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6269 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6270 SelectWhilePair(Node,
Op);
6272 case Intrinsic::aarch64_sve_whilels_x2:
6274 Node->getValueType(0),
6275 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6276 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6277 SelectWhilePair(Node,
Op);
6279 case Intrinsic::aarch64_sve_whilelt_x2:
6281 Node->getValueType(0),
6282 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6283 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6284 SelectWhilePair(Node,
Op);
6286 case Intrinsic::aarch64_sve_smax_single_x2:
6288 Node->getValueType(0),
6289 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6290 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6293 case Intrinsic::aarch64_sve_umax_single_x2:
6295 Node->getValueType(0),
6296 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6297 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6298 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6300 case Intrinsic::aarch64_sve_fmax_single_x2:
6302 Node->getValueType(0),
6303 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6304 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6305 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6307 case Intrinsic::aarch64_sve_smax_single_x4:
6309 Node->getValueType(0),
6310 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6311 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6312 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6314 case Intrinsic::aarch64_sve_umax_single_x4:
6316 Node->getValueType(0),
6317 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6318 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6319 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6321 case Intrinsic::aarch64_sve_fmax_single_x4:
6323 Node->getValueType(0),
6324 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6325 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6326 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6328 case Intrinsic::aarch64_sve_smin_single_x2:
6330 Node->getValueType(0),
6331 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6332 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6333 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6335 case Intrinsic::aarch64_sve_umin_single_x2:
6337 Node->getValueType(0),
6338 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6339 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6340 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6342 case Intrinsic::aarch64_sve_fmin_single_x2:
6344 Node->getValueType(0),
6345 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6346 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6347 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6349 case Intrinsic::aarch64_sve_smin_single_x4:
6351 Node->getValueType(0),
6352 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6353 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6354 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6356 case Intrinsic::aarch64_sve_umin_single_x4:
6358 Node->getValueType(0),
6359 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6360 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6361 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6363 case Intrinsic::aarch64_sve_fmin_single_x4:
6365 Node->getValueType(0),
6366 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6367 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6368 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6370 case Intrinsic::aarch64_sve_smax_x2:
6372 Node->getValueType(0),
6373 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6374 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6375 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6377 case Intrinsic::aarch64_sve_umax_x2:
6379 Node->getValueType(0),
6380 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6381 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6382 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6384 case Intrinsic::aarch64_sve_fmax_x2:
6386 Node->getValueType(0),
6387 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6388 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6389 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6391 case Intrinsic::aarch64_sve_smax_x4:
6393 Node->getValueType(0),
6394 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6395 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6396 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6398 case Intrinsic::aarch64_sve_umax_x4:
6400 Node->getValueType(0),
6401 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6402 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6403 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6405 case Intrinsic::aarch64_sve_fmax_x4:
6407 Node->getValueType(0),
6408 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6409 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6410 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6412 case Intrinsic::aarch64_sme_famax_x2:
6414 Node->getValueType(0),
6415 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6416 AArch64::FAMAX_2Z2Z_D}))
6417 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6419 case Intrinsic::aarch64_sme_famax_x4:
6421 Node->getValueType(0),
6422 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6423 AArch64::FAMAX_4Z4Z_D}))
6424 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6426 case Intrinsic::aarch64_sme_famin_x2:
6428 Node->getValueType(0),
6429 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6430 AArch64::FAMIN_2Z2Z_D}))
6431 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6433 case Intrinsic::aarch64_sme_famin_x4:
6435 Node->getValueType(0),
6436 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6437 AArch64::FAMIN_4Z4Z_D}))
6438 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6440 case Intrinsic::aarch64_sve_smin_x2:
6442 Node->getValueType(0),
6443 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6444 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6445 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6447 case Intrinsic::aarch64_sve_umin_x2:
6449 Node->getValueType(0),
6450 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6451 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6452 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6454 case Intrinsic::aarch64_sve_fmin_x2:
6456 Node->getValueType(0),
6457 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6458 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6459 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6461 case Intrinsic::aarch64_sve_smin_x4:
6463 Node->getValueType(0),
6464 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6465 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6466 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6468 case Intrinsic::aarch64_sve_umin_x4:
6470 Node->getValueType(0),
6471 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6472 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6473 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6475 case Intrinsic::aarch64_sve_fmin_x4:
6477 Node->getValueType(0),
6478 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6479 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6480 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6482 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6484 Node->getValueType(0),
6485 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6486 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6487 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6489 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6491 Node->getValueType(0),
6492 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6493 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6494 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6496 case Intrinsic::aarch64_sve_fminnm_single_x2:
6498 Node->getValueType(0),
6499 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6500 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6501 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6503 case Intrinsic::aarch64_sve_fminnm_single_x4:
6505 Node->getValueType(0),
6506 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6507 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6508 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6510 case Intrinsic::aarch64_sve_fscale_single_x4:
6511 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6513 case Intrinsic::aarch64_sve_fscale_single_x2:
6514 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6516 case Intrinsic::aarch64_sve_fmul_single_x4:
6518 Node->getValueType(0),
6519 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6520 AArch64::FMUL_4ZZ_D}))
6521 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6523 case Intrinsic::aarch64_sve_fmul_single_x2:
6525 Node->getValueType(0),
6526 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6527 AArch64::FMUL_2ZZ_D}))
6528 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6530 case Intrinsic::aarch64_sve_fmaxnm_x2:
6532 Node->getValueType(0),
6533 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6534 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6535 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6537 case Intrinsic::aarch64_sve_fmaxnm_x4:
6539 Node->getValueType(0),
6540 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6541 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6542 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6544 case Intrinsic::aarch64_sve_fminnm_x2:
6546 Node->getValueType(0),
6547 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6548 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6549 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6551 case Intrinsic::aarch64_sve_fminnm_x4:
6553 Node->getValueType(0),
6554 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6555 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6556 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6558 case Intrinsic::aarch64_sve_aese_lane_x2:
6559 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6561 case Intrinsic::aarch64_sve_aesd_lane_x2:
6562 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6564 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6565 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6567 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6568 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6570 case Intrinsic::aarch64_sve_aese_lane_x4:
6571 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6573 case Intrinsic::aarch64_sve_aesd_lane_x4:
6574 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6576 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6577 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6579 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6580 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6582 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6583 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6585 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6589 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6591 for (
unsigned I = 0;
I < 2;
I++)
6593 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6595 CurDAG->RemoveDeadNode(Node);
6598 case Intrinsic::aarch64_sve_fscale_x4:
6599 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6601 case Intrinsic::aarch64_sve_fscale_x2:
6602 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6604 case Intrinsic::aarch64_sve_fmul_x4:
6606 Node->getValueType(0),
6607 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6608 AArch64::FMUL_4Z4Z_D}))
6609 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6611 case Intrinsic::aarch64_sve_fmul_x2:
6613 Node->getValueType(0),
6614 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6615 AArch64::FMUL_2Z2Z_D}))
6616 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6618 case Intrinsic::aarch64_sve_fcvtzs_x2:
6619 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6621 case Intrinsic::aarch64_sve_scvtf_x2:
6622 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6624 case Intrinsic::aarch64_sve_fcvtzu_x2:
6625 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6627 case Intrinsic::aarch64_sve_ucvtf_x2:
6628 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6630 case Intrinsic::aarch64_sve_fcvtzs_x4:
6631 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6633 case Intrinsic::aarch64_sve_scvtf_x4:
6634 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6636 case Intrinsic::aarch64_sve_fcvtzu_x4:
6637 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6639 case Intrinsic::aarch64_sve_ucvtf_x4:
6640 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6642 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6643 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6645 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6646 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6648 case Intrinsic::aarch64_sve_sclamp_single_x2:
6650 Node->getValueType(0),
6651 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6652 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6653 SelectClamp(Node, 2,
Op);
6655 case Intrinsic::aarch64_sve_uclamp_single_x2:
6657 Node->getValueType(0),
6658 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6659 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6660 SelectClamp(Node, 2,
Op);
6662 case Intrinsic::aarch64_sve_fclamp_single_x2:
6664 Node->getValueType(0),
6665 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6666 AArch64::FCLAMP_VG2_2Z2Z_D}))
6667 SelectClamp(Node, 2,
Op);
6669 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6670 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6672 case Intrinsic::aarch64_sve_sclamp_single_x4:
6674 Node->getValueType(0),
6675 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6676 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6677 SelectClamp(Node, 4,
Op);
6679 case Intrinsic::aarch64_sve_uclamp_single_x4:
6681 Node->getValueType(0),
6682 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6683 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6684 SelectClamp(Node, 4,
Op);
6686 case Intrinsic::aarch64_sve_fclamp_single_x4:
6688 Node->getValueType(0),
6689 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6690 AArch64::FCLAMP_VG4_4Z4Z_D}))
6691 SelectClamp(Node, 4,
Op);
6693 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6694 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6696 case Intrinsic::aarch64_sve_add_single_x2:
6698 Node->getValueType(0),
6699 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6700 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6701 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6703 case Intrinsic::aarch64_sve_add_single_x4:
6705 Node->getValueType(0),
6706 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6707 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6708 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6710 case Intrinsic::aarch64_sve_zip_x2:
6712 Node->getValueType(0),
6713 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6714 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6715 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6717 case Intrinsic::aarch64_sve_zipq_x2:
6718 SelectUnaryMultiIntrinsic(Node, 2,
false,
6719 AArch64::ZIP_VG2_2ZZZ_Q);
6721 case Intrinsic::aarch64_sve_zip_x4:
6723 Node->getValueType(0),
6724 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6725 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6726 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6728 case Intrinsic::aarch64_sve_zipq_x4:
6729 SelectUnaryMultiIntrinsic(Node, 4,
true,
6730 AArch64::ZIP_VG4_4Z4Z_Q);
6732 case Intrinsic::aarch64_sve_uzp_x2:
6734 Node->getValueType(0),
6735 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6736 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6737 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6739 case Intrinsic::aarch64_sve_uzpq_x2:
6740 SelectUnaryMultiIntrinsic(Node, 2,
false,
6741 AArch64::UZP_VG2_2ZZZ_Q);
6743 case Intrinsic::aarch64_sve_uzp_x4:
6745 Node->getValueType(0),
6746 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6747 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6748 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6750 case Intrinsic::aarch64_sve_uzpq_x4:
6751 SelectUnaryMultiIntrinsic(Node, 4,
true,
6752 AArch64::UZP_VG4_4Z4Z_Q);
6754 case Intrinsic::aarch64_sve_sel_x2:
6756 Node->getValueType(0),
6757 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6758 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6759 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6761 case Intrinsic::aarch64_sve_sel_x4:
6763 Node->getValueType(0),
6764 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6765 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6766 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6768 case Intrinsic::aarch64_sve_frinta_x2:
6769 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6771 case Intrinsic::aarch64_sve_frinta_x4:
6772 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6774 case Intrinsic::aarch64_sve_frintm_x2:
6775 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6777 case Intrinsic::aarch64_sve_frintm_x4:
6778 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6780 case Intrinsic::aarch64_sve_frintn_x2:
6781 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6783 case Intrinsic::aarch64_sve_frintn_x4:
6784 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6786 case Intrinsic::aarch64_sve_frintp_x2:
6787 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6789 case Intrinsic::aarch64_sve_frintp_x4:
6790 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6792 case Intrinsic::aarch64_sve_sunpk_x2:
6794 Node->getValueType(0),
6795 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6796 AArch64::SUNPK_VG2_2ZZ_D}))
6797 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6799 case Intrinsic::aarch64_sve_uunpk_x2:
6801 Node->getValueType(0),
6802 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6803 AArch64::UUNPK_VG2_2ZZ_D}))
6804 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6806 case Intrinsic::aarch64_sve_sunpk_x4:
6808 Node->getValueType(0),
6809 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6810 AArch64::SUNPK_VG4_4Z2Z_D}))
6811 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6813 case Intrinsic::aarch64_sve_uunpk_x4:
6815 Node->getValueType(0),
6816 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6817 AArch64::UUNPK_VG4_4Z2Z_D}))
6818 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6820 case Intrinsic::aarch64_sve_pext_x2: {
6822 Node->getValueType(0),
6823 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6824 AArch64::PEXT_2PCI_D}))
6825 SelectPExtPair(Node,
Op);
6832 unsigned IntNo =
Node->getConstantOperandVal(1);
6833 if (
Node->getNumOperands() >= 3)
6834 VT =
Node->getOperand(2)->getValueType(0);
6838 case Intrinsic::aarch64_neon_st1x2: {
6839 if (VT == MVT::v8i8) {
6840 SelectStore(Node, 2, AArch64::ST1Twov8b);
6842 }
else if (VT == MVT::v16i8) {
6843 SelectStore(Node, 2, AArch64::ST1Twov16b);
6845 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6846 VT == MVT::v4bf16) {
6847 SelectStore(Node, 2, AArch64::ST1Twov4h);
6849 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6850 VT == MVT::v8bf16) {
6851 SelectStore(Node, 2, AArch64::ST1Twov8h);
6853 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6854 SelectStore(Node, 2, AArch64::ST1Twov2s);
6856 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6857 SelectStore(Node, 2, AArch64::ST1Twov4s);
6859 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6860 SelectStore(Node, 2, AArch64::ST1Twov2d);
6862 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6863 SelectStore(Node, 2, AArch64::ST1Twov1d);
6868 case Intrinsic::aarch64_neon_st1x3: {
6869 if (VT == MVT::v8i8) {
6870 SelectStore(Node, 3, AArch64::ST1Threev8b);
6872 }
else if (VT == MVT::v16i8) {
6873 SelectStore(Node, 3, AArch64::ST1Threev16b);
6875 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6876 VT == MVT::v4bf16) {
6877 SelectStore(Node, 3, AArch64::ST1Threev4h);
6879 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6880 VT == MVT::v8bf16) {
6881 SelectStore(Node, 3, AArch64::ST1Threev8h);
6883 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6884 SelectStore(Node, 3, AArch64::ST1Threev2s);
6886 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6887 SelectStore(Node, 3, AArch64::ST1Threev4s);
6889 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6890 SelectStore(Node, 3, AArch64::ST1Threev2d);
6892 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6893 SelectStore(Node, 3, AArch64::ST1Threev1d);
6898 case Intrinsic::aarch64_neon_st1x4: {
6899 if (VT == MVT::v8i8) {
6900 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6902 }
else if (VT == MVT::v16i8) {
6903 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6905 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6906 VT == MVT::v4bf16) {
6907 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6909 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6910 VT == MVT::v8bf16) {
6911 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6913 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6914 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6916 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6917 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6919 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6920 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6922 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6923 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6928 case Intrinsic::aarch64_neon_st2: {
6929 if (VT == MVT::v8i8) {
6930 SelectStore(Node, 2, AArch64::ST2Twov8b);
6932 }
else if (VT == MVT::v16i8) {
6933 SelectStore(Node, 2, AArch64::ST2Twov16b);
6935 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6936 VT == MVT::v4bf16) {
6937 SelectStore(Node, 2, AArch64::ST2Twov4h);
6939 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6940 VT == MVT::v8bf16) {
6941 SelectStore(Node, 2, AArch64::ST2Twov8h);
6943 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6944 SelectStore(Node, 2, AArch64::ST2Twov2s);
6946 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6947 SelectStore(Node, 2, AArch64::ST2Twov4s);
6949 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6950 SelectStore(Node, 2, AArch64::ST2Twov2d);
6952 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6953 SelectStore(Node, 2, AArch64::ST1Twov1d);
6958 case Intrinsic::aarch64_neon_st3: {
6959 if (VT == MVT::v8i8) {
6960 SelectStore(Node, 3, AArch64::ST3Threev8b);
6962 }
else if (VT == MVT::v16i8) {
6963 SelectStore(Node, 3, AArch64::ST3Threev16b);
6965 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6966 VT == MVT::v4bf16) {
6967 SelectStore(Node, 3, AArch64::ST3Threev4h);
6969 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6970 VT == MVT::v8bf16) {
6971 SelectStore(Node, 3, AArch64::ST3Threev8h);
6973 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6974 SelectStore(Node, 3, AArch64::ST3Threev2s);
6976 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6977 SelectStore(Node, 3, AArch64::ST3Threev4s);
6979 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6980 SelectStore(Node, 3, AArch64::ST3Threev2d);
6982 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6983 SelectStore(Node, 3, AArch64::ST1Threev1d);
6988 case Intrinsic::aarch64_neon_st4: {
6989 if (VT == MVT::v8i8) {
6990 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6992 }
else if (VT == MVT::v16i8) {
6993 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6995 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6996 VT == MVT::v4bf16) {
6997 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6999 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7000 VT == MVT::v8bf16) {
7001 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7003 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7004 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7006 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7007 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7009 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7010 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7012 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7013 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7018 case Intrinsic::aarch64_neon_st2lane: {
7019 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7020 SelectStoreLane(Node, 2, AArch64::ST2i8);
7022 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7023 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7024 SelectStoreLane(Node, 2, AArch64::ST2i16);
7026 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7028 SelectStoreLane(Node, 2, AArch64::ST2i32);
7030 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7032 SelectStoreLane(Node, 2, AArch64::ST2i64);
7037 case Intrinsic::aarch64_neon_st3lane: {
7038 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7039 SelectStoreLane(Node, 3, AArch64::ST3i8);
7041 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7042 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7043 SelectStoreLane(Node, 3, AArch64::ST3i16);
7045 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7047 SelectStoreLane(Node, 3, AArch64::ST3i32);
7049 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7051 SelectStoreLane(Node, 3, AArch64::ST3i64);
7056 case Intrinsic::aarch64_neon_st4lane: {
7057 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7058 SelectStoreLane(Node, 4, AArch64::ST4i8);
7060 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7061 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7062 SelectStoreLane(Node, 4, AArch64::ST4i16);
7064 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7066 SelectStoreLane(Node, 4, AArch64::ST4i32);
7068 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7070 SelectStoreLane(Node, 4, AArch64::ST4i64);
7075 case Intrinsic::aarch64_sve_st2q: {
7076 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7079 case Intrinsic::aarch64_sve_st3q: {
7080 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7083 case Intrinsic::aarch64_sve_st4q: {
7084 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7087 case Intrinsic::aarch64_sve_st2: {
7088 if (VT == MVT::nxv16i8) {
7089 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7091 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7092 VT == MVT::nxv8bf16) {
7093 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7095 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7096 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7098 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7099 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7104 case Intrinsic::aarch64_sve_st3: {
7105 if (VT == MVT::nxv16i8) {
7106 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7108 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7109 VT == MVT::nxv8bf16) {
7110 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7112 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7113 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7115 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7116 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7121 case Intrinsic::aarch64_sve_st4: {
7122 if (VT == MVT::nxv16i8) {
7123 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7125 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7126 VT == MVT::nxv8bf16) {
7127 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7129 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7130 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7132 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7133 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7141 case AArch64ISD::LD2post: {
7142 if (VT == MVT::v8i8) {
7143 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7145 }
else if (VT == MVT::v16i8) {
7146 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7148 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7149 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7151 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7152 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7154 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7155 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7157 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7158 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7160 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7161 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7163 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7164 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7169 case AArch64ISD::LD3post: {
7170 if (VT == MVT::v8i8) {
7171 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7173 }
else if (VT == MVT::v16i8) {
7174 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7176 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7177 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7179 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7180 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7182 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7183 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7185 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7186 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7188 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7189 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7191 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7192 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7197 case AArch64ISD::LD4post: {
7198 if (VT == MVT::v8i8) {
7199 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7201 }
else if (VT == MVT::v16i8) {
7202 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7204 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7205 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7207 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7208 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7210 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7211 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7213 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7214 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7216 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7217 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7219 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7220 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7225 case AArch64ISD::LD1x2post: {
7226 if (VT == MVT::v8i8) {
7227 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7229 }
else if (VT == MVT::v16i8) {
7230 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7232 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7233 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7235 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7236 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7238 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7239 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7241 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7242 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7244 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7245 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7247 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7248 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7253 case AArch64ISD::LD1x3post: {
7254 if (VT == MVT::v8i8) {
7255 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7257 }
else if (VT == MVT::v16i8) {
7258 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7260 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7261 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7263 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7264 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7266 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7267 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7269 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7270 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7272 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7273 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7275 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7276 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7281 case AArch64ISD::LD1x4post: {
7282 if (VT == MVT::v8i8) {
7283 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7285 }
else if (VT == MVT::v16i8) {
7286 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7288 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7289 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7291 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7292 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7294 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7295 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7297 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7298 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7300 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7301 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7303 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7304 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7309 case AArch64ISD::LD1DUPpost: {
7310 if (VT == MVT::v8i8) {
7311 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7313 }
else if (VT == MVT::v16i8) {
7314 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7316 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7317 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7319 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7320 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7322 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7323 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7325 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7326 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7328 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7329 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7331 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7332 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7337 case AArch64ISD::LD2DUPpost: {
7338 if (VT == MVT::v8i8) {
7339 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7341 }
else if (VT == MVT::v16i8) {
7342 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7344 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7345 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7347 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7348 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7350 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7351 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7353 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7354 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7356 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7357 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7359 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7360 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7365 case AArch64ISD::LD3DUPpost: {
7366 if (VT == MVT::v8i8) {
7367 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7369 }
else if (VT == MVT::v16i8) {
7370 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7372 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7373 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7375 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7376 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7378 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7379 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7381 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7382 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7384 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7385 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7387 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7388 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7393 case AArch64ISD::LD4DUPpost: {
7394 if (VT == MVT::v8i8) {
7395 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7397 }
else if (VT == MVT::v16i8) {
7398 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7400 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7401 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7403 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7404 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7406 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7407 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7409 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7410 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7412 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7413 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7415 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7416 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7421 case AArch64ISD::LD1LANEpost: {
7422 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7423 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7425 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7426 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7427 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7429 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7431 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7433 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7435 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7440 case AArch64ISD::LD2LANEpost: {
7441 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7442 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7444 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7445 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7446 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7448 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7450 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7452 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7454 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7459 case AArch64ISD::LD3LANEpost: {
7460 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7461 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7463 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7464 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7465 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7467 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7469 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7471 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7473 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7478 case AArch64ISD::LD4LANEpost: {
7479 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7480 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7482 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7483 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7484 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7486 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7488 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7490 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7492 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7497 case AArch64ISD::ST2post: {
7498 VT =
Node->getOperand(1).getValueType();
7499 if (VT == MVT::v8i8) {
7500 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7502 }
else if (VT == MVT::v16i8) {
7503 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7505 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7506 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7508 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7509 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7511 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7512 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7514 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7515 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7517 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7518 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7520 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7521 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7526 case AArch64ISD::ST3post: {
7527 VT =
Node->getOperand(1).getValueType();
7528 if (VT == MVT::v8i8) {
7529 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7531 }
else if (VT == MVT::v16i8) {
7532 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7534 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7535 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7537 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7538 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7540 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7541 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7543 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7544 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7546 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7547 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7549 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7550 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7555 case AArch64ISD::ST4post: {
7556 VT =
Node->getOperand(1).getValueType();
7557 if (VT == MVT::v8i8) {
7558 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7560 }
else if (VT == MVT::v16i8) {
7561 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7563 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7564 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7566 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7567 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7569 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7570 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7572 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7573 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7575 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7576 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7578 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7579 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7584 case AArch64ISD::ST1x2post: {
7585 VT =
Node->getOperand(1).getValueType();
7586 if (VT == MVT::v8i8) {
7587 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7589 }
else if (VT == MVT::v16i8) {
7590 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7592 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7593 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7595 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7596 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7598 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7599 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7601 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7602 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7604 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7605 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7607 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7608 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7613 case AArch64ISD::ST1x3post: {
7614 VT =
Node->getOperand(1).getValueType();
7615 if (VT == MVT::v8i8) {
7616 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7618 }
else if (VT == MVT::v16i8) {
7619 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7621 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7622 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7624 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7625 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7627 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7628 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7630 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7631 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7633 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7634 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7636 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7637 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7642 case AArch64ISD::ST1x4post: {
7643 VT =
Node->getOperand(1).getValueType();
7644 if (VT == MVT::v8i8) {
7645 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7647 }
else if (VT == MVT::v16i8) {
7648 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7650 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7651 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7653 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7654 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7656 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7657 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7659 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7660 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7662 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7663 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7665 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7666 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7671 case AArch64ISD::ST2LANEpost: {
7672 VT =
Node->getOperand(1).getValueType();
7673 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7674 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7676 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7677 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7678 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7680 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7682 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7684 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7686 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7691 case AArch64ISD::ST3LANEpost: {
7692 VT =
Node->getOperand(1).getValueType();
7693 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7694 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7696 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7697 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7698 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7700 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7702 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7704 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7706 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7711 case AArch64ISD::ST4LANEpost: {
7712 VT =
Node->getOperand(1).getValueType();
7713 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7714 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7716 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7717 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7718 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7720 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7722 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7724 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7726 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7741 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7753 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7757 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7758 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7780 return MemIntr->getMemoryVT();
7787 DataVT = Load->getValueType(0);
7789 DataVT = Load->getValueType(0);
7791 DataVT = Store->getValue().getValueType();
7793 DataVT = Store->getValue().getValueType();
7800 const unsigned Opcode = Root->
getOpcode();
7804 case AArch64ISD::LD1_MERGE_ZERO:
7805 case AArch64ISD::LD1S_MERGE_ZERO:
7806 case AArch64ISD::LDNF1_MERGE_ZERO:
7807 case AArch64ISD::LDNF1S_MERGE_ZERO:
7809 case AArch64ISD::ST1_PRED:
7821 case Intrinsic::aarch64_sme_ldr:
7822 case Intrinsic::aarch64_sme_str:
7823 return MVT::nxv16i8;
7824 case Intrinsic::aarch64_sve_prf:
7829 case Intrinsic::aarch64_sve_ld2_sret:
7830 case Intrinsic::aarch64_sve_ld2q_sret:
7833 case Intrinsic::aarch64_sve_st2q:
7836 case Intrinsic::aarch64_sve_ld3_sret:
7837 case Intrinsic::aarch64_sve_ld3q_sret:
7840 case Intrinsic::aarch64_sve_st3q:
7843 case Intrinsic::aarch64_sve_ld4_sret:
7844 case Intrinsic::aarch64_sve_ld4q_sret:
7847 case Intrinsic::aarch64_sve_st4q:
7850 case Intrinsic::aarch64_sve_ld1_pn_x2:
7851 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7854 case Intrinsic::aarch64_sve_ld1_pn_x4:
7855 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7858 case Intrinsic::aarch64_sve_st1_pn_x2:
7859 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7862 case Intrinsic::aarch64_sve_st1_pn_x4:
7863 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7866 case Intrinsic::aarch64_sve_ld1udq:
7867 case Intrinsic::aarch64_sve_st1dq:
7868 return EVT(MVT::nxv1i64);
7869 case Intrinsic::aarch64_sve_ld1uwq:
7870 case Intrinsic::aarch64_sve_st1wq:
7871 return EVT(MVT::nxv1i32);
7878template <
int64_t Min,
int64_t Max>
7879bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7883 const DataLayout &
DL = CurDAG->getDataLayout();
7884 const MachineFrameInfo &MFI = MF->getFrameInfo();
7892 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7906 int64_t MulImm = std::numeric_limits<int64_t>::max();
7910 int64_t ByteOffset =
C->getSExtValue();
7911 const auto KnownVScale =
7914 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7917 MulImm = ByteOffset / KnownVScale;
7924 if ((MulImm % MemWidthBytes) != 0)
7927 int64_t
Offset = MulImm / MemWidthBytes;
7931 Base =
N.getOperand(0);
7940 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7946bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7965 int64_t ImmOff =
C->getSExtValue();
7966 unsigned Size = 1 << Scale;
7975 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7977 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7988 if (
C->getZExtValue() == Scale) {
7997bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7998 const AArch64TargetLowering *TLI =
7999 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8004bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
8005 return N.getValueType().isScalableVectorOf(MVT::i1);
8008bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
8013 int64_t ImmOff =
C->getSExtValue();
8014 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8015 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8020 if (
SDValue C = MatchConstantOffset(
N)) {
8027 if (CurDAG->isBaseWithConstantOffset(
N)) {
8028 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
8029 Base =
N.getOperand(0);
8037 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8041bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
8061 uint64_t LowerBound = 0, UpperBound = 64;
8079 if (CN->getAPIntValue().uge(LowerBound) &&
8080 CN->getAPIntValue().ult(UpperBound)) {
8082 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8090template <
bool MatchCBB>
8097 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8099 Reg =
N.getOperand(0);
8101 SDLoc(
N), MVT::i32);
8109 Reg =
N.getOperand(0);
8129SDValue AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode &
N) {
8130 EVT VT =
N.getValueType(0);
8141 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8150 unsigned CondCode = CC->getZExtValue();
8153 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8155 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8156 else if (VT == MVT::f32)
8157 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8158 else if (VT == MVT::f64)
8159 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8167 if (TVal == CmpLHS && FVal == CmpRHS)
8172 if (TVal == CmpLHS && FVal == CmpRHS)
8181 unsigned Opc = getOpc(VT, isMax);
8187 if (!CFP || CFP->getValueAPF().isNaN())
8192 if (CFP->isZero() && !
N.getFlags().hasNoSignedZeros())
8198 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8204 return SDValue(CurDAG->getMachineNode(
Opc,
DL, VT, CmpLHS, CmpRHS), 0);
8207void AArch64DAGToDAGISel::PreprocessISelDAG() {
8208 bool MadeChange =
false;
8214 switch (
N.getOpcode()) {
8216 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8217 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8218 ScalarTy ==
N.getOperand(0).getValueType())
8223 case AArch64ISD::CSEL:
8224 Result = tryFoldCselToFMaxMin(
N);
8231 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8237 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(&
N, 0), Result);
8243 CurDAG->RemoveDeadNodes();
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 std::optional< APInt > GetNEONSplatValue(SDValue N)
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 SDValue addBitcastHints(SelectionDAG &DAG, SDNode &N)
addBitcastHints - This method adds bitcast hints to the operands of a node to help instruction select...
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 std::optional< APInt > DecodeNEONSplat(SDValue N)
static bool checkCVTFixedPointOperandWithFBitsForVectors(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static SDValue getZeroRegister(SelectionDAG &DAG, SDLoc DL, EVT VT)
Returns a copy from WZR or XZR.
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 APInt DecodeFMOVImm(uint64_t Imm, unsigned RegWidth)
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 EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec)
Builds an integer vector type large enough to hold NumVec instances of VecVT.
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!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
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
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64RegisterInfo * getRegisterInfo() const override
const AArch64TargetLowering * getTargetLowering() 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(const SelectionDAG &DAG, SDValue N) const
Register matchRegisterName(StringRef RegName) const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static const fltSemantics & IEEEhalf()
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.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
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
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
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 getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
LLVM Value Representation.
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 uint64_t decodeAdvSIMDModImmType12(uint8_t Imm)
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static uint64_t decodeAdvSIMDModImmType11(uint8_t Imm)
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static uint64_t decodeAdvSIMDModImmType10(uint8_t Imm)
static bool isSVELogicalImm(unsigned SizeInBits, uint64_t ImmVal, uint64_t &Encoding)
constexpr unsigned getArithImmedShift(const uint64_t C)
getArithImmedShift - assumes C is a legal immediate for arithmetic instructions and
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 bool isSignExtendShiftType(AArch64_AM::ShiftExtendType Type)
isSignExtendShiftType - Returns true if Type is sign extending.
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.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ 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...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ 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.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
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.
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Undef
Value of the register doesn't matter.
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.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
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.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
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.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
unsigned getBitWidth() const
Get the bit width of this value.