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,
419 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc);
421 template <
unsigned MaxIdx,
unsigned Scale>
426 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
427 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
428 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
429 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
430 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
431 unsigned Opc_rr,
unsigned Opc_ri);
432 std::tuple<unsigned, SDValue, SDValue>
433 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
437 bool tryBitfieldExtractOp(
SDNode *
N);
438 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
439 bool tryBitfieldInsertOp(
SDNode *
N);
440 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
441 bool tryShiftAmountMod(
SDNode *
N);
443 bool tryReadRegister(
SDNode *
N);
444 bool tryWriteRegister(
SDNode *
N);
446 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
447 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
454#include "AArch64GenDAGISel.inc"
462 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
464 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
477 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
478 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
479 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
482 template<
unsigned RegW
idth>
484 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
486 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
488 template <
unsigned RegW
idth>
490 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
492 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
494 template<
unsigned RegW
idth>
496 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
502 template <
unsigned FloatW
idth>
504 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
510 bool SelectCMP_SWAP(
SDNode *
N);
529 bool AllowSaturation,
SDValue &Imm);
537 bool SelectAllActivePredicate(
SDValue N);
542 template <
bool MatchCBB>
552 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
556char AArch64DAGToDAGISelLegacy::ID = 0;
562 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
568 auto getFloatVT = [&](
EVT VT) {
570 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
571 return VT.changeElementType(*(DAG.
getContext()),
572 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
577 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
578 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
582 EVT OrigVT =
N.getValueType(0);
591 Imm =
C->getZExtValue();
608 return N->getOpcode() ==
Opc &&
619 return Imm == ImmExpected;
624 assert(RegWidth == 32 || RegWidth == 64);
626 return APInt(RegWidth,
633 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
634 if (
N->getOpcode() == AArch64ISD::NVCAST)
635 N =
N->getOperand(0);
636 unsigned SplatWidth =
N.getScalarValueSizeInBits();
637 if (
N.getOpcode() == AArch64ISD::FMOV)
639 if (
N->getOpcode() == AArch64ISD::MOVI)
640 return APInt(SplatWidth,
N.getConstantOperandVal(0));
641 if (
N->getOpcode() == AArch64ISD::MOVIshift)
642 return APInt(SplatWidth,
N.getConstantOperandVal(0)
643 <<
N.getConstantOperandVal(1));
644 if (
N->getOpcode() == AArch64ISD::MVNIshift)
645 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
646 <<
N.getConstantOperandVal(1));
647 if (
N->getOpcode() == AArch64ISD::MOVIedit)
649 N.getConstantOperandVal(0)));
650 if (
N->getOpcode() == AArch64ISD::DUP)
652 return Const->getAPIntValue().trunc(SplatWidth);
661 unsigned SplatWidth =
N.getScalarValueSizeInBits();
663 if (SplatVal->getBitWidth() <= SplatWidth)
665 if (SplatVal->isSplat(SplatWidth))
666 return SplatVal->trunc(SplatWidth);
671bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
678 ImmVal->getZExtValue(), Encoding))
681 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
685bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(
SDValue N,
SDValue &Imm,
688 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
689 N.getValueType().getScalarType().getSimpleVT(),
695bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(
SDValue N,
698 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal, Imm);
702bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
704 std::vector<SDValue> &OutOps) {
705 switch(ConstraintID) {
708 case InlineAsm::ConstraintCode::m:
709 case InlineAsm::ConstraintCode::o:
710 case InlineAsm::ConstraintCode::Q:
714 const TargetRegisterClass *TRC =
TRI->getPointerRegClass();
716 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
718 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
719 dl,
Op.getValueType(),
721 OutOps.push_back(NewOp);
740 uint64_t Immed =
N.getNode()->getAsZExtVal();
750 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
751 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
768 uint64_t Immed =
N.getNode()->getAsZExtVal();
776 if (
N.getValueType() == MVT::i32)
777 Immed = ~((uint32_t)Immed) + 1;
779 Immed = ~Immed + 1ULL;
780 if (Immed & 0xFFFFFFFFFF000000ULL)
783 Immed &= 0xFFFFFFULL;
784 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
791 switch (
N.getOpcode()) {
817 unsigned ShiftVal = CSD->getZExtValue();
835bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
838 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
843 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
867 EVT VT =
N.getValueType();
868 if (VT != MVT::i32 && VT != MVT::i64)
871 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
877 unsigned LHSOpcode =
LHS->getOpcode();
891 unsigned LowZBits, MaskLen;
895 unsigned BitWidth =
N.getValueSizeInBits();
902 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
905 NewShiftC = LowZBits - ShiftAmtC;
906 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
912 NewShiftC = LowZBits + ShiftAmtC;
925 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
927 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
931 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
933 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
934 NewShiftAmt, BitWidthMinus1),
937 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
951 SrcVT =
N.getOperand(0).getValueType();
953 if (!IsLoadStore && SrcVT == MVT::i8)
955 else if (!IsLoadStore && SrcVT == MVT::i16)
957 else if (SrcVT == MVT::i32)
959 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
964 EVT SrcVT =
N.getOperand(0).getValueType();
965 if (!IsLoadStore && SrcVT == MVT::i8)
967 else if (!IsLoadStore && SrcVT == MVT::i16)
969 else if (SrcVT == MVT::i32)
971 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
999bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
1002 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1007 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1008 V.getConstantOperandVal(1) <= 4 &&
1021bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
1023 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1033 unsigned BitSize =
N.getValueSizeInBits();
1034 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1037 Reg =
N.getOperand(0);
1038 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1039 return isWorthFoldingALU(
N,
true);
1050 if (
N.getValueType() == MVT::i32)
1058template<
signed Low,
signed High,
signed Scale>
1064 if ((MulImm % std::abs(Scale)) == 0) {
1065 int64_t RDVLImm = MulImm / Scale;
1066 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1067 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1076template <
signed Low,
signed High>
1077bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
1082 if (MulImm >=
Low && MulImm <=
High) {
1083 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1094 unsigned ShiftVal = 0;
1109 Reg =
N.getOperand(0).getOperand(0);
1121 Op =
Op->getOperand(0);
1123 Op.getOperand(0).getValueType().isFixedLengthVector())
1127 Reg =
N.getOperand(0);
1132 unsigned Opc =
N.getOpcode();
1150 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1152 return isWorthFoldingALU(
N);
1159 unsigned ShiftVal = 0;
1173 Reg =
N.getOperand(0);
1174 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1176 return isWorthFoldingALU(
N);
1185 for (
auto *
User :
N->users()) {
1212bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1213 unsigned BW,
unsigned Size,
1217 const DataLayout &
DL = CurDAG->getDataLayout();
1218 const TargetLowering *TLI = getTargetLowering();
1222 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1228 if (CurDAG->isBaseWithConstantOffset(
N)) {
1231 int64_t RHSC =
RHS->getSExtValue();
1233 int64_t
Range = 0x1LL << (BW - 1);
1235 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1236 RHSC < (
Range << Scale)) {
1237 Base =
N.getOperand(0);
1242 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1247 uint64_t RHSC =
RHS->getZExtValue();
1249 uint64_t
Range = 0x1ULL << BW;
1251 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1252 Base =
N.getOperand(0);
1257 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1268 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1275bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1278 const DataLayout &
DL = CurDAG->getDataLayout();
1279 const TargetLowering *TLI = getTargetLowering();
1283 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1288 GlobalAddressSDNode *GAN =
1290 Base =
N.getOperand(0);
1300 if (CurDAG->isBaseWithConstantOffset(
N)) {
1302 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1305 Base =
N.getOperand(0);
1310 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1318 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1326 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1335bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1338 if (!CurDAG->isBaseWithConstantOffset(
N))
1341 int64_t RHSC =
RHS->getSExtValue();
1342 if (RHSC >= -256 && RHSC < 256) {
1343 Base =
N.getOperand(0);
1346 const TargetLowering *TLI = getTargetLowering();
1347 Base = CurDAG->getTargetFrameIndex(
1350 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1360 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1367bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1387 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1393 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1396 return isWorthFoldingAddr(
N,
Size);
1399bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1417 const SDNode *
Node =
N.getNode();
1418 for (SDNode *UI :
Node->users()) {
1424 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1427 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1430 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1435 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1438 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1443 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1447 if (IsExtendedRegisterWorthFolding &&
1454 if (isWorthFoldingAddr(
LHS,
Size))
1459 if (IsExtendedRegisterWorthFolding &&
1466 if (isWorthFoldingAddr(
RHS,
Size))
1478 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1481 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1483 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1484 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1488bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1501 const SDNode *
Node =
N.getNode();
1502 for (SDNode *UI :
Node->users()) {
1519 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1529 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1536 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1539 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1542 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1547 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1550 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1557 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1558 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1564 static const unsigned RegClassIDs[] = {
1565 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1566 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1567 AArch64::dsub2, AArch64::dsub3};
1573 static const unsigned RegClassIDs[] = {
1574 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1575 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1576 AArch64::qsub2, AArch64::qsub3};
1582 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1583 AArch64::ZPR3RegClassID,
1584 AArch64::ZPR4RegClassID};
1585 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1586 AArch64::zsub2, AArch64::zsub3};
1596 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1597 AArch64::ZPR4Mul4RegClassID};
1598 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1599 AArch64::zsub2, AArch64::zsub3};
1604 const unsigned RegClassIDs[],
1605 const unsigned SubRegs[]) {
1608 if (Regs.
size() == 1)
1619 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1622 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1623 Ops.push_back(Regs[i]);
1624 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1628 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1632void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1635 EVT VT =
N->getValueType(0);
1637 unsigned ExtOff = isExt;
1640 unsigned Vec0Off = ExtOff + 1;
1646 Ops.push_back(
N->getOperand(1));
1647 Ops.push_back(RegSeq);
1648 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1649 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1652static std::tuple<SDValue, SDValue>
1673 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1678 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1680 return std::make_tuple(
1685void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1690 SDValue AUTDisc =
N->getOperand(3);
1693 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1695 SDValue AUTAddrDisc, AUTConstDisc;
1696 std::tie(AUTConstDisc, AUTAddrDisc) =
1700 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1702 if (
N->getNumOperands() > 4)
1703 Ops.push_back(
N->getOperand(4));
1706 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1707 ReplaceNode(
N, AUT);
1709 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1710 AArch64::X16, Val,
SDValue());
1713 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1714 ReplaceNode(
N, AUT);
1718void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1728 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1733 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1734 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1736 SDValue AUTAddrDisc, AUTConstDisc;
1737 std::tie(AUTConstDisc, AUTAddrDisc) =
1740 SDValue PACAddrDisc, PACConstDisc;
1741 std::tie(PACConstDisc, PACAddrDisc) =
1744 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1745 AArch64::X16, Val,
SDValue());
1748 SDValue Addend =
N->getOperand(OffsetBase + 6);
1749 SDValue IncomingChain =
N->getOperand(0);
1750 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1751 PACKey, PACConstDisc, PACAddrDisc,
1752 Addend, IncomingChain, X16Copy.
getValue(1)};
1754 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1755 MVT::i64, MVT::Other,
Ops);
1756 ReplaceNode(
N, AUTRELLOADPAC);
1758 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1759 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1761 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1762 ReplaceNode(
N, AUTPAC);
1766bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1768 if (
LD->isUnindexed())
1770 EVT VT =
LD->getMemoryVT();
1771 EVT DstVT =
N->getValueType(0);
1775 int OffsetVal = (int)
OffsetOp->getZExtValue();
1780 unsigned Opcode = 0;
1783 bool InsertTo64 =
false;
1785 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1786 else if (VT == MVT::i32) {
1788 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1790 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1792 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1798 }
else if (VT == MVT::i16) {
1800 if (DstVT == MVT::i64)
1801 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1803 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1805 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1806 InsertTo64 = DstVT == MVT::i64;
1811 }
else if (VT == MVT::i8) {
1813 if (DstVT == MVT::i64)
1814 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1816 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1818 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1819 InsertTo64 = DstVT == MVT::i64;
1824 }
else if (VT == MVT::f16) {
1825 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1826 }
else if (VT == MVT::bf16) {
1827 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1828 }
else if (VT == MVT::f32) {
1829 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1830 }
else if (VT == MVT::f64 ||
1832 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1834 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1836 if (IsPre || OffsetVal != 8)
1840 Opcode = AArch64::LD1Onev8b_POST;
1843 Opcode = AArch64::LD1Onev4h_POST;
1846 Opcode = AArch64::LD1Onev2s_POST;
1849 Opcode = AArch64::LD1Onev1d_POST;
1855 if (IsPre || OffsetVal != 16)
1859 Opcode = AArch64::LD1Onev16b_POST;
1862 Opcode = AArch64::LD1Onev8h_POST;
1865 Opcode = AArch64::LD1Onev4s_POST;
1868 Opcode = AArch64::LD1Onev2d_POST;
1880 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1881 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1883 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1893 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1894 LoadedVal =
SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
1895 MVT::i64, LoadedVal, SubReg),
1899 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1902 CurDAG->RemoveDeadNode(
N);
1906void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1907 unsigned SubRegIdx) {
1909 EVT VT =
N->getValueType(0);
1915 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
1917 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1919 for (
unsigned i = 0; i < NumVecs; ++i)
1921 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1928 MachineMemOperand *MemOp = MemIntr->getMemOperand();
1932 CurDAG->RemoveDeadNode(
N);
1935void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
1936 unsigned Opc,
unsigned SubRegIdx) {
1938 EVT VT =
N->getValueType(0);
1945 const EVT ResTys[] = {MVT::i64,
1946 MVT::Untyped, MVT::Other};
1948 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
1956 ReplaceUses(
SDValue(
N, 0), SuperReg);
1958 for (
unsigned i = 0; i < NumVecs; ++i)
1960 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
1968 CurDAG->RemoveDeadNode(
N);
1974std::tuple<unsigned, SDValue, SDValue>
1975AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
1981 SDValue NewOffset = OldOffset;
1983 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
1984 N, OldBase, NewBase, NewOffset);
1988 const bool IsRegReg =
1989 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
1992 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2005template <SelectTypeKind Kind>
2017 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2022 if (EltVT != MVT::i1)
2026 if (EltVT == MVT::bf16)
2028 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2058void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2061 if (
Imm->getZExtValue() > 1)
2065 EVT VT =
N->getValueType(0);
2067 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2070 for (
unsigned I = 0;
I < 2; ++
I)
2071 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2072 AArch64::psub0 +
I,
DL, VT, SuperReg));
2074 CurDAG->RemoveDeadNode(
N);
2077void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2079 EVT VT =
N->getValueType(0);
2083 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2086 for (
unsigned I = 0;
I < 2; ++
I)
2087 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2088 AArch64::psub0 +
I,
DL, VT, SuperReg));
2090 CurDAG->RemoveDeadNode(
N);
2093void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2095 EVT VT =
N->getValueType(0);
2099 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2101 for (
unsigned i = 0; i < NumVecs; ++i)
2102 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2103 AArch64::zsub0 + i,
DL, VT, SuperReg));
2105 CurDAG->RemoveDeadNode(
N);
2108void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2111 EVT VT =
N->getValueType(0);
2113 Ops.push_back(
N->getOperand(0));
2116 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2119 for (
unsigned i = 0; i < NumVecs; ++i)
2120 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2121 AArch64::zsub0 + i,
DL, VT, SuperReg));
2124 unsigned ChainIdx = NumVecs;
2126 CurDAG->RemoveDeadNode(
N);
2129void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2134 assert(Opcode != 0 &&
"Unexpected opcode");
2137 EVT VT =
N->getValueType(0);
2138 SDUse *OpsIter =
N->op_begin() + 1;
2141 auto GetMultiVecOperand = [&]() {
2144 return createZMulTuple(Regs);
2148 Ops.push_back(*OpsIter++);
2150 Ops.push_back(GetMultiVecOperand());
2152 Ops.push_back(GetMultiVecOperand());
2154 Ops.push_back(*OpsIter++);
2157 Ops.append(OpsIter,
N->op_end());
2159 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2161 for (
unsigned i = 0; i < NumVecs; ++i)
2162 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2163 AArch64::zsub0 + i,
DL, VT, SuperReg));
2165 CurDAG->RemoveDeadNode(
N);
2168void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2169 unsigned Scale,
unsigned Opc_ri,
2170 unsigned Opc_rr,
bool IsIntr) {
2171 assert(Scale < 5 &&
"Invalid scaling value.");
2173 EVT VT =
N->getValueType(0);
2180 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2181 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2187 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2189 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2191 for (
unsigned i = 0; i < NumVecs; ++i)
2192 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2193 AArch64::zsub0 + i,
DL, VT, SuperReg));
2196 unsigned ChainIdx = NumVecs;
2198 CurDAG->RemoveDeadNode(
N);
2201void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2206 assert(Scale < 4 &&
"Invalid scaling value.");
2208 EVT VT =
N->getValueType(0);
2216 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2222 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2224 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2226 for (
unsigned i = 0; i < NumVecs; ++i)
2227 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2228 AArch64::zsub0 + i,
DL, VT, SuperReg));
2231 unsigned ChainIdx = NumVecs;
2233 CurDAG->RemoveDeadNode(
N);
2236void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2238 if (
N->getValueType(0) != MVT::nxv4f32)
2240 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2243void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2244 unsigned NumOutVecs,
2248 if (
Imm->getZExtValue() > MaxImm)
2252 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2258 EVT VT =
Node->getValueType(0);
2261 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2264 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2265 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2266 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2269 unsigned ChainIdx = NumOutVecs;
2271 CurDAG->RemoveDeadNode(Node);
2274void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2275 unsigned NumOutVecs,
2278 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2283 createZMulTuple({
Node->getOperand(3),
Node->getOperand(4)}),
2287 EVT VT =
Node->getValueType(0);
2290 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2293 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2294 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2295 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2298 unsigned ChainIdx = NumOutVecs;
2300 CurDAG->RemoveDeadNode(Node);
2303void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2306 EVT VT =
N->getValueType(0);
2309 SDValue Zd = createZMulTuple(Regs);
2310 SDValue Zn =
N->getOperand(1 + NumVecs);
2311 SDValue Zm =
N->getOperand(2 + NumVecs);
2317 for (
unsigned i = 0; i < NumVecs; ++i)
2318 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2319 AArch64::zsub0 + i,
DL, VT, SuperReg));
2321 CurDAG->RemoveDeadNode(
N);
2351template <
unsigned MaxIdx,
unsigned Scale>
2352void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2353 unsigned BaseReg,
unsigned Op) {
2354 unsigned TileNum = 0;
2355 if (BaseReg != AArch64::ZA)
2356 TileNum =
N->getConstantOperandVal(2);
2362 if (BaseReg == AArch64::ZA)
2367 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2371 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2373 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2375 EVT VT =
N->getValueType(0);
2376 for (
unsigned I = 0;
I < NumVecs; ++
I)
2378 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2381 unsigned ChainIdx = NumVecs;
2383 CurDAG->RemoveDeadNode(
N);
2386void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2387 unsigned Op,
unsigned MaxIdx,
2388 unsigned Scale,
unsigned BaseReg) {
2393 if (BaseReg != AArch64::ZA)
2397 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2404 if (BaseReg != AArch64::ZA )
2405 Ops.push_back(
N->getOperand(2));
2408 Ops.push_back(
N->getOperand(0));
2409 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2411 EVT VT =
N->getValueType(0);
2412 for (
unsigned I = 0;
I < NumVecs; ++
I)
2414 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2418 unsigned ChainIdx = NumVecs;
2420 CurDAG->RemoveDeadNode(
N);
2423void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2424 unsigned NumOutVecs,
2428 EVT VT =
N->getValueType(0);
2429 unsigned NumInVecs =
N->getNumOperands() - 1;
2433 assert((NumInVecs == 2 || NumInVecs == 4) &&
2434 "Don't know how to handle multi-register input!");
2436 Ops.push_back(createZMulTuple(Regs));
2439 for (
unsigned I = 0;
I < NumInVecs;
I++)
2440 Ops.push_back(
N->getOperand(1 +
I));
2443 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2446 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2447 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2448 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2449 CurDAG->RemoveDeadNode(
N);
2452void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2455 EVT VT =
N->getOperand(2)->getValueType(0);
2463 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2472void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2473 unsigned Scale,
unsigned Opc_rr,
2479 SDValue RegSeq = createZTuple(Regs);
2485 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2486 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2492 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2500 const DataLayout &
DL = CurDAG->getDataLayout();
2501 const TargetLowering *TLI = getTargetLowering();
2505 int FI = FINode->getIndex();
2507 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
2514void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2517 EVT VT =
N->getOperand(2)->getValueType(0);
2518 const EVT ResTys[] = {MVT::i64,
2530 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2574void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2577 EVT VT =
N->getValueType(0);
2589 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2591 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2593 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2595 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2599 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2600 AArch64::qsub2, AArch64::qsub3 };
2601 for (
unsigned i = 0; i < NumVecs; ++i) {
2602 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2609 CurDAG->RemoveDeadNode(
N);
2612void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2615 EVT VT =
N->getValueType(0);
2627 const EVT ResTys[] = {MVT::i64,
2630 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2633 CurDAG->getTargetConstant(LaneNo, dl,
2638 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2650 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2651 AArch64::qsub2, AArch64::qsub3 };
2652 for (
unsigned i = 0; i < NumVecs; ++i) {
2653 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2663 CurDAG->RemoveDeadNode(
N);
2666void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2669 EVT VT =
N->getOperand(2)->getValueType(0);
2681 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2683 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2685 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2694void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2697 EVT VT =
N->getOperand(2)->getValueType(0);
2709 const EVT ResTys[] = {MVT::i64,
2712 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2714 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2718 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2729 unsigned &LSB,
unsigned &MSB,
2730 unsigned NumberOfIgnoredLowBits,
2731 bool BiggerPattern) {
2733 "N must be a AND operation to call this function");
2735 EVT VT =
N->getValueType(0);
2740 assert((VT == MVT::i32 || VT == MVT::i64) &&
2741 "Type checking must have been done before calling this function");
2755 const SDNode *Op0 =
N->getOperand(0).getNode();
2762 if (AndImm & (AndImm + 1))
2765 bool ClampMSB =
false;
2785 ClampMSB = (VT == MVT::i32);
2786 }
else if (BiggerPattern) {
2792 Opd0 =
N->getOperand(0);
2798 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2801 <<
": Found large shift immediate, this should not happen\n"));
2815 MSB = MSB > 31 ? 31 : MSB;
2817 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2822 SDValue &Opd0,
unsigned &Immr,
2826 EVT VT =
N->getValueType(0);
2828 assert((VT == MVT::i32 || VT == MVT::i64) &&
2829 "Type checking must have been done before calling this function");
2833 Op =
Op->getOperand(0);
2834 VT =
Op->getValueType(0);
2843 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2847 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2848 Opd0 =
Op.getOperand(0);
2850 Imms = ShiftImm + Width - 1;
2878 Opd0 =
N->getOperand(0).getOperand(0);
2888 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2895 unsigned &Immr,
unsigned &Imms,
2896 bool BiggerPattern) {
2898 "N must be a SHR/SRA operation to call this function");
2900 EVT VT =
N->getValueType(0);
2905 assert((VT == MVT::i32 || VT == MVT::i64) &&
2906 "Type checking must have been done before calling this function");
2916 Opd0 =
N->getOperand(0).getOperand(0);
2917 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
2923 Opd0 =
N->getOperand(0).getOperand(0);
2926 assert(VT == MVT::i64 &&
"the promoted type should be i64");
2927 }
else if (BiggerPattern) {
2931 Opd0 =
N->getOperand(0);
2940 <<
": Found large shift immediate, this should not happen\n"));
2949 "bad amount in shift node!");
2950 int immr = SrlImm - ShlImm;
2955 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
2957 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
2961bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
2964 EVT VT =
N->getValueType(0);
2965 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
2966 if (VT != MVT::i64 || NarrowVT != MVT::i32)
2977 unsigned Immr = ShiftImm;
2979 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
2980 CurDAG->getTargetConstant(Imms, dl, VT)};
2981 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
2986 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
2987 unsigned NumberOfIgnoredLowBits = 0,
2988 bool BiggerPattern =
false) {
2989 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
2992 switch (
N->getOpcode()) {
2994 if (!
N->isMachineOpcode())
2999 NumberOfIgnoredLowBits, BiggerPattern);
3008 unsigned NOpc =
N->getMachineOpcode();
3012 case AArch64::SBFMWri:
3013 case AArch64::UBFMWri:
3014 case AArch64::SBFMXri:
3015 case AArch64::UBFMXri:
3017 Opd0 =
N->getOperand(0);
3018 Immr =
N->getConstantOperandVal(1);
3019 Imms =
N->getConstantOperandVal(2);
3026bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3027 unsigned Opc, Immr, Imms;
3032 EVT VT =
N->getValueType(0);
3037 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3038 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3039 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3041 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3042 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3048 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3049 CurDAG->getTargetConstant(Imms, dl, VT)};
3050 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3059 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3060 assert((VT == MVT::i32 || VT == MVT::i64) &&
3061 "i32 or i64 mask type expected!");
3065 APInt SignificantDstMask =
3069 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3070 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3103 APInt OpUsefulBits(UsefulBits);
3107 OpUsefulBits <<= MSB - Imm + 1;
3112 OpUsefulBits <<= Imm;
3114 OpUsefulBits <<= MSB + 1;
3117 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
3123 UsefulBits &= OpUsefulBits;
3140 APInt Mask(UsefulBits);
3141 Mask.clearAllBits();
3149 Mask.lshrInPlace(ShiftAmt);
3155 Mask.lshrInPlace(ShiftAmt);
3171 APInt OpUsefulBits(UsefulBits);
3185 OpUsefulBits <<= Width;
3188 if (
Op.getOperand(1) == Orig) {
3190 Mask = ResultUsefulBits & OpUsefulBits;
3194 if (
Op.getOperand(0) == Orig)
3196 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3202 OpUsefulBits <<= Width;
3204 OpUsefulBits <<= LSB;
3206 if (
Op.getOperand(1) == Orig) {
3208 Mask = ResultUsefulBits & OpUsefulBits;
3209 Mask.lshrInPlace(LSB);
3212 if (
Op.getOperand(0) == Orig)
3213 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3230 case AArch64::ANDSWri:
3231 case AArch64::ANDSXri:
3232 case AArch64::ANDWri:
3233 case AArch64::ANDXri:
3237 case AArch64::UBFMWri:
3238 case AArch64::UBFMXri:
3241 case AArch64::ORRWrs:
3242 case AArch64::ORRXrs:
3247 case AArch64::BFMWri:
3248 case AArch64::BFMXri:
3251 case AArch64::STRBBui:
3252 case AArch64::STURBBi:
3258 case AArch64::STRHHui:
3259 case AArch64::STURHHi:
3272 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3274 UsefulBits =
APInt(Bitwidth, 0);
3283 UsersUsefulBits |= UsefulBitsForUse;
3288 UsefulBits &= UsersUsefulBits;
3298 EVT VT =
Op.getValueType();
3301 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3304 if (ShlAmount > 0) {
3307 UBFMOpc, dl, VT,
Op,
3312 assert(ShlAmount < 0 &&
"expected right shift");
3313 int ShrAmount = -ShlAmount;
3325 const uint64_t NonZeroBits,
3332 const uint64_t NonZeroBits,
3339 bool BiggerPattern,
SDValue &Src,
3340 int &DstLSB,
int &Width) {
3341 EVT VT =
Op.getValueType();
3350 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3354 switch (
Op.getOpcode()) {
3359 NonZeroBits, Src, DstLSB, Width);
3362 NonZeroBits, Src, DstLSB, Width);
3375 EVT VT =
Op.getValueType();
3376 assert((VT == MVT::i32 || VT == MVT::i64) &&
3377 "Caller guarantees VT is one of i32 or i64");
3390 assert((~AndImm & NonZeroBits) == 0 &&
3391 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3420 if (!BiggerPattern && !AndOp0.
hasOneUse())
3439 <<
"Found large Width in bit-field-positioning -- this indicates no "
3440 "proper combining / constant folding was performed\n");
3449 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3464 "Op.getNode() should be a SHL node to call this function");
3466 "Op.getNode() should shift ShlImm to call this function");
3473 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3497 EVT VT =
Op.getValueType();
3498 assert((VT == MVT::i32 || VT == MVT::i64) &&
3499 "Caller guarantees that type is i32 or i64");
3506 if (!BiggerPattern && !
Op.hasOneUse())
3515 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3523 assert(VT == MVT::i32 || VT == MVT::i64);
3534 EVT VT =
N->getValueType(0);
3535 if (VT != MVT::i32 && VT != MVT::i64)
3553 if (!
And.hasOneUse() ||
3563 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3570 if ((OrImm & NotKnownZero) != 0) {
3582 unsigned ImmS = Width - 1;
3588 bool IsBFI = LSB != 0;
3593 unsigned OrChunks = 0, BFIChunks = 0;
3594 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3595 if (((OrImm >> Shift) & 0xFFFF) != 0)
3597 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3600 if (BFIChunks > OrChunks)
3606 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3614 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3623 if (!Dst.hasOneUse())
3626 EVT VT = Dst.getValueType();
3627 assert((VT == MVT::i32 || VT == MVT::i64) &&
3628 "Caller should guarantee that VT is one of i32 or i64");
3656 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3657 unsigned MaskWidth =
3660 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3666 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3667 ShiftedOperand =
SDValue(UBFMNode, 0);
3696 const bool BiggerPattern) {
3697 EVT VT =
N->getValueType(0);
3698 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3699 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3700 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3701 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3702 assert((VT == MVT::i32 || VT == MVT::i64) &&
3703 "Expect result type to be i32 or i64 since N is combinable to BFM");
3710 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3713 if (BiggerPattern) {
3736 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3798 EVT VT =
N->getValueType(0);
3799 if (VT != MVT::i32 && VT != MVT::i64)
3807 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3808 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3828 for (
int I = 0;
I < 4; ++
I) {
3831 unsigned ImmR, ImmS;
3832 bool BiggerPattern =
I / 2;
3833 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3835 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3841 NumberOfIgnoredLowBits, BiggerPattern)) {
3844 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3845 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3850 Width = ImmS - ImmR + 1;
3861 Src, DstLSB, Width)) {
3869 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3879 APInt BitsToBeInserted =
3882 if ((BitsToBeInserted & ~Known.
Zero) != 0)
3906 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3939 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3941 if (Src->hasOneUse() &&
3944 Src = Src->getOperand(0);
3954 unsigned ImmS = Width - 1;
3960 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3968bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
3977 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
3990bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
3994 EVT VT =
N->getValueType(0);
3995 if (VT != MVT::i32 && VT != MVT::i64)
4001 Op0, DstLSB, Width))
4007 unsigned ImmS = Width - 1;
4010 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4011 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4012 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4013 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4019bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4020 EVT VT =
N->getValueType(0);
4023 switch (
N->getOpcode()) {
4025 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4028 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4031 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4034 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4042 if (VT == MVT::i32) {
4045 }
else if (VT == MVT::i64) {
4051 SDValue ShiftAmt =
N->getOperand(1);
4071 (Add0Imm %
Size == 0)) {
4077 if (SubVT == MVT::i32) {
4078 NegOpc = AArch64::SUBWrr;
4079 ZeroReg = AArch64::WZR;
4081 assert(SubVT == MVT::i64);
4082 NegOpc = AArch64::SUBXrr;
4083 ZeroReg = AArch64::XZR;
4086 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4087 MachineSDNode *Neg =
4088 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4089 NewShiftAmt =
SDValue(Neg, 0);
4097 if (SubVT == MVT::i32) {
4098 NotOpc = AArch64::ORNWrr;
4099 ZeroReg = AArch64::WZR;
4101 assert(SubVT == MVT::i64);
4102 NotOpc = AArch64::ORNXrr;
4103 ZeroReg = AArch64::XZR;
4106 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4107 MachineSDNode *
Not =
4108 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4109 NewShiftAmt =
SDValue(Not, 0);
4130 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4131 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4132 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4133 NewShiftAmt, SubReg);
4134 NewShiftAmt =
SDValue(Ext, 0);
4138 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4145 bool isReciprocal) {
4148 FVal = CN->getValueAPF();
4151 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4161 if (
unsigned FBits =
4174 bool isReciprocal) {
4175 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4176 N.getValueType().getScalarSizeInBits() ==
4177 N.getOperand(0).getValueType().getScalarSizeInBits())
4178 N =
N.getOperand(0);
4180 auto ImmToFloat = [RegWidth](
APInt Imm) {
4194 switch (
N->getOpcode()) {
4195 case AArch64ISD::MOVIshift:
4196 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4197 <<
N.getConstantOperandVal(1)));
4199 case AArch64ISD::FMOV:
4200 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4202 case AArch64ISD::DUP:
4204 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4212 if (
unsigned FBits =
4221bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4222 unsigned RegWidth) {
4227bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
4228 unsigned RegWidth) {
4230 CurDAG,
N, FixedPos, RegWidth,
false);
4233bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(
SDValue N,
4235 unsigned RegWidth) {
4237 CurDAG,
N, FixedPos, RegWidth,
true);
4240bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4242 unsigned RegWidth) {
4252 RegString.
split(Fields,
':');
4254 if (Fields.
size() == 1)
4258 &&
"Invalid number of fields in read register string");
4261 bool AllIntFields =
true;
4265 AllIntFields &= !
Field.getAsInteger(10, IntField);
4266 Ops.push_back(IntField);
4270 "Unexpected non-integer value in special register string.");
4275 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4283bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4285 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4288 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4290 unsigned Opcode64Bit = AArch64::MRS;
4295 const auto *TheReg =
4296 AArch64SysReg::lookupSysRegByName(RegString->getString());
4297 if (TheReg && TheReg->Readable &&
4298 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4299 Imm = TheReg->Encoding;
4305 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4306 Opcode64Bit = AArch64::ADR;
4315 RegString->getString());
4316 unsigned PseudoOp = 0;
4317 if (AArch64::GPR64RegClass.
contains(PReg))
4318 PseudoOp = AArch64::READ_REGISTER_GPR64;
4319 else if (AArch64::FPR64RegClass.
contains(PReg))
4320 PseudoOp = AArch64::READ_REGISTER_FPR64;
4321 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4322 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4323 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4332 SDValue InChain =
N->getOperand(0);
4333 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4334 if (!ReadIs128Bit) {
4335 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4336 {SysRegImm, InChain});
4338 SDNode *MRRS = CurDAG->getMachineNode(
4340 {MVT::Untyped , MVT::Other },
4341 {SysRegImm, InChain});
4345 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4347 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4353 ReplaceUses(
SDValue(
N, 2), OutChain);
4362bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4364 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4367 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4369 if (!WriteIs128Bit) {
4375 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4378 "Expected a constant integer expression.");
4379 unsigned Reg = PMapper->Encoding;
4380 uint64_t Immed =
N->getConstantOperandVal(2);
4381 CurDAG->SelectNodeTo(
4382 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4383 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4389 if (trySelectPState(
4390 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4391 AArch64::MSRpstateImm4))
4393 if (trySelectPState(
4394 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4395 AArch64::MSRpstateImm1))
4404 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4405 if (TheReg && TheReg->Writeable &&
4406 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4407 Imm = TheReg->Encoding;
4417 RegString->getString());
4418 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4419 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4420 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4421 N->getOperand(2).getValueType() == MVT::i64) {
4423 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4424 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4425 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4426 MVT::Other, {RegOp,
Copy});
4428 CurDAG->RemoveDeadNode(
N);
4436 if (!WriteIs128Bit) {
4437 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4438 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4439 N->getOperand(2), InChain);
4443 SDNode *Pair = CurDAG->getMachineNode(
4444 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4445 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4448 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4450 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4452 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4453 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4461bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4466 if (Subtarget->hasLSE())
return false;
4468 if (MemTy == MVT::i8)
4469 Opcode = AArch64::CMP_SWAP_8;
4470 else if (MemTy == MVT::i16)
4471 Opcode = AArch64::CMP_SWAP_16;
4472 else if (MemTy == MVT::i32)
4473 Opcode = AArch64::CMP_SWAP_32;
4474 else if (MemTy == MVT::i64)
4475 Opcode = AArch64::CMP_SWAP_64;
4479 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4480 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4482 SDNode *CmpSwap = CurDAG->getMachineNode(
4484 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4491 CurDAG->RemoveDeadNode(
N);
4496bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4497 SDValue &Shift,
bool Negate) {
4504 return SelectSVEAddSubImm(SDLoc(
N), Val, VT, Imm, Shift, Negate);
4507bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4516 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4523 if ((Val & ~0xff) == 0) {
4524 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4529 if ((Val & ~0xff00) == 0) {
4530 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4542bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4566 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4567 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4574 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4575 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4579 if (Val <= 65280 && Val % 256 == 0) {
4580 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4581 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4592bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4602 int32_t ImmVal, ShiftVal;
4607 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4608 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4612bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4614 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(), Imm);
4618bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4621 if (ImmVal >= -128 && ImmVal < 128) {
4622 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4628bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4630 uint64_t ImmVal = CNode->getZExtValue();
4640 ImmVal &= 0xFFFFFFFF;
4649 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4656bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4660 ImmVal = CI->getZExtValue();
4662 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4673 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4682bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4683 uint64_t
High,
bool AllowSaturation,
4686 uint64_t ImmVal = CN->getZExtValue();
4693 if (ImmVal >
High) {
4694 if (!AllowSaturation)
4699 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4706bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4720 const TargetLowering *TLI = getTargetLowering();
4723 SDValue FiOp = CurDAG->getTargetFrameIndex(
4725 int TagOffset =
N->getConstantOperandVal(3);
4727 SDNode *Out = CurDAG->getMachineNode(
4728 AArch64::TAGPstack,
DL, MVT::i64,
4729 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4730 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4731 ReplaceNode(
N, Out);
4735void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4737 "llvm.aarch64.tagp third argument must be an immediate");
4738 if (trySelectStackSlotTagP(
N))
4745 int TagOffset =
N->getConstantOperandVal(3);
4746 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4747 {
N->getOperand(1),
N->getOperand(2)});
4748 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4749 {
SDValue(N1, 0),
N->getOperand(2)});
4750 SDNode *N3 = CurDAG->getMachineNode(
4751 AArch64::ADDG,
DL, MVT::i64,
4752 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4753 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4757bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4761 if (
N->getConstantOperandVal(2) != 0)
4763 if (!
N->getOperand(0).isUndef())
4767 EVT VT =
N->getValueType(0);
4768 EVT InVT =
N->getOperand(1).getValueType();
4779 "Expected to insert into a packed scalable vector!");
4782 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4783 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4784 N->getOperand(1), RC));
4788bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4792 if (
N->getConstantOperandVal(1) != 0)
4796 EVT VT =
N->getValueType(0);
4797 EVT InVT =
N->getOperand(0).getValueType();
4808 "Expected to extract from a packed scalable vector!");
4811 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4812 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4813 N->getOperand(0), RC));
4817bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4823 EVT VT =
N->getValueType(0);
4836 (Subtarget->hasSVE2() ||
4837 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4838 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4841 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4845 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4846 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4847 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4854 bool IsXOROperand =
true;
4856 IsXOROperand =
false;
4862 APInt ShlAmt, ShrAmt;
4870 if (!IsXOROperand) {
4872 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4875 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4876 SDNode *SubRegToReg =
4877 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
4888 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4889 AArch64::XAR_ZZZI_D})) {
4890 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4915 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4925 if (N0->
getOpcode() != AArch64ISD::VSHL ||
4933 bool IsXOROperand =
true;
4935 IsXOROperand =
false;
4938 R1 =
XOR.getOperand(0);
4939 R2 =
XOR.getOperand(1);
4949 if (ShAmt + HsAmt != VTSizeInBits)
4952 if (!IsXOROperand) {
4955 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
4964 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
4970 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
4971 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
4973 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4976 if (
R2.getValueType() == VT)
4977 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
4982 SDValue SubReg = CurDAG->getTargetConstant(
4985 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
4990 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
4996 SDNode *XAR =
nullptr;
5000 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5001 AArch64::XAR_ZZZI_D}))
5002 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5004 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5007 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5013 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5014 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5017 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5018 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5021 SDValue SubReg = CurDAG->getTargetConstant(
5024 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5028 ReplaceNode(
N, XAR);
5032void AArch64DAGToDAGISel::Select(SDNode *Node) {
5034 if (
Node->isMachineOpcode()) {
5036 Node->setNodeId(-1);
5041 EVT VT =
Node->getValueType(0);
5043 switch (
Node->getOpcode()) {
5048 if (SelectCMP_SWAP(Node))
5053 case AArch64ISD::MRRS:
5054 if (tryReadRegister(Node))
5059 case AArch64ISD::MSRR:
5060 if (tryWriteRegister(Node))
5067 if (tryIndexedLoad(Node))
5076 if (tryBitfieldExtractOp(Node))
5078 if (tryBitfieldInsertInZeroOp(Node))
5083 if (tryShiftAmountMod(Node))
5088 if (tryBitfieldExtractOpFromSExt(Node))
5093 if (tryBitfieldInsertOp(Node))
5095 if (trySelectXAR(Node))
5100 if (trySelectCastScalableToFixedLengthVector(Node))
5106 if (trySelectCastFixedLengthToScalableVector(Node))
5115 if (ConstNode->
isZero()) {
5116 if (VT == MVT::i32) {
5118 CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32);
5119 ReplaceNode(Node,
New.getNode());
5121 }
else if (VT == MVT::i64) {
5123 CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64);
5124 ReplaceNode(Node,
New.getNode());
5135 const TargetLowering *TLI = getTargetLowering();
5136 SDValue TFI = CurDAG->getTargetFrameIndex(
5139 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5140 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5141 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5145 unsigned IntNo =
Node->getConstantOperandVal(1);
5149 case Intrinsic::aarch64_gcsss: {
5153 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5155 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5156 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5157 MVT::Other, Zero,
SDValue(SS1, 0));
5158 ReplaceNode(Node, SS2);
5161 case Intrinsic::aarch64_ldaxp:
5162 case Intrinsic::aarch64_ldxp: {
5164 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5169 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5170 MVT::Other, MemAddr, Chain);
5173 MachineMemOperand *MemOp =
5176 ReplaceNode(Node, Ld);
5179 case Intrinsic::aarch64_stlxp:
5180 case Intrinsic::aarch64_stxp: {
5182 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5190 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5192 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5194 MachineMemOperand *MemOp =
5198 ReplaceNode(Node, St);
5201 case Intrinsic::aarch64_neon_ld1x2:
5202 if (VT == MVT::v8i8) {
5203 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5205 }
else if (VT == MVT::v16i8) {
5206 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5208 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5209 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5211 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5212 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5214 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5215 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5217 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5218 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5220 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5221 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5223 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5224 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5228 case Intrinsic::aarch64_neon_ld1x3:
5229 if (VT == MVT::v8i8) {
5230 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5232 }
else if (VT == MVT::v16i8) {
5233 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5235 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5236 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5238 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5239 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5241 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5242 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5244 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5245 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5247 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5248 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5250 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5251 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5255 case Intrinsic::aarch64_neon_ld1x4:
5256 if (VT == MVT::v8i8) {
5257 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5259 }
else if (VT == MVT::v16i8) {
5260 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5262 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5263 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5265 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5266 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5268 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5269 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5271 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5272 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5274 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5275 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5277 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5278 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5282 case Intrinsic::aarch64_neon_ld2:
5283 if (VT == MVT::v8i8) {
5284 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5286 }
else if (VT == MVT::v16i8) {
5287 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5289 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5290 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5292 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5293 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5295 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5296 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5298 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5299 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5301 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5302 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5304 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5305 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5309 case Intrinsic::aarch64_neon_ld3:
5310 if (VT == MVT::v8i8) {
5311 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5313 }
else if (VT == MVT::v16i8) {
5314 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5316 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5317 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5319 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5320 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5322 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5323 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5325 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5326 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5328 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5329 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5331 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5332 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5336 case Intrinsic::aarch64_neon_ld4:
5337 if (VT == MVT::v8i8) {
5338 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5340 }
else if (VT == MVT::v16i8) {
5341 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5343 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5344 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5346 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5347 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5349 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5350 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5352 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5353 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5355 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5356 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5358 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5359 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5363 case Intrinsic::aarch64_neon_ld2r:
5364 if (VT == MVT::v8i8) {
5365 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5367 }
else if (VT == MVT::v16i8) {
5368 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5370 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5371 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5373 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5374 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5376 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5377 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5379 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5380 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5382 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5383 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5385 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5386 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5390 case Intrinsic::aarch64_neon_ld3r:
5391 if (VT == MVT::v8i8) {
5392 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5394 }
else if (VT == MVT::v16i8) {
5395 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5397 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5398 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5400 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5401 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5403 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5404 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5406 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5407 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5409 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5410 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5412 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5413 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5417 case Intrinsic::aarch64_neon_ld4r:
5418 if (VT == MVT::v8i8) {
5419 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5421 }
else if (VT == MVT::v16i8) {
5422 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5424 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5425 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5427 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5428 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5430 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5431 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5433 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5434 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5436 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5437 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5439 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5440 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5444 case Intrinsic::aarch64_neon_ld2lane:
5445 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5446 SelectLoadLane(Node, 2, AArch64::LD2i8);
5448 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5449 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5450 SelectLoadLane(Node, 2, AArch64::LD2i16);
5452 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5454 SelectLoadLane(Node, 2, AArch64::LD2i32);
5456 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5458 SelectLoadLane(Node, 2, AArch64::LD2i64);
5462 case Intrinsic::aarch64_neon_ld3lane:
5463 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5464 SelectLoadLane(Node, 3, AArch64::LD3i8);
5466 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5467 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5468 SelectLoadLane(Node, 3, AArch64::LD3i16);
5470 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5472 SelectLoadLane(Node, 3, AArch64::LD3i32);
5474 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5476 SelectLoadLane(Node, 3, AArch64::LD3i64);
5480 case Intrinsic::aarch64_neon_ld4lane:
5481 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5482 SelectLoadLane(Node, 4, AArch64::LD4i8);
5484 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5485 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5486 SelectLoadLane(Node, 4, AArch64::LD4i16);
5488 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5490 SelectLoadLane(Node, 4, AArch64::LD4i32);
5492 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5494 SelectLoadLane(Node, 4, AArch64::LD4i64);
5498 case Intrinsic::aarch64_ld64b:
5499 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5501 case Intrinsic::aarch64_sve_ld2q_sret: {
5502 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5505 case Intrinsic::aarch64_sve_ld3q_sret: {
5506 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5509 case Intrinsic::aarch64_sve_ld4q_sret: {
5510 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5513 case Intrinsic::aarch64_sve_ld2_sret: {
5514 if (VT == MVT::nxv16i8) {
5515 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5518 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5519 VT == MVT::nxv8bf16) {
5520 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5523 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5524 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5527 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5528 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5534 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5535 if (VT == MVT::nxv16i8) {
5536 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5537 SelectContiguousMultiVectorLoad(
5538 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5539 else if (Subtarget->hasSVE2p1())
5540 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5545 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5546 VT == MVT::nxv8bf16) {
5547 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5548 SelectContiguousMultiVectorLoad(
5549 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5550 else if (Subtarget->hasSVE2p1())
5551 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5556 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5557 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5558 SelectContiguousMultiVectorLoad(
5559 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5560 else if (Subtarget->hasSVE2p1())
5561 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5566 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5567 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5568 SelectContiguousMultiVectorLoad(
5569 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5570 else if (Subtarget->hasSVE2p1())
5571 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5579 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5580 if (VT == MVT::nxv16i8) {
5581 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5582 SelectContiguousMultiVectorLoad(
5583 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5584 else if (Subtarget->hasSVE2p1())
5585 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5590 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5591 VT == MVT::nxv8bf16) {
5592 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5593 SelectContiguousMultiVectorLoad(
5594 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5595 else if (Subtarget->hasSVE2p1())
5596 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5601 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5602 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5603 SelectContiguousMultiVectorLoad(
5604 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5605 else if (Subtarget->hasSVE2p1())
5606 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5611 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5612 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5613 SelectContiguousMultiVectorLoad(
5614 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5615 else if (Subtarget->hasSVE2p1())
5616 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5624 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5625 if (VT == MVT::nxv16i8) {
5626 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5627 SelectContiguousMultiVectorLoad(Node, 2, 0,
5628 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5629 AArch64::LDNT1B_2Z_PSEUDO);
5630 else if (Subtarget->hasSVE2p1())
5631 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5632 AArch64::LDNT1B_2Z);
5636 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5637 VT == MVT::nxv8bf16) {
5638 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5639 SelectContiguousMultiVectorLoad(Node, 2, 1,
5640 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5641 AArch64::LDNT1H_2Z_PSEUDO);
5642 else if (Subtarget->hasSVE2p1())
5643 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5644 AArch64::LDNT1H_2Z);
5648 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5649 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5650 SelectContiguousMultiVectorLoad(Node, 2, 2,
5651 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5652 AArch64::LDNT1W_2Z_PSEUDO);
5653 else if (Subtarget->hasSVE2p1())
5654 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5655 AArch64::LDNT1W_2Z);
5659 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5660 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5661 SelectContiguousMultiVectorLoad(Node, 2, 3,
5662 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5663 AArch64::LDNT1D_2Z_PSEUDO);
5664 else if (Subtarget->hasSVE2p1())
5665 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5666 AArch64::LDNT1D_2Z);
5673 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5674 if (VT == MVT::nxv16i8) {
5675 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5676 SelectContiguousMultiVectorLoad(Node, 4, 0,
5677 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5678 AArch64::LDNT1B_4Z_PSEUDO);
5679 else if (Subtarget->hasSVE2p1())
5680 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5681 AArch64::LDNT1B_4Z);
5685 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5686 VT == MVT::nxv8bf16) {
5687 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5688 SelectContiguousMultiVectorLoad(Node, 4, 1,
5689 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5690 AArch64::LDNT1H_4Z_PSEUDO);
5691 else if (Subtarget->hasSVE2p1())
5692 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5693 AArch64::LDNT1H_4Z);
5697 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5698 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5699 SelectContiguousMultiVectorLoad(Node, 4, 2,
5700 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5701 AArch64::LDNT1W_4Z_PSEUDO);
5702 else if (Subtarget->hasSVE2p1())
5703 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5704 AArch64::LDNT1W_4Z);
5708 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5709 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5710 SelectContiguousMultiVectorLoad(Node, 4, 3,
5711 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5712 AArch64::LDNT1D_4Z_PSEUDO);
5713 else if (Subtarget->hasSVE2p1())
5714 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5715 AArch64::LDNT1D_4Z);
5722 case Intrinsic::aarch64_sve_ld3_sret: {
5723 if (VT == MVT::nxv16i8) {
5724 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5727 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5728 VT == MVT::nxv8bf16) {
5729 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5732 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5733 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5736 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5737 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5743 case Intrinsic::aarch64_sve_ld4_sret: {
5744 if (VT == MVT::nxv16i8) {
5745 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5748 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5749 VT == MVT::nxv8bf16) {
5750 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5753 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5754 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5757 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5758 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5764 case Intrinsic::aarch64_sme_read_hor_vg2: {
5765 if (VT == MVT::nxv16i8) {
5766 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5767 AArch64::MOVA_2ZMXI_H_B);
5769 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5770 VT == MVT::nxv8bf16) {
5771 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5772 AArch64::MOVA_2ZMXI_H_H);
5774 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5775 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5776 AArch64::MOVA_2ZMXI_H_S);
5778 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5779 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5780 AArch64::MOVA_2ZMXI_H_D);
5785 case Intrinsic::aarch64_sme_read_ver_vg2: {
5786 if (VT == MVT::nxv16i8) {
5787 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5788 AArch64::MOVA_2ZMXI_V_B);
5790 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5791 VT == MVT::nxv8bf16) {
5792 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5793 AArch64::MOVA_2ZMXI_V_H);
5795 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5796 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5797 AArch64::MOVA_2ZMXI_V_S);
5799 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5800 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5801 AArch64::MOVA_2ZMXI_V_D);
5806 case Intrinsic::aarch64_sme_read_hor_vg4: {
5807 if (VT == MVT::nxv16i8) {
5808 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5809 AArch64::MOVA_4ZMXI_H_B);
5811 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5812 VT == MVT::nxv8bf16) {
5813 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5814 AArch64::MOVA_4ZMXI_H_H);
5816 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5817 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5818 AArch64::MOVA_4ZMXI_H_S);
5820 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5821 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5822 AArch64::MOVA_4ZMXI_H_D);
5827 case Intrinsic::aarch64_sme_read_ver_vg4: {
5828 if (VT == MVT::nxv16i8) {
5829 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5830 AArch64::MOVA_4ZMXI_V_B);
5832 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5833 VT == MVT::nxv8bf16) {
5834 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5835 AArch64::MOVA_4ZMXI_V_H);
5837 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5838 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5839 AArch64::MOVA_4ZMXI_V_S);
5841 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5842 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5843 AArch64::MOVA_4ZMXI_V_D);
5848 case Intrinsic::aarch64_sme_read_vg1x2: {
5849 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5850 AArch64::MOVA_VG2_2ZMXI);
5853 case Intrinsic::aarch64_sme_read_vg1x4: {
5854 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5855 AArch64::MOVA_VG4_4ZMXI);
5858 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5859 if (VT == MVT::nxv16i8) {
5860 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5862 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5863 VT == MVT::nxv8bf16) {
5864 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5866 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5867 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5869 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5870 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5875 case Intrinsic::aarch64_sme_readz_vert_x2: {
5876 if (VT == MVT::nxv16i8) {
5877 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5879 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5880 VT == MVT::nxv8bf16) {
5881 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5883 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5884 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5886 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5887 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5892 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5893 if (VT == MVT::nxv16i8) {
5894 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5896 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5897 VT == MVT::nxv8bf16) {
5898 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
5900 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5901 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
5903 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5904 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
5909 case Intrinsic::aarch64_sme_readz_vert_x4: {
5910 if (VT == MVT::nxv16i8) {
5911 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
5913 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5914 VT == MVT::nxv8bf16) {
5915 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
5917 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5918 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
5920 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5921 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
5926 case Intrinsic::aarch64_sme_readz_x2: {
5927 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
5931 case Intrinsic::aarch64_sme_readz_x4: {
5932 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
5936 case Intrinsic::swift_async_context_addr: {
5939 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
5941 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
5942 CurDAG->getTargetConstant(8,
DL, MVT::i32),
5943 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
5945 ReplaceUses(
SDValue(Node, 0), Res);
5947 CurDAG->RemoveDeadNode(Node);
5949 auto &MF = CurDAG->getMachineFunction();
5950 MF.getFrameInfo().setFrameAddressIsTaken(
true);
5951 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
5954 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
5956 Node->getValueType(0),
5957 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
5958 AArch64::LUTI2_4ZTZI_S}))
5960 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
5963 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
5965 Node->getValueType(0),
5966 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
5968 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
5971 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
5973 Node->getValueType(0),
5974 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
5975 AArch64::LUTI2_2ZTZI_S}))
5977 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
5980 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
5982 Node->getValueType(0),
5983 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
5984 AArch64::LUTI4_2ZTZI_S}))
5986 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
5989 case Intrinsic::aarch64_sme_luti4_zt_x4: {
5990 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z);
5993 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
5995 Node->getValueType(0),
5996 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
5997 SelectCVTIntrinsicFP8(Node, 2,
Opc);
5999 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6001 Node->getValueType(0),
6002 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6003 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6005 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6007 Node->getValueType(0),
6008 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6009 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6011 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6013 Node->getValueType(0),
6014 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6015 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6017 case Intrinsic::ptrauth_resign_load_relative:
6018 SelectPtrauthResign(Node);
6023 unsigned IntNo =
Node->getConstantOperandVal(0);
6027 case Intrinsic::aarch64_tagp:
6031 case Intrinsic::ptrauth_auth:
6032 SelectPtrauthAuth(Node);
6035 case Intrinsic::ptrauth_resign:
6036 SelectPtrauthResign(Node);
6039 case Intrinsic::aarch64_neon_tbl2:
6040 SelectTable(Node, 2,
6041 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6044 case Intrinsic::aarch64_neon_tbl3:
6045 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6046 : AArch64::TBLv16i8Three,
6049 case Intrinsic::aarch64_neon_tbl4:
6050 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6051 : AArch64::TBLv16i8Four,
6054 case Intrinsic::aarch64_neon_tbx2:
6055 SelectTable(Node, 2,
6056 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6059 case Intrinsic::aarch64_neon_tbx3:
6060 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6061 : AArch64::TBXv16i8Three,
6064 case Intrinsic::aarch64_neon_tbx4:
6065 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6066 : AArch64::TBXv16i8Four,
6069 case Intrinsic::aarch64_sve_srshl_single_x2:
6071 Node->getValueType(0),
6072 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6073 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6074 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6076 case Intrinsic::aarch64_sve_srshl_single_x4:
6078 Node->getValueType(0),
6079 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6080 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6081 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6083 case Intrinsic::aarch64_sve_urshl_single_x2:
6085 Node->getValueType(0),
6086 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6087 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6088 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6090 case Intrinsic::aarch64_sve_urshl_single_x4:
6092 Node->getValueType(0),
6093 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6094 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6095 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6097 case Intrinsic::aarch64_sve_srshl_x2:
6099 Node->getValueType(0),
6100 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6101 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6102 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6104 case Intrinsic::aarch64_sve_srshl_x4:
6106 Node->getValueType(0),
6107 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6108 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6109 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6111 case Intrinsic::aarch64_sve_urshl_x2:
6113 Node->getValueType(0),
6114 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6115 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6116 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6118 case Intrinsic::aarch64_sve_urshl_x4:
6120 Node->getValueType(0),
6121 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6122 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6123 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6125 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6127 Node->getValueType(0),
6128 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6129 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6130 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6132 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6134 Node->getValueType(0),
6135 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6136 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6137 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6139 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6141 Node->getValueType(0),
6142 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6143 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6144 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6146 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6148 Node->getValueType(0),
6149 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6150 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6151 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6153 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6155 Node->getValueType(0),
6156 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6157 AArch64::FSCALE_2ZZ_D}))
6158 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6160 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6162 Node->getValueType(0),
6163 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6164 AArch64::FSCALE_4ZZ_D}))
6165 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6167 case Intrinsic::aarch64_sme_fp8_scale_x2:
6169 Node->getValueType(0),
6170 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6171 AArch64::FSCALE_2Z2Z_D}))
6172 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6174 case Intrinsic::aarch64_sme_fp8_scale_x4:
6176 Node->getValueType(0),
6177 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6178 AArch64::FSCALE_4Z4Z_D}))
6179 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6181 case Intrinsic::aarch64_sve_whilege_x2:
6183 Node->getValueType(0),
6184 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6185 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6186 SelectWhilePair(Node,
Op);
6188 case Intrinsic::aarch64_sve_whilegt_x2:
6190 Node->getValueType(0),
6191 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6192 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6193 SelectWhilePair(Node,
Op);
6195 case Intrinsic::aarch64_sve_whilehi_x2:
6197 Node->getValueType(0),
6198 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6199 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6200 SelectWhilePair(Node,
Op);
6202 case Intrinsic::aarch64_sve_whilehs_x2:
6204 Node->getValueType(0),
6205 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6206 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6207 SelectWhilePair(Node,
Op);
6209 case Intrinsic::aarch64_sve_whilele_x2:
6211 Node->getValueType(0),
6212 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6213 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6214 SelectWhilePair(Node,
Op);
6216 case Intrinsic::aarch64_sve_whilelo_x2:
6218 Node->getValueType(0),
6219 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6220 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6221 SelectWhilePair(Node,
Op);
6223 case Intrinsic::aarch64_sve_whilels_x2:
6225 Node->getValueType(0),
6226 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6227 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6228 SelectWhilePair(Node,
Op);
6230 case Intrinsic::aarch64_sve_whilelt_x2:
6232 Node->getValueType(0),
6233 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6234 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6235 SelectWhilePair(Node,
Op);
6237 case Intrinsic::aarch64_sve_smax_single_x2:
6239 Node->getValueType(0),
6240 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6241 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6244 case Intrinsic::aarch64_sve_umax_single_x2:
6246 Node->getValueType(0),
6247 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6248 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6251 case Intrinsic::aarch64_sve_fmax_single_x2:
6253 Node->getValueType(0),
6254 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6255 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6256 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6258 case Intrinsic::aarch64_sve_smax_single_x4:
6260 Node->getValueType(0),
6261 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6262 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6263 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6265 case Intrinsic::aarch64_sve_umax_single_x4:
6267 Node->getValueType(0),
6268 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6269 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6270 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6272 case Intrinsic::aarch64_sve_fmax_single_x4:
6274 Node->getValueType(0),
6275 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6276 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6277 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6279 case Intrinsic::aarch64_sve_smin_single_x2:
6281 Node->getValueType(0),
6282 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6283 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6284 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6286 case Intrinsic::aarch64_sve_umin_single_x2:
6288 Node->getValueType(0),
6289 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6290 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6293 case Intrinsic::aarch64_sve_fmin_single_x2:
6295 Node->getValueType(0),
6296 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6297 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6298 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6300 case Intrinsic::aarch64_sve_smin_single_x4:
6302 Node->getValueType(0),
6303 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6304 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6305 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6307 case Intrinsic::aarch64_sve_umin_single_x4:
6309 Node->getValueType(0),
6310 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6311 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6312 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6314 case Intrinsic::aarch64_sve_fmin_single_x4:
6316 Node->getValueType(0),
6317 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6318 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6319 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6321 case Intrinsic::aarch64_sve_smax_x2:
6323 Node->getValueType(0),
6324 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6325 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6326 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6328 case Intrinsic::aarch64_sve_umax_x2:
6330 Node->getValueType(0),
6331 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6332 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6333 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6335 case Intrinsic::aarch64_sve_fmax_x2:
6337 Node->getValueType(0),
6338 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6339 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6340 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6342 case Intrinsic::aarch64_sve_smax_x4:
6344 Node->getValueType(0),
6345 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6346 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6347 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6349 case Intrinsic::aarch64_sve_umax_x4:
6351 Node->getValueType(0),
6352 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6353 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6354 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6356 case Intrinsic::aarch64_sve_fmax_x4:
6358 Node->getValueType(0),
6359 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6360 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6361 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6363 case Intrinsic::aarch64_sme_famax_x2:
6365 Node->getValueType(0),
6366 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6367 AArch64::FAMAX_2Z2Z_D}))
6368 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6370 case Intrinsic::aarch64_sme_famax_x4:
6372 Node->getValueType(0),
6373 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6374 AArch64::FAMAX_4Z4Z_D}))
6375 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6377 case Intrinsic::aarch64_sme_famin_x2:
6379 Node->getValueType(0),
6380 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6381 AArch64::FAMIN_2Z2Z_D}))
6382 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6384 case Intrinsic::aarch64_sme_famin_x4:
6386 Node->getValueType(0),
6387 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6388 AArch64::FAMIN_4Z4Z_D}))
6389 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6391 case Intrinsic::aarch64_sve_smin_x2:
6393 Node->getValueType(0),
6394 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6395 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6396 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6398 case Intrinsic::aarch64_sve_umin_x2:
6400 Node->getValueType(0),
6401 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6402 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6403 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6405 case Intrinsic::aarch64_sve_fmin_x2:
6407 Node->getValueType(0),
6408 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6409 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6410 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6412 case Intrinsic::aarch64_sve_smin_x4:
6414 Node->getValueType(0),
6415 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6416 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6417 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6419 case Intrinsic::aarch64_sve_umin_x4:
6421 Node->getValueType(0),
6422 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6423 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6424 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6426 case Intrinsic::aarch64_sve_fmin_x4:
6428 Node->getValueType(0),
6429 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6430 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6431 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6433 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6435 Node->getValueType(0),
6436 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6437 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6438 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6440 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6442 Node->getValueType(0),
6443 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6444 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6445 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6447 case Intrinsic::aarch64_sve_fminnm_single_x2:
6449 Node->getValueType(0),
6450 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6451 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6452 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6454 case Intrinsic::aarch64_sve_fminnm_single_x4:
6456 Node->getValueType(0),
6457 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6458 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6459 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6461 case Intrinsic::aarch64_sve_fscale_single_x4:
6462 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6464 case Intrinsic::aarch64_sve_fscale_single_x2:
6465 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6467 case Intrinsic::aarch64_sve_fmul_single_x4:
6469 Node->getValueType(0),
6470 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6471 AArch64::FMUL_4ZZ_D}))
6472 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6474 case Intrinsic::aarch64_sve_fmul_single_x2:
6476 Node->getValueType(0),
6477 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6478 AArch64::FMUL_2ZZ_D}))
6479 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6481 case Intrinsic::aarch64_sve_fmaxnm_x2:
6483 Node->getValueType(0),
6484 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6485 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6486 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6488 case Intrinsic::aarch64_sve_fmaxnm_x4:
6490 Node->getValueType(0),
6491 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6492 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6493 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6495 case Intrinsic::aarch64_sve_fminnm_x2:
6497 Node->getValueType(0),
6498 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6499 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6500 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6502 case Intrinsic::aarch64_sve_fminnm_x4:
6504 Node->getValueType(0),
6505 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6506 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6507 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6509 case Intrinsic::aarch64_sve_aese_lane_x2:
6510 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6512 case Intrinsic::aarch64_sve_aesd_lane_x2:
6513 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6515 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6516 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6518 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6519 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6521 case Intrinsic::aarch64_sve_aese_lane_x4:
6522 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6524 case Intrinsic::aarch64_sve_aesd_lane_x4:
6525 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6527 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6528 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6530 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6531 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6533 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6534 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6536 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6540 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6542 for (
unsigned I = 0;
I < 2;
I++)
6544 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6546 CurDAG->RemoveDeadNode(Node);
6549 case Intrinsic::aarch64_sve_fscale_x4:
6550 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6552 case Intrinsic::aarch64_sve_fscale_x2:
6553 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6555 case Intrinsic::aarch64_sve_fmul_x4:
6557 Node->getValueType(0),
6558 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6559 AArch64::FMUL_4Z4Z_D}))
6560 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6562 case Intrinsic::aarch64_sve_fmul_x2:
6564 Node->getValueType(0),
6565 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6566 AArch64::FMUL_2Z2Z_D}))
6567 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6569 case Intrinsic::aarch64_sve_fcvtzs_x2:
6570 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6572 case Intrinsic::aarch64_sve_scvtf_x2:
6573 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6575 case Intrinsic::aarch64_sve_fcvtzu_x2:
6576 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6578 case Intrinsic::aarch64_sve_ucvtf_x2:
6579 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6581 case Intrinsic::aarch64_sve_fcvtzs_x4:
6582 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6584 case Intrinsic::aarch64_sve_scvtf_x4:
6585 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6587 case Intrinsic::aarch64_sve_fcvtzu_x4:
6588 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6590 case Intrinsic::aarch64_sve_ucvtf_x4:
6591 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6593 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6594 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6596 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6597 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6599 case Intrinsic::aarch64_sve_sclamp_single_x2:
6601 Node->getValueType(0),
6602 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6603 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6604 SelectClamp(Node, 2,
Op);
6606 case Intrinsic::aarch64_sve_uclamp_single_x2:
6608 Node->getValueType(0),
6609 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6610 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6611 SelectClamp(Node, 2,
Op);
6613 case Intrinsic::aarch64_sve_fclamp_single_x2:
6615 Node->getValueType(0),
6616 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6617 AArch64::FCLAMP_VG2_2Z2Z_D}))
6618 SelectClamp(Node, 2,
Op);
6620 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6621 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6623 case Intrinsic::aarch64_sve_sclamp_single_x4:
6625 Node->getValueType(0),
6626 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6627 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6628 SelectClamp(Node, 4,
Op);
6630 case Intrinsic::aarch64_sve_uclamp_single_x4:
6632 Node->getValueType(0),
6633 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6634 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6635 SelectClamp(Node, 4,
Op);
6637 case Intrinsic::aarch64_sve_fclamp_single_x4:
6639 Node->getValueType(0),
6640 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6641 AArch64::FCLAMP_VG4_4Z4Z_D}))
6642 SelectClamp(Node, 4,
Op);
6644 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6645 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6647 case Intrinsic::aarch64_sve_add_single_x2:
6649 Node->getValueType(0),
6650 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6651 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6652 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6654 case Intrinsic::aarch64_sve_add_single_x4:
6656 Node->getValueType(0),
6657 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6658 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6659 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6661 case Intrinsic::aarch64_sve_zip_x2:
6663 Node->getValueType(0),
6664 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6665 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6666 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6668 case Intrinsic::aarch64_sve_zipq_x2:
6669 SelectUnaryMultiIntrinsic(Node, 2,
false,
6670 AArch64::ZIP_VG2_2ZZZ_Q);
6672 case Intrinsic::aarch64_sve_zip_x4:
6674 Node->getValueType(0),
6675 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6676 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6677 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6679 case Intrinsic::aarch64_sve_zipq_x4:
6680 SelectUnaryMultiIntrinsic(Node, 4,
true,
6681 AArch64::ZIP_VG4_4Z4Z_Q);
6683 case Intrinsic::aarch64_sve_uzp_x2:
6685 Node->getValueType(0),
6686 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6687 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6688 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6690 case Intrinsic::aarch64_sve_uzpq_x2:
6691 SelectUnaryMultiIntrinsic(Node, 2,
false,
6692 AArch64::UZP_VG2_2ZZZ_Q);
6694 case Intrinsic::aarch64_sve_uzp_x4:
6696 Node->getValueType(0),
6697 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6698 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6699 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6701 case Intrinsic::aarch64_sve_uzpq_x4:
6702 SelectUnaryMultiIntrinsic(Node, 4,
true,
6703 AArch64::UZP_VG4_4Z4Z_Q);
6705 case Intrinsic::aarch64_sve_sel_x2:
6707 Node->getValueType(0),
6708 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6709 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6710 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6712 case Intrinsic::aarch64_sve_sel_x4:
6714 Node->getValueType(0),
6715 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6716 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6717 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6719 case Intrinsic::aarch64_sve_frinta_x2:
6720 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6722 case Intrinsic::aarch64_sve_frinta_x4:
6723 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6725 case Intrinsic::aarch64_sve_frintm_x2:
6726 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6728 case Intrinsic::aarch64_sve_frintm_x4:
6729 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6731 case Intrinsic::aarch64_sve_frintn_x2:
6732 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6734 case Intrinsic::aarch64_sve_frintn_x4:
6735 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6737 case Intrinsic::aarch64_sve_frintp_x2:
6738 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6740 case Intrinsic::aarch64_sve_frintp_x4:
6741 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6743 case Intrinsic::aarch64_sve_sunpk_x2:
6745 Node->getValueType(0),
6746 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6747 AArch64::SUNPK_VG2_2ZZ_D}))
6748 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6750 case Intrinsic::aarch64_sve_uunpk_x2:
6752 Node->getValueType(0),
6753 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6754 AArch64::UUNPK_VG2_2ZZ_D}))
6755 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6757 case Intrinsic::aarch64_sve_sunpk_x4:
6759 Node->getValueType(0),
6760 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6761 AArch64::SUNPK_VG4_4Z2Z_D}))
6762 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6764 case Intrinsic::aarch64_sve_uunpk_x4:
6766 Node->getValueType(0),
6767 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6768 AArch64::UUNPK_VG4_4Z2Z_D}))
6769 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6771 case Intrinsic::aarch64_sve_pext_x2: {
6773 Node->getValueType(0),
6774 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6775 AArch64::PEXT_2PCI_D}))
6776 SelectPExtPair(Node,
Op);
6783 unsigned IntNo =
Node->getConstantOperandVal(1);
6784 if (
Node->getNumOperands() >= 3)
6785 VT =
Node->getOperand(2)->getValueType(0);
6789 case Intrinsic::aarch64_neon_st1x2: {
6790 if (VT == MVT::v8i8) {
6791 SelectStore(Node, 2, AArch64::ST1Twov8b);
6793 }
else if (VT == MVT::v16i8) {
6794 SelectStore(Node, 2, AArch64::ST1Twov16b);
6796 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6797 VT == MVT::v4bf16) {
6798 SelectStore(Node, 2, AArch64::ST1Twov4h);
6800 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6801 VT == MVT::v8bf16) {
6802 SelectStore(Node, 2, AArch64::ST1Twov8h);
6804 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6805 SelectStore(Node, 2, AArch64::ST1Twov2s);
6807 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6808 SelectStore(Node, 2, AArch64::ST1Twov4s);
6810 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6811 SelectStore(Node, 2, AArch64::ST1Twov2d);
6813 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6814 SelectStore(Node, 2, AArch64::ST1Twov1d);
6819 case Intrinsic::aarch64_neon_st1x3: {
6820 if (VT == MVT::v8i8) {
6821 SelectStore(Node, 3, AArch64::ST1Threev8b);
6823 }
else if (VT == MVT::v16i8) {
6824 SelectStore(Node, 3, AArch64::ST1Threev16b);
6826 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6827 VT == MVT::v4bf16) {
6828 SelectStore(Node, 3, AArch64::ST1Threev4h);
6830 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6831 VT == MVT::v8bf16) {
6832 SelectStore(Node, 3, AArch64::ST1Threev8h);
6834 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6835 SelectStore(Node, 3, AArch64::ST1Threev2s);
6837 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6838 SelectStore(Node, 3, AArch64::ST1Threev4s);
6840 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6841 SelectStore(Node, 3, AArch64::ST1Threev2d);
6843 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6844 SelectStore(Node, 3, AArch64::ST1Threev1d);
6849 case Intrinsic::aarch64_neon_st1x4: {
6850 if (VT == MVT::v8i8) {
6851 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6853 }
else if (VT == MVT::v16i8) {
6854 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6856 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6857 VT == MVT::v4bf16) {
6858 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6860 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6861 VT == MVT::v8bf16) {
6862 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6864 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6865 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6867 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6868 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6870 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6871 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6873 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6874 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6879 case Intrinsic::aarch64_neon_st2: {
6880 if (VT == MVT::v8i8) {
6881 SelectStore(Node, 2, AArch64::ST2Twov8b);
6883 }
else if (VT == MVT::v16i8) {
6884 SelectStore(Node, 2, AArch64::ST2Twov16b);
6886 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6887 VT == MVT::v4bf16) {
6888 SelectStore(Node, 2, AArch64::ST2Twov4h);
6890 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6891 VT == MVT::v8bf16) {
6892 SelectStore(Node, 2, AArch64::ST2Twov8h);
6894 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6895 SelectStore(Node, 2, AArch64::ST2Twov2s);
6897 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6898 SelectStore(Node, 2, AArch64::ST2Twov4s);
6900 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6901 SelectStore(Node, 2, AArch64::ST2Twov2d);
6903 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6904 SelectStore(Node, 2, AArch64::ST1Twov1d);
6909 case Intrinsic::aarch64_neon_st3: {
6910 if (VT == MVT::v8i8) {
6911 SelectStore(Node, 3, AArch64::ST3Threev8b);
6913 }
else if (VT == MVT::v16i8) {
6914 SelectStore(Node, 3, AArch64::ST3Threev16b);
6916 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6917 VT == MVT::v4bf16) {
6918 SelectStore(Node, 3, AArch64::ST3Threev4h);
6920 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6921 VT == MVT::v8bf16) {
6922 SelectStore(Node, 3, AArch64::ST3Threev8h);
6924 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6925 SelectStore(Node, 3, AArch64::ST3Threev2s);
6927 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6928 SelectStore(Node, 3, AArch64::ST3Threev4s);
6930 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6931 SelectStore(Node, 3, AArch64::ST3Threev2d);
6933 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6934 SelectStore(Node, 3, AArch64::ST1Threev1d);
6939 case Intrinsic::aarch64_neon_st4: {
6940 if (VT == MVT::v8i8) {
6941 SelectStore(Node, 4, AArch64::ST4Fourv8b);
6943 }
else if (VT == MVT::v16i8) {
6944 SelectStore(Node, 4, AArch64::ST4Fourv16b);
6946 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6947 VT == MVT::v4bf16) {
6948 SelectStore(Node, 4, AArch64::ST4Fourv4h);
6950 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6951 VT == MVT::v8bf16) {
6952 SelectStore(Node, 4, AArch64::ST4Fourv8h);
6954 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6955 SelectStore(Node, 4, AArch64::ST4Fourv2s);
6957 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6958 SelectStore(Node, 4, AArch64::ST4Fourv4s);
6960 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6961 SelectStore(Node, 4, AArch64::ST4Fourv2d);
6963 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6964 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6969 case Intrinsic::aarch64_neon_st2lane: {
6970 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6971 SelectStoreLane(Node, 2, AArch64::ST2i8);
6973 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6974 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6975 SelectStoreLane(Node, 2, AArch64::ST2i16);
6977 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6979 SelectStoreLane(Node, 2, AArch64::ST2i32);
6981 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
6983 SelectStoreLane(Node, 2, AArch64::ST2i64);
6988 case Intrinsic::aarch64_neon_st3lane: {
6989 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
6990 SelectStoreLane(Node, 3, AArch64::ST3i8);
6992 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
6993 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
6994 SelectStoreLane(Node, 3, AArch64::ST3i16);
6996 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
6998 SelectStoreLane(Node, 3, AArch64::ST3i32);
7000 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7002 SelectStoreLane(Node, 3, AArch64::ST3i64);
7007 case Intrinsic::aarch64_neon_st4lane: {
7008 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7009 SelectStoreLane(Node, 4, AArch64::ST4i8);
7011 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7012 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7013 SelectStoreLane(Node, 4, AArch64::ST4i16);
7015 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7017 SelectStoreLane(Node, 4, AArch64::ST4i32);
7019 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7021 SelectStoreLane(Node, 4, AArch64::ST4i64);
7026 case Intrinsic::aarch64_sve_st2q: {
7027 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7030 case Intrinsic::aarch64_sve_st3q: {
7031 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7034 case Intrinsic::aarch64_sve_st4q: {
7035 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7038 case Intrinsic::aarch64_sve_st2: {
7039 if (VT == MVT::nxv16i8) {
7040 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7042 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7043 VT == MVT::nxv8bf16) {
7044 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7046 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7047 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7049 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7050 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7055 case Intrinsic::aarch64_sve_st3: {
7056 if (VT == MVT::nxv16i8) {
7057 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7059 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7060 VT == MVT::nxv8bf16) {
7061 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7063 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7064 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7066 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7067 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7072 case Intrinsic::aarch64_sve_st4: {
7073 if (VT == MVT::nxv16i8) {
7074 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7076 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7077 VT == MVT::nxv8bf16) {
7078 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7080 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7081 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7083 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7084 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7092 case AArch64ISD::LD2post: {
7093 if (VT == MVT::v8i8) {
7094 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7096 }
else if (VT == MVT::v16i8) {
7097 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7099 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7100 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7102 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7103 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7105 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7106 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7108 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7109 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7111 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7112 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7114 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7115 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7120 case AArch64ISD::LD3post: {
7121 if (VT == MVT::v8i8) {
7122 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7124 }
else if (VT == MVT::v16i8) {
7125 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7127 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7128 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7130 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7131 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7133 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7134 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7136 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7137 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7139 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7140 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7142 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7143 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7148 case AArch64ISD::LD4post: {
7149 if (VT == MVT::v8i8) {
7150 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7152 }
else if (VT == MVT::v16i8) {
7153 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7155 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7156 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7158 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7159 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7161 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7162 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7164 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7165 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7167 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7168 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7170 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7171 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7176 case AArch64ISD::LD1x2post: {
7177 if (VT == MVT::v8i8) {
7178 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7180 }
else if (VT == MVT::v16i8) {
7181 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7183 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7184 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7186 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7187 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7189 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7190 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7192 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7193 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7195 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7196 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7198 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7199 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7204 case AArch64ISD::LD1x3post: {
7205 if (VT == MVT::v8i8) {
7206 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7208 }
else if (VT == MVT::v16i8) {
7209 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7211 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7212 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7214 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7215 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7217 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7218 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7220 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7221 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7223 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7224 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7226 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7227 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7232 case AArch64ISD::LD1x4post: {
7233 if (VT == MVT::v8i8) {
7234 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7236 }
else if (VT == MVT::v16i8) {
7237 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7239 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7240 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7242 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7243 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7245 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7246 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7248 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7249 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7251 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7252 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7254 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7255 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7260 case AArch64ISD::LD1DUPpost: {
7261 if (VT == MVT::v8i8) {
7262 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7264 }
else if (VT == MVT::v16i8) {
7265 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7267 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7268 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7270 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7271 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7273 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7274 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7276 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7277 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7279 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7280 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7282 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7283 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7288 case AArch64ISD::LD2DUPpost: {
7289 if (VT == MVT::v8i8) {
7290 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7292 }
else if (VT == MVT::v16i8) {
7293 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7295 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7296 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7298 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7299 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7301 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7302 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7304 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7305 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7307 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7308 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7310 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7311 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7316 case AArch64ISD::LD3DUPpost: {
7317 if (VT == MVT::v8i8) {
7318 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7320 }
else if (VT == MVT::v16i8) {
7321 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7323 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7324 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7326 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7327 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7329 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7330 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7332 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7333 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7335 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7336 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7338 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7339 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7344 case AArch64ISD::LD4DUPpost: {
7345 if (VT == MVT::v8i8) {
7346 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7348 }
else if (VT == MVT::v16i8) {
7349 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7351 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7352 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7354 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7355 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7357 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7358 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7360 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7361 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7363 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7364 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7366 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7367 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7372 case AArch64ISD::LD1LANEpost: {
7373 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7374 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7376 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7377 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7378 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7380 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7382 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7384 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7386 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7391 case AArch64ISD::LD2LANEpost: {
7392 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7393 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7395 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7396 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7397 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7399 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7401 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7403 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7405 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7410 case AArch64ISD::LD3LANEpost: {
7411 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7412 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7414 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7415 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7416 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7418 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7420 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7422 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7424 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7429 case AArch64ISD::LD4LANEpost: {
7430 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7431 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7433 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7434 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7435 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7437 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7439 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7441 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7443 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7448 case AArch64ISD::ST2post: {
7449 VT =
Node->getOperand(1).getValueType();
7450 if (VT == MVT::v8i8) {
7451 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7453 }
else if (VT == MVT::v16i8) {
7454 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7456 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7457 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7459 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7460 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7462 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7463 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7465 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7466 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7468 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7469 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7471 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7472 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7477 case AArch64ISD::ST3post: {
7478 VT =
Node->getOperand(1).getValueType();
7479 if (VT == MVT::v8i8) {
7480 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7482 }
else if (VT == MVT::v16i8) {
7483 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7485 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7486 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7488 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7489 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7491 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7492 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7494 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7495 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7497 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7498 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7500 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7501 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7506 case AArch64ISD::ST4post: {
7507 VT =
Node->getOperand(1).getValueType();
7508 if (VT == MVT::v8i8) {
7509 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7511 }
else if (VT == MVT::v16i8) {
7512 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7514 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7515 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7517 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7518 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7520 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7521 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7523 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7524 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7526 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7527 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7529 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7530 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7535 case AArch64ISD::ST1x2post: {
7536 VT =
Node->getOperand(1).getValueType();
7537 if (VT == MVT::v8i8) {
7538 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7540 }
else if (VT == MVT::v16i8) {
7541 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7543 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7544 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7546 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7547 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7549 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7550 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7552 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7553 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7555 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7556 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7558 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7559 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7564 case AArch64ISD::ST1x3post: {
7565 VT =
Node->getOperand(1).getValueType();
7566 if (VT == MVT::v8i8) {
7567 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7569 }
else if (VT == MVT::v16i8) {
7570 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7572 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7573 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7575 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7576 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7578 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7579 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7581 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7582 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7584 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7585 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7587 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7588 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7593 case AArch64ISD::ST1x4post: {
7594 VT =
Node->getOperand(1).getValueType();
7595 if (VT == MVT::v8i8) {
7596 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7598 }
else if (VT == MVT::v16i8) {
7599 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7601 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7602 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7604 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7605 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7607 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7608 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7610 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7611 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7613 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7614 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7616 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7617 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7622 case AArch64ISD::ST2LANEpost: {
7623 VT =
Node->getOperand(1).getValueType();
7624 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7625 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7627 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7628 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7629 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7631 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7633 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7635 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7637 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7642 case AArch64ISD::ST3LANEpost: {
7643 VT =
Node->getOperand(1).getValueType();
7644 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7645 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7647 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7648 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7649 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7651 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7653 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7655 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7657 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7662 case AArch64ISD::ST4LANEpost: {
7663 VT =
Node->getOperand(1).getValueType();
7664 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7665 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7667 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7668 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7669 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7671 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7673 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7675 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7677 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7692 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7704 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7708 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7709 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7731 return MemIntr->getMemoryVT();
7738 DataVT = Load->getValueType(0);
7740 DataVT = Load->getValueType(0);
7742 DataVT = Store->getValue().getValueType();
7744 DataVT = Store->getValue().getValueType();
7751 const unsigned Opcode = Root->
getOpcode();
7755 case AArch64ISD::LD1_MERGE_ZERO:
7756 case AArch64ISD::LD1S_MERGE_ZERO:
7757 case AArch64ISD::LDNF1_MERGE_ZERO:
7758 case AArch64ISD::LDNF1S_MERGE_ZERO:
7760 case AArch64ISD::ST1_PRED:
7772 case Intrinsic::aarch64_sme_ldr:
7773 case Intrinsic::aarch64_sme_str:
7774 return MVT::nxv16i8;
7775 case Intrinsic::aarch64_sve_prf:
7780 case Intrinsic::aarch64_sve_ld2_sret:
7781 case Intrinsic::aarch64_sve_ld2q_sret:
7784 case Intrinsic::aarch64_sve_st2q:
7787 case Intrinsic::aarch64_sve_ld3_sret:
7788 case Intrinsic::aarch64_sve_ld3q_sret:
7791 case Intrinsic::aarch64_sve_st3q:
7794 case Intrinsic::aarch64_sve_ld4_sret:
7795 case Intrinsic::aarch64_sve_ld4q_sret:
7798 case Intrinsic::aarch64_sve_st4q:
7801 case Intrinsic::aarch64_sve_ld1_pn_x2:
7802 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7805 case Intrinsic::aarch64_sve_ld1_pn_x4:
7806 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7809 case Intrinsic::aarch64_sve_st1_pn_x2:
7810 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7813 case Intrinsic::aarch64_sve_st1_pn_x4:
7814 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7817 case Intrinsic::aarch64_sve_ld1udq:
7818 case Intrinsic::aarch64_sve_st1dq:
7819 return EVT(MVT::nxv1i64);
7820 case Intrinsic::aarch64_sve_ld1uwq:
7821 case Intrinsic::aarch64_sve_st1wq:
7822 return EVT(MVT::nxv1i32);
7829template <
int64_t Min,
int64_t Max>
7830bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7834 const DataLayout &
DL = CurDAG->getDataLayout();
7835 const MachineFrameInfo &MFI = MF->getFrameInfo();
7843 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7857 int64_t MulImm = std::numeric_limits<int64_t>::max();
7861 int64_t ByteOffset =
C->getSExtValue();
7862 const auto KnownVScale =
7865 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7868 MulImm = ByteOffset / KnownVScale;
7875 if ((MulImm % MemWidthBytes) != 0)
7878 int64_t
Offset = MulImm / MemWidthBytes;
7882 Base =
N.getOperand(0);
7891 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
7897bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
7916 int64_t ImmOff =
C->getSExtValue();
7917 unsigned Size = 1 << Scale;
7926 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
7928 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
7939 if (
C->getZExtValue() == Scale) {
7948bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
7949 const AArch64TargetLowering *TLI =
7950 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
7955bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
7956 return N.getValueType().isScalableVectorOf(MVT::i1);
7959bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
7964 int64_t ImmOff =
C->getSExtValue();
7965 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
7966 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
7971 if (
SDValue C = MatchConstantOffset(
N)) {
7972 Base = CurDAG->getConstant(0, SDLoc(
N), MVT::i32);
7978 if (CurDAG->isBaseWithConstantOffset(
N)) {
7979 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
7980 Base =
N.getOperand(0);
7988 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7992bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
8012 uint64_t LowerBound = 0, UpperBound = 64;
8030 if (CN->getAPIntValue().uge(LowerBound) &&
8031 CN->getAPIntValue().ult(UpperBound)) {
8033 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8041template <
bool MatchCBB>
8048 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8050 Reg =
N.getOperand(0);
8052 SDLoc(
N), MVT::i32);
8060 Reg =
N.getOperand(0);
8080SDValue AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode &
N) {
8081 EVT VT =
N.getValueType(0);
8092 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8101 unsigned CondCode = CC->getZExtValue();
8104 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8106 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8107 else if (VT == MVT::f32)
8108 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8109 else if (VT == MVT::f64)
8110 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8118 if (TVal == CmpLHS && FVal == CmpRHS)
8120 else if (TVal == CmpRHS && FVal == CmpLHS)
8125 if (TVal == CmpLHS && FVal == CmpRHS)
8127 else if (TVal == CmpRHS && FVal == CmpLHS)
8136 unsigned Opc = getOpc(VT, isMax);
8142 if (!CFP || CFP->getValueAPF().isNaN())
8147 if (CFP->isZero() && !
N.getFlags().hasNoSignedZeros())
8153 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8159 return SDValue(CurDAG->getMachineNode(
Opc,
DL, VT, CmpLHS, CmpRHS), 0);
8162void AArch64DAGToDAGISel::PreprocessISelDAG() {
8163 bool MadeChange =
false;
8169 switch (
N.getOpcode()) {
8171 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8172 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8173 ScalarTy ==
N.getOperand(0).getValueType())
8178 case AArch64ISD::CSEL:
8179 Result = tryFoldCselToFMaxMin(
N);
8186 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8192 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(&
N, 0), Result);
8198 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 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!")
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(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.
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.
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.