25#include "llvm/IR/IntrinsicsAArch64.h"
35#define DEBUG_TYPE "aarch64-isel"
36#define PASS_NAME "AArch64 Instruction Selection"
39#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
40#pragma inline_depth(0)
56 AArch64DAGToDAGISel() =
delete;
68 void PreprocessISelDAG()
override;
72 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
74 std::vector<SDValue> &OutOps)
override;
76 template <
signed Low,
signed High,
signed Scale>
79 template <
signed Low,
signed High>
87 return SelectShiftedRegister(
N,
false,
Reg, Shift);
90 return SelectShiftedRegister(
N,
true,
Reg, Shift);
93 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
96 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
99 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
102 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
105 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
108 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
111 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
114 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
117 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
120 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
123 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
126 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
129 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
132 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
135 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
138 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
141 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
143 template <
unsigned Size,
unsigned Max>
147 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
150 int64_t
C = CI->getSExtValue();
158 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
165 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
171 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
176 N =
N->getOperand(0);
180 EVT VT =
N->getValueType(0);
181 EVT LVT =
N->getOperand(0).getValueType();
182 unsigned Index =
N->getConstantOperandVal(1);
186 Res =
N->getOperand(0);
191 if (
N.getOpcode() != AArch64ISD::VLSHR)
194 EVT VT =
Op.getValueType();
195 unsigned ShtAmt =
N->getConstantOperandVal(1);
200 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
202 Op.getOperand(1).getConstantOperandVal(0)
203 <<
Op.getOperand(1).getConstantOperandVal(1));
204 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
207 Op.getOperand(1).getConstantOperandVal(0));
211 if (Imm != 1ULL << (ShtAmt - 1))
214 Res1 =
Op.getOperand(0);
215 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
219 bool SelectDupZeroOrUndef(
SDValue N) {
220 switch(
N->getOpcode()) {
224 case AArch64ISD::DUP:
226 auto Opnd0 =
N->getOperand(0);
240 bool SelectAny(
SDValue) {
return true; }
243 switch(
N->getOpcode()) {
244 case AArch64ISD::DUP:
246 auto Opnd0 =
N->getOperand(0);
258 template <MVT::SimpleValueType VT,
bool Negate>
260 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
263 template <MVT::SimpleValueType VT,
bool Negate>
265 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
268 template <MVT::SimpleValueType VT>
270 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
273 template <MVT::SimpleValueType VT,
bool Invert = false>
275 return SelectSVELogicalImm(
N, VT, Imm, Invert);
278 template <MVT::SimpleValueType VT>
280 return SelectSVEArithImm(
N, VT, Imm);
283 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
285 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
292 EVT EltVT =
N->getValueType(0).getVectorElementType();
293 return SelectSVEShiftImm(
N->getOperand(0), 1,
299 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
306 MulImm = 1LL << MulImm;
308 if ((MulImm % std::abs(Scale)) != 0)
312 if ((MulImm >= Min) && (MulImm <= Max)) {
313 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
320 template <
signed Max,
signed Scale>
327 if (MulImm >= 0 && MulImm <= Max) {
329 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
336 template <
unsigned BaseReg,
unsigned Max>
344 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
367 const unsigned SubRegs[]);
369 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
371 bool tryIndexedLoad(
SDNode *
N);
373 void SelectPtrauthAuth(
SDNode *
N);
374 void SelectPtrauthResign(
SDNode *
N);
375 void SelectPtrauthResignWithPC(
SDNode *
N);
377 bool trySelectStackSlotTagP(
SDNode *
N);
380 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
382 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
384 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
385 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
386 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
387 unsigned Opc_rr,
unsigned Opc_ri,
388 bool IsIntr =
false);
389 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
390 unsigned Scale,
unsigned Opc_ri,
392 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
393 bool IsZmMulti,
unsigned Opcode,
394 bool HasPred =
false);
396 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
397 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
398 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
399 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
400 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
401 bool IsTupleInput,
unsigned Opc);
402 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
404 template <
unsigned MaxIdx,
unsigned Scale>
405 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
407 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
408 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
409 unsigned BaseReg = 0);
411 template <
int64_t Min,
int64_t Max>
415 template <
unsigned Scale>
417 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
420 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
422 void SelectMultiVectorLuti6LaneX4(
SDNode *
Node,
unsigned NumIndexVecs);
424 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc,
427 template <
unsigned MaxIdx,
unsigned Scale>
432 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
433 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
434 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
435 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
436 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
437 unsigned Opc_rr,
unsigned Opc_ri);
438 std::tuple<unsigned, SDValue, SDValue>
439 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
443 bool tryBitfieldExtractOp(
SDNode *
N);
444 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
445 bool tryBitfieldInsertOp(
SDNode *
N);
446 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
447 bool tryShiftAmountMod(
SDNode *
N);
449 bool tryReadRegister(
SDNode *
N);
450 bool tryWriteRegister(
SDNode *
N);
452 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
453 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
457 bool tryFoldCselToFMaxMin(
SDNode *
N);
460#include "AArch64GenDAGISel.inc"
468 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
470 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
483 bool isWorthNegatingImm(
SDValue V)
const;
484 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
485 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
486 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
489 template<
unsigned RegW
idth>
491 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
493 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
495 template <
unsigned RegW
idth>
497 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
499 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
501 template<
unsigned RegW
idth>
503 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
509 template <
unsigned FloatW
idth>
511 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
517 bool SelectCMP_SWAP(
SDNode *
N);
538 bool AllowSaturation,
SDValue &Imm);
546 bool SelectAllActivePredicate(
SDValue N);
551 template <
bool MatchCBB>
561 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
565char AArch64DAGToDAGISelLegacy::ID = 0;
571 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
577 auto getFloatVT = [&](
EVT VT) {
579 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
580 return VT.changeElementType(*(DAG.
getContext()),
581 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
586 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
587 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
591 EVT OrigVT =
N.getValueType(0);
600 Imm =
C->getZExtValue();
617 return N->getOpcode() ==
Opc &&
628 return Imm == ImmExpected;
633 assert(RegWidth == 32 || RegWidth == 64);
635 return APInt(RegWidth,
642 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
643 if (
N->getOpcode() == AArch64ISD::NVCAST)
644 N =
N->getOperand(0);
645 unsigned SplatWidth =
N.getScalarValueSizeInBits();
646 if (
N.getOpcode() == AArch64ISD::FMOV)
648 if (
N->getOpcode() == AArch64ISD::MOVI)
649 return APInt(SplatWidth,
N.getConstantOperandVal(0));
650 if (
N->getOpcode() == AArch64ISD::MOVIshift)
651 return APInt(SplatWidth,
N.getConstantOperandVal(0)
652 <<
N.getConstantOperandVal(1));
653 if (
N->getOpcode() == AArch64ISD::MVNIshift)
654 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
655 <<
N.getConstantOperandVal(1));
656 if (
N->getOpcode() == AArch64ISD::MOVIedit)
658 N.getConstantOperandVal(0)));
659 if (
N->getOpcode() == AArch64ISD::DUP)
661 return Const->getAPIntValue().trunc(SplatWidth);
664 return SplatVal.
trunc(SplatWidth);
673 unsigned SplatWidth =
N.getScalarValueSizeInBits();
675 if (SplatVal->getBitWidth() <= SplatWidth)
677 if (SplatVal->isSplat(SplatWidth))
678 return SplatVal->trunc(SplatWidth);
683bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
690 ImmVal->getZExtValue(), Encoding))
693 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
697bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(
SDValue N,
SDValue &Imm,
700 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
701 N.getValueType().getScalarType().getSimpleVT(),
707bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(
SDValue N,
710 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal, Imm);
714bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(
SDValue N,
SDValue &Imm) {
719 int64_t ImmVal = ImmAPIntVal->getSExtValue();
720 if (ImmVal < -128 || ImmVal > 127)
723 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
727bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(
SDValue N,
SDValue &Imm) {
732 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
736 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
740bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
742 std::vector<SDValue> &OutOps) {
743 switch(ConstraintID) {
746 case InlineAsm::ConstraintCode::m:
747 case InlineAsm::ConstraintCode::o:
748 case InlineAsm::ConstraintCode::Q:
754 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
756 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
757 dl,
Op.getValueType(),
759 OutOps.push_back(NewOp);
778 uint64_t Immed =
N.getNode()->getAsZExtVal();
788 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
789 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
806 uint64_t Immed =
N.getNode()->getAsZExtVal();
814 if (
N.getValueType() == MVT::i32)
815 Immed = ~((uint32_t)Immed) + 1;
817 Immed = ~Immed + 1ULL;
818 if (Immed & 0xFFFFFFFFFF000000ULL)
821 Immed &= 0xFFFFFFULL;
822 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
829 switch (
N.getOpcode()) {
855 unsigned ShiftVal = CSD->getZExtValue();
873bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
876 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
881 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
905 EVT VT =
N.getValueType();
906 if (VT != MVT::i32 && VT != MVT::i64)
909 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
915 unsigned LHSOpcode =
LHS->getOpcode();
929 unsigned LowZBits, MaskLen;
933 unsigned BitWidth =
N.getValueSizeInBits();
940 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
943 NewShiftC = LowZBits - ShiftAmtC;
944 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
950 NewShiftC = LowZBits + ShiftAmtC;
963 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
965 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
969 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
971 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
972 NewShiftAmt, BitWidthMinus1),
975 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
989 SrcVT =
N.getOperand(0).getValueType();
991 if (!IsLoadStore && SrcVT == MVT::i8)
993 else if (!IsLoadStore && SrcVT == MVT::i16)
995 else if (SrcVT == MVT::i32)
997 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1002 EVT SrcVT =
N.getOperand(0).getValueType();
1003 if (!IsLoadStore && SrcVT == MVT::i8)
1005 else if (!IsLoadStore && SrcVT == MVT::i16)
1007 else if (SrcVT == MVT::i32)
1009 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1034bool AArch64DAGToDAGISel::isWorthNegatingImm(
SDValue V)
const {
1037 EVT VT =
V.getValueType();
1038 assert((VT == MVT::i32 || VT == MVT::i64) &&
"invalid type");
1049 return NewCost.
size() < OrigCost.
size();
1056bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
1059 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1064 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1065 V.getConstantOperandVal(1) <= 4 &&
1078bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
1080 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1090 unsigned BitSize =
N.getValueSizeInBits();
1091 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1094 Reg =
N.getOperand(0);
1095 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1096 return isWorthFoldingALU(
N,
true);
1107 if (
N.getValueType() == MVT::i32)
1115template<
signed Low,
signed High,
signed Scale>
1121 if ((MulImm % std::abs(Scale)) == 0) {
1122 int64_t RDVLImm = MulImm / Scale;
1123 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1124 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1133template <
signed Low,
signed High>
1134bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
1139 if (MulImm >=
Low && MulImm <=
High) {
1140 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1151 unsigned ShiftVal = 0;
1166 Reg =
N.getOperand(0).getOperand(0);
1178 Op =
Op->getOperand(0);
1180 Op.getOperand(0).getValueType().isFixedLengthVector())
1184 Reg =
N.getOperand(0);
1189 unsigned Opc =
N.getOpcode();
1207 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1209 return isWorthFoldingALU(
N);
1216 unsigned ShiftVal = 0;
1230 Reg =
N.getOperand(0);
1231 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1233 return isWorthFoldingALU(
N);
1242 for (
auto *
User :
N->users()) {
1269bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1270 unsigned BW,
unsigned Size,
1274 const DataLayout &
DL = CurDAG->getDataLayout();
1275 const TargetLowering *TLI = getTargetLowering();
1279 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1285 if (CurDAG->isBaseWithConstantOffset(
N)) {
1288 int64_t RHSC =
RHS->getSExtValue();
1290 int64_t
Range = 0x1LL << (BW - 1);
1292 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1293 RHSC < (
Range << Scale)) {
1294 Base =
N.getOperand(0);
1299 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1304 uint64_t RHSC =
RHS->getZExtValue();
1306 uint64_t
Range = 0x1ULL << BW;
1308 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1309 Base =
N.getOperand(0);
1314 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1325 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1332bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1335 const DataLayout &
DL = CurDAG->getDataLayout();
1336 const TargetLowering *TLI = getTargetLowering();
1340 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1345 GlobalAddressSDNode *GAN =
1347 Base =
N.getOperand(0);
1357 if (CurDAG->isBaseWithConstantOffset(
N)) {
1359 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1362 Base =
N.getOperand(0);
1367 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1375 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1383 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1392bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1395 if (!CurDAG->isBaseWithConstantOffset(
N))
1398 int64_t RHSC =
RHS->getSExtValue();
1399 if (RHSC >= -256 && RHSC < 256) {
1400 Base =
N.getOperand(0);
1403 const TargetLowering *TLI = getTargetLowering();
1404 Base = CurDAG->getTargetFrameIndex(
1407 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1417 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1424bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1444 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1450 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1453 return isWorthFoldingAddr(
N,
Size);
1456bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1474 const SDNode *
Node =
N.getNode();
1475 for (SDNode *UI :
Node->users()) {
1481 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1484 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1487 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1492 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1495 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1500 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1504 if (IsExtendedRegisterWorthFolding &&
1511 if (isWorthFoldingAddr(
LHS,
Size))
1516 if (IsExtendedRegisterWorthFolding &&
1523 if (isWorthFoldingAddr(
RHS,
Size))
1535 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1538 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1540 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1541 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1545bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1558 const SDNode *
Node =
N.getNode();
1559 for (SDNode *UI :
Node->users()) {
1576 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1586 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1593 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1596 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1599 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1604 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1607 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1614 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1615 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1621 static const unsigned RegClassIDs[] = {
1622 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1623 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1624 AArch64::dsub2, AArch64::dsub3};
1630 static const unsigned RegClassIDs[] = {
1631 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1632 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1633 AArch64::qsub2, AArch64::qsub3};
1639 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1640 AArch64::ZPR3RegClassID,
1641 AArch64::ZPR4RegClassID};
1642 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1643 AArch64::zsub2, AArch64::zsub3};
1653 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1654 AArch64::ZPR4Mul4RegClassID};
1655 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1656 AArch64::zsub2, AArch64::zsub3};
1661 const unsigned RegClassIDs[],
1662 const unsigned SubRegs[]) {
1665 if (Regs.
size() == 1)
1676 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1679 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1680 Ops.push_back(Regs[i]);
1681 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1685 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1689void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1692 EVT VT =
N->getValueType(0);
1694 unsigned ExtOff = isExt;
1697 unsigned Vec0Off = ExtOff + 1;
1703 Ops.push_back(
N->getOperand(1));
1704 Ops.push_back(RegSeq);
1705 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1706 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1709static std::tuple<SDValue, SDValue>
1730 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1735 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1737 return std::make_tuple(
1742void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1747 SDValue AUTDisc =
N->getOperand(3);
1750 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1752 SDValue AUTAddrDisc, AUTConstDisc;
1753 std::tie(AUTConstDisc, AUTAddrDisc) =
1757 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1759 if (
N->getNumOperands() > 4)
1760 Ops.push_back(
N->getOperand(4));
1763 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1764 ReplaceNode(
N, AUT);
1766 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1767 AArch64::X16, Val,
SDValue());
1770 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1771 ReplaceNode(
N, AUT);
1775void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1785 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1790 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1791 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1793 SDValue AUTAddrDisc, AUTConstDisc;
1794 std::tie(AUTConstDisc, AUTAddrDisc) =
1797 SDValue PACAddrDisc, PACConstDisc;
1798 std::tie(PACConstDisc, PACAddrDisc) =
1801 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1802 AArch64::X16, Val,
SDValue());
1805 SDValue Addend =
N->getOperand(OffsetBase + 6);
1806 SDValue IncomingChain =
N->getOperand(0);
1807 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1808 PACKey, PACConstDisc, PACAddrDisc,
1809 Addend, IncomingChain, X16Copy.
getValue(1)};
1811 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1812 MVT::i64, MVT::Other,
Ops);
1813 ReplaceNode(
N, AUTRELLOADPAC);
1815 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1816 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1818 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1819 ReplaceNode(
N, AUTPAC);
1823void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *
N) {
1835 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1836 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1838 SDValue PACAddrDisc, PACConstDisc;
1839 std::tie(PACConstDisc, PACAddrDisc) =
1842 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1843 AArch64::X17, Val,
SDValue());
1844 SDValue X16Copy = CurDAG->getCopyToReg(
1845 CurDAG->getEntryNode(),
DL, AArch64::X16, AUTDisc, X17Copy.
getValue(1));
1846 SDValue X15Copy = CurDAG->getCopyToReg(
1847 CurDAG->getEntryNode(),
DL, AArch64::X15, AUTPC, X16Copy.
getValue(1));
1849 SDValue Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1852 CurDAG->getMachineNode(AArch64::AUTPCPAC,
DL, MVT::i64,
Ops);
1853 ReplaceNode(
N, AUTPCPAC);
1856bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1858 if (
LD->isUnindexed())
1860 EVT VT =
LD->getMemoryVT();
1861 EVT DstVT =
N->getValueType(0);
1865 int OffsetVal = (int)
OffsetOp->getZExtValue();
1870 unsigned Opcode = 0;
1873 bool InsertTo64 =
false;
1875 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1876 else if (VT == MVT::i32) {
1878 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1880 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1882 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1888 }
else if (VT == MVT::i16) {
1890 if (DstVT == MVT::i64)
1891 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1893 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1895 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1896 InsertTo64 = DstVT == MVT::i64;
1901 }
else if (VT == MVT::i8) {
1903 if (DstVT == MVT::i64)
1904 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1906 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1908 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1909 InsertTo64 = DstVT == MVT::i64;
1914 }
else if (VT == MVT::f16) {
1915 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1916 }
else if (VT == MVT::bf16) {
1917 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1918 }
else if (VT == MVT::f32) {
1919 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1920 }
else if (VT == MVT::f64 ||
1922 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1924 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1926 if (IsPre || OffsetVal != 8)
1930 Opcode = AArch64::LD1Onev8b_POST;
1933 Opcode = AArch64::LD1Onev4h_POST;
1936 Opcode = AArch64::LD1Onev2s_POST;
1939 Opcode = AArch64::LD1Onev1d_POST;
1945 if (IsPre || OffsetVal != 16)
1949 Opcode = AArch64::LD1Onev16b_POST;
1952 Opcode = AArch64::LD1Onev8h_POST;
1955 Opcode = AArch64::LD1Onev4s_POST;
1958 Opcode = AArch64::LD1Onev2d_POST;
1970 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1971 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1973 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1983 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1984 LoadedVal =
SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
1985 MVT::i64, LoadedVal, SubReg),
1989 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1992 CurDAG->RemoveDeadNode(
N);
1996void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1997 unsigned SubRegIdx) {
1999 EVT VT =
N->getValueType(0);
2005 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2007 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2009 for (
unsigned i = 0; i < NumVecs; ++i)
2011 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2018 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2022 CurDAG->RemoveDeadNode(
N);
2025void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2026 unsigned Opc,
unsigned SubRegIdx) {
2028 EVT VT =
N->getValueType(0);
2035 const EVT ResTys[] = {MVT::i64,
2036 MVT::Untyped, MVT::Other};
2038 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2046 ReplaceUses(
SDValue(
N, 0), SuperReg);
2048 for (
unsigned i = 0; i < NumVecs; ++i)
2050 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2058 CurDAG->RemoveDeadNode(
N);
2064std::tuple<unsigned, SDValue, SDValue>
2065AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2071 SDValue NewOffset = OldOffset;
2073 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2074 N, OldBase, NewBase, NewOffset);
2078 const bool IsRegReg =
2079 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2082 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2095template <SelectTypeKind Kind>
2107 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2112 if (EltVT != MVT::i1)
2116 if (EltVT == MVT::bf16)
2118 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2148void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2151 if (
Imm->getZExtValue() > 1)
2155 EVT VT =
N->getValueType(0);
2157 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2160 for (
unsigned I = 0;
I < 2; ++
I)
2161 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2162 AArch64::psub0 +
I,
DL, VT, SuperReg));
2164 CurDAG->RemoveDeadNode(
N);
2167void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2169 EVT VT =
N->getValueType(0);
2173 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2176 for (
unsigned I = 0;
I < 2; ++
I)
2177 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2178 AArch64::psub0 +
I,
DL, VT, SuperReg));
2180 CurDAG->RemoveDeadNode(
N);
2183void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2185 EVT VT =
N->getValueType(0);
2189 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2191 for (
unsigned i = 0; i < NumVecs; ++i)
2192 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2193 AArch64::zsub0 + i,
DL, VT, SuperReg));
2195 CurDAG->RemoveDeadNode(
N);
2198void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2201 EVT VT =
N->getValueType(0);
2203 Ops.push_back(
N->getOperand(0));
2206 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2209 for (
unsigned i = 0; i < NumVecs; ++i)
2210 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2211 AArch64::zsub0 + i,
DL, VT, SuperReg));
2214 unsigned ChainIdx = NumVecs;
2216 CurDAG->RemoveDeadNode(
N);
2219void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2224 assert(Opcode != 0 &&
"Unexpected opcode");
2227 EVT VT =
N->getValueType(0);
2228 SDUse *OpsIter =
N->op_begin() + 1;
2231 auto GetMultiVecOperand = [&]() {
2234 return createZMulTuple(Regs);
2238 Ops.push_back(*OpsIter++);
2240 Ops.push_back(GetMultiVecOperand());
2242 Ops.push_back(GetMultiVecOperand());
2244 Ops.push_back(*OpsIter++);
2247 Ops.append(OpsIter,
N->op_end());
2249 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2251 for (
unsigned i = 0; i < NumVecs; ++i)
2252 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2253 AArch64::zsub0 + i,
DL, VT, SuperReg));
2255 CurDAG->RemoveDeadNode(
N);
2258void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2259 unsigned Scale,
unsigned Opc_ri,
2260 unsigned Opc_rr,
bool IsIntr) {
2261 assert(Scale < 5 &&
"Invalid scaling value.");
2263 EVT VT =
N->getValueType(0);
2270 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2271 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2277 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2279 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2281 for (
unsigned i = 0; i < NumVecs; ++i)
2282 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2283 AArch64::zsub0 + i,
DL, VT, SuperReg));
2286 unsigned ChainIdx = NumVecs;
2288 CurDAG->RemoveDeadNode(
N);
2291void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2296 assert(Scale < 4 &&
"Invalid scaling value.");
2298 EVT VT =
N->getValueType(0);
2306 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2312 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2314 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2316 for (
unsigned i = 0; i < NumVecs; ++i)
2317 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2318 AArch64::zsub0 + i,
DL, VT, SuperReg));
2321 unsigned ChainIdx = NumVecs;
2323 CurDAG->RemoveDeadNode(
N);
2326void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2328 if (
N->getValueType(0) != MVT::nxv4f32)
2330 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2333void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2334 unsigned NumOutVecs,
2338 if (
Imm->getZExtValue() > MaxImm)
2342 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2348 EVT VT =
Node->getValueType(0);
2351 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2354 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2355 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2356 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2359 unsigned ChainIdx = NumOutVecs;
2361 CurDAG->RemoveDeadNode(Node);
2364void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2365 unsigned NumIndexVecs) {
2366 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2367 "unexpected number of index vectors");
2369 constexpr unsigned FirstIndexOp = 3;
2370 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2372 if (!Imm ||
Imm->getZExtValue() > 1)
2378 unsigned Lane =
Imm->getZExtValue();
2379 unsigned IndexOp = FirstIndexOp;
2380 if (NumIndexVecs == 3)
2383 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2385 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2386 SDValue Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2389 EVT VT =
Node->getValueType(0);
2391 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2394 for (
unsigned I = 0;
I < 4; ++
I)
2395 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2396 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2398 CurDAG->RemoveDeadNode(Node);
2401void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2402 unsigned NumOutVecs,
2404 unsigned NumInVecs) {
2405 assert((NumInVecs == 2 || NumInVecs == 3) &&
2406 "unexpected number of input vectors");
2409 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2413 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2417 EVT VT =
Node->getValueType(0);
2420 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2423 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2424 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2425 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2428 CurDAG->RemoveDeadNode(Node);
2431void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2434 EVT VT =
N->getValueType(0);
2437 SDValue Zd = createZMulTuple(Regs);
2438 SDValue Zn =
N->getOperand(1 + NumVecs);
2439 SDValue Zm =
N->getOperand(2 + NumVecs);
2445 for (
unsigned i = 0; i < NumVecs; ++i)
2446 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2447 AArch64::zsub0 + i,
DL, VT, SuperReg));
2449 CurDAG->RemoveDeadNode(
N);
2479template <
unsigned MaxIdx,
unsigned Scale>
2480void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2481 unsigned BaseReg,
unsigned Op) {
2482 unsigned TileNum = 0;
2483 if (BaseReg != AArch64::ZA)
2484 TileNum =
N->getConstantOperandVal(2);
2490 if (BaseReg == AArch64::ZA)
2495 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2499 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2501 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2503 EVT VT =
N->getValueType(0);
2504 for (
unsigned I = 0;
I < NumVecs; ++
I)
2506 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2509 unsigned ChainIdx = NumVecs;
2511 CurDAG->RemoveDeadNode(
N);
2514void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2515 unsigned Op,
unsigned MaxIdx,
2516 unsigned Scale,
unsigned BaseReg) {
2521 if (BaseReg != AArch64::ZA)
2525 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2532 if (BaseReg != AArch64::ZA )
2533 Ops.push_back(
N->getOperand(2));
2536 Ops.push_back(
N->getOperand(0));
2537 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2539 EVT VT =
N->getValueType(0);
2540 for (
unsigned I = 0;
I < NumVecs; ++
I)
2542 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2546 unsigned ChainIdx = NumVecs;
2548 CurDAG->RemoveDeadNode(
N);
2551void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2552 unsigned NumOutVecs,
2556 EVT VT =
N->getValueType(0);
2557 unsigned NumInVecs =
N->getNumOperands() - 1;
2561 assert((NumInVecs == 2 || NumInVecs == 4) &&
2562 "Don't know how to handle multi-register input!");
2564 Ops.push_back(createZMulTuple(Regs));
2567 for (
unsigned I = 0;
I < NumInVecs;
I++)
2568 Ops.push_back(
N->getOperand(1 +
I));
2571 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2574 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2575 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2576 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2577 CurDAG->RemoveDeadNode(
N);
2580void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2583 EVT VT =
N->getOperand(2)->getValueType(0);
2591 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2600void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2601 unsigned Scale,
unsigned Opc_rr,
2607 SDValue RegSeq = createZTuple(Regs);
2613 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2614 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2620 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2629void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2632 EVT VT =
N->getOperand(2)->getValueType(0);
2633 const EVT ResTys[] = {MVT::i64,
2645 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2689void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2692 EVT VT =
N->getValueType(0);
2704 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2706 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2708 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2710 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2714 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2715 AArch64::qsub2, AArch64::qsub3 };
2716 for (
unsigned i = 0; i < NumVecs; ++i) {
2717 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2724 CurDAG->RemoveDeadNode(
N);
2727void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2730 EVT VT =
N->getValueType(0);
2742 const EVT ResTys[] = {MVT::i64,
2745 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2748 CurDAG->getTargetConstant(LaneNo, dl,
2753 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2765 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2766 AArch64::qsub2, AArch64::qsub3 };
2767 for (
unsigned i = 0; i < NumVecs; ++i) {
2768 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2778 CurDAG->RemoveDeadNode(
N);
2781void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2784 EVT VT =
N->getOperand(2)->getValueType(0);
2796 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2798 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2800 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2809void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2812 EVT VT =
N->getOperand(2)->getValueType(0);
2824 const EVT ResTys[] = {MVT::i64,
2827 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2829 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2833 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2844 unsigned &LSB,
unsigned &MSB,
2845 unsigned NumberOfIgnoredLowBits,
2846 bool BiggerPattern) {
2848 "N must be a AND operation to call this function");
2850 EVT VT =
N->getValueType(0);
2855 assert((VT == MVT::i32 || VT == MVT::i64) &&
2856 "Type checking must have been done before calling this function");
2870 const SDNode *Op0 =
N->getOperand(0).getNode();
2877 if (AndImm & (AndImm + 1))
2880 bool ClampMSB =
false;
2900 ClampMSB = (VT == MVT::i32);
2901 }
else if (BiggerPattern) {
2907 Opd0 =
N->getOperand(0);
2913 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2916 <<
": Found large shift immediate, this should not happen\n"));
2930 MSB = MSB > 31 ? 31 : MSB;
2932 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2937 SDValue &Opd0,
unsigned &Immr,
2941 EVT VT =
N->getValueType(0);
2943 assert((VT == MVT::i32 || VT == MVT::i64) &&
2944 "Type checking must have been done before calling this function");
2948 Op =
Op->getOperand(0);
2949 VT =
Op->getValueType(0);
2958 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2962 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2963 Opd0 =
Op.getOperand(0);
2965 Imms = ShiftImm + Width - 1;
2993 Opd0 =
N->getOperand(0).getOperand(0);
3003 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3010 unsigned &Immr,
unsigned &Imms,
3011 bool BiggerPattern) {
3013 "N must be a SHR/SRA operation to call this function");
3015 EVT VT =
N->getValueType(0);
3020 assert((VT == MVT::i32 || VT == MVT::i64) &&
3021 "Type checking must have been done before calling this function");
3031 Opd0 =
N->getOperand(0).getOperand(0);
3032 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3038 Opd0 =
N->getOperand(0).getOperand(0);
3041 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3042 }
else if (BiggerPattern) {
3046 Opd0 =
N->getOperand(0);
3055 <<
": Found large shift immediate, this should not happen\n"));
3064 "bad amount in shift node!");
3065 int immr = SrlImm - ShlImm;
3070 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3072 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3076bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
3079 EVT VT =
N->getValueType(0);
3080 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
3081 if (VT != MVT::i64 || NarrowVT != MVT::i32)
3092 unsigned Immr = ShiftImm;
3094 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3095 CurDAG->getTargetConstant(Imms, dl, VT)};
3096 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
3101 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3102 unsigned NumberOfIgnoredLowBits = 0,
3103 bool BiggerPattern =
false) {
3104 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3107 switch (
N->getOpcode()) {
3109 if (!
N->isMachineOpcode())
3114 NumberOfIgnoredLowBits, BiggerPattern);
3123 unsigned NOpc =
N->getMachineOpcode();
3127 case AArch64::SBFMWri:
3128 case AArch64::UBFMWri:
3129 case AArch64::SBFMXri:
3130 case AArch64::UBFMXri:
3132 Opd0 =
N->getOperand(0);
3133 Immr =
N->getConstantOperandVal(1);
3134 Imms =
N->getConstantOperandVal(2);
3141bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3142 unsigned Opc, Immr, Imms;
3147 EVT VT =
N->getValueType(0);
3152 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3153 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3154 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3156 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3157 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3163 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3164 CurDAG->getTargetConstant(Imms, dl, VT)};
3165 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3174 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3175 assert((VT == MVT::i32 || VT == MVT::i64) &&
3176 "i32 or i64 mask type expected!");
3180 APInt SignificantDstMask =
3184 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3185 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3218 APInt OpUsefulBits(UsefulBits);
3222 OpUsefulBits <<= MSB - Imm + 1;
3227 OpUsefulBits <<= Imm;
3229 OpUsefulBits <<= MSB + 1;
3232 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
3238 UsefulBits &= OpUsefulBits;
3255 APInt Mask(UsefulBits);
3256 Mask.clearAllBits();
3264 Mask.lshrInPlace(ShiftAmt);
3270 Mask.lshrInPlace(ShiftAmt);
3286 APInt OpUsefulBits(UsefulBits);
3300 OpUsefulBits <<= Width;
3303 if (
Op.getOperand(1) == Orig) {
3305 Mask = ResultUsefulBits & OpUsefulBits;
3309 if (
Op.getOperand(0) == Orig)
3311 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3317 OpUsefulBits <<= Width;
3319 OpUsefulBits <<= LSB;
3321 if (
Op.getOperand(1) == Orig) {
3323 Mask = ResultUsefulBits & OpUsefulBits;
3324 Mask.lshrInPlace(LSB);
3327 if (
Op.getOperand(0) == Orig)
3328 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3345 case AArch64::ANDSWri:
3346 case AArch64::ANDSXri:
3347 case AArch64::ANDWri:
3348 case AArch64::ANDXri:
3352 case AArch64::UBFMWri:
3353 case AArch64::UBFMXri:
3356 case AArch64::ORRWrs:
3357 case AArch64::ORRXrs:
3362 case AArch64::BFMWri:
3363 case AArch64::BFMXri:
3366 case AArch64::STRBBui:
3367 case AArch64::STURBBi:
3373 case AArch64::STRHHui:
3374 case AArch64::STURHHi:
3387 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3389 UsefulBits =
APInt(Bitwidth, 0);
3398 UsersUsefulBits |= UsefulBitsForUse;
3403 UsefulBits &= UsersUsefulBits;
3413 EVT VT =
Op.getValueType();
3416 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3419 if (ShlAmount > 0) {
3422 UBFMOpc, dl, VT,
Op,
3427 assert(ShlAmount < 0 &&
"expected right shift");
3428 int ShrAmount = -ShlAmount;
3440 const uint64_t NonZeroBits,
3447 const uint64_t NonZeroBits,
3454 bool BiggerPattern,
SDValue &Src,
3455 int &DstLSB,
int &Width) {
3456 EVT VT =
Op.getValueType();
3469 switch (
Op.getOpcode()) {
3474 NonZeroBits, Src, DstLSB, Width);
3477 NonZeroBits, Src, DstLSB, Width);
3490 EVT VT =
Op.getValueType();
3491 assert((VT == MVT::i32 || VT == MVT::i64) &&
3492 "Caller guarantees VT is one of i32 or i64");
3505 assert((~AndImm & NonZeroBits) == 0 &&
3506 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3535 if (!BiggerPattern && !AndOp0.
hasOneUse())
3554 <<
"Found large Width in bit-field-positioning -- this indicates no "
3555 "proper combining / constant folding was performed\n");
3564 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3579 "Op.getNode() should be a SHL node to call this function");
3581 "Op.getNode() should shift ShlImm to call this function");
3588 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3612 EVT VT =
Op.getValueType();
3613 assert((VT == MVT::i32 || VT == MVT::i64) &&
3614 "Caller guarantees that type is i32 or i64");
3621 if (!BiggerPattern && !
Op.hasOneUse())
3630 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3638 assert(VT == MVT::i32 || VT == MVT::i64);
3649 EVT VT =
N->getValueType(0);
3650 if (VT != MVT::i32 && VT != MVT::i64)
3668 if (!
And.hasOneUse() ||
3685 if ((OrImm & NotKnownZero) != 0) {
3697 unsigned ImmS = Width - 1;
3703 bool IsBFI = LSB != 0;
3708 unsigned OrChunks = 0, BFIChunks = 0;
3709 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3710 if (((OrImm >> Shift) & 0xFFFF) != 0)
3712 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3715 if (BFIChunks > OrChunks)
3721 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3729 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3738 if (!Dst.hasOneUse())
3741 EVT VT = Dst.getValueType();
3742 assert((VT == MVT::i32 || VT == MVT::i64) &&
3743 "Caller should guarantee that VT is one of i32 or i64");
3771 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3772 unsigned MaskWidth =
3775 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3781 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3782 ShiftedOperand =
SDValue(UBFMNode, 0);
3811 const bool BiggerPattern) {
3812 EVT VT =
N->getValueType(0);
3813 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3814 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3815 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3816 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3817 assert((VT == MVT::i32 || VT == MVT::i64) &&
3818 "Expect result type to be i32 or i64 since N is combinable to BFM");
3825 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3828 if (BiggerPattern) {
3851 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3913 EVT VT =
N->getValueType(0);
3914 if (VT != MVT::i32 && VT != MVT::i64)
3922 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3923 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3943 for (
int I = 0;
I < 4; ++
I) {
3946 unsigned ImmR, ImmS;
3947 bool BiggerPattern =
I / 2;
3948 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3950 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3956 NumberOfIgnoredLowBits, BiggerPattern)) {
3959 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3960 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3965 Width = ImmS - ImmR + 1;
3976 Src, DstLSB, Width)) {
3984 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3994 APInt BitsToBeInserted =
3997 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4021 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4054 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4056 if (Src->hasOneUse() &&
4059 Src = Src->getOperand(0);
4069 unsigned ImmS = Width - 1;
4075 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4083bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4092 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4105bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4109 EVT VT =
N->getValueType(0);
4110 if (VT != MVT::i32 && VT != MVT::i64)
4116 Op0, DstLSB, Width))
4122 unsigned ImmS = Width - 1;
4125 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4126 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4127 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4128 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4134bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4135 EVT VT =
N->getValueType(0);
4138 switch (
N->getOpcode()) {
4140 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4143 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4146 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4149 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4157 if (VT == MVT::i32) {
4160 }
else if (VT == MVT::i64) {
4166 SDValue ShiftAmt =
N->getOperand(1);
4186 (Add0Imm %
Size == 0)) {
4192 if (SubVT == MVT::i32) {
4193 NegOpc = AArch64::SUBWrr;
4194 ZeroReg = AArch64::WZR;
4196 assert(SubVT == MVT::i64);
4197 NegOpc = AArch64::SUBXrr;
4198 ZeroReg = AArch64::XZR;
4201 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4202 MachineSDNode *Neg =
4203 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4204 NewShiftAmt =
SDValue(Neg, 0);
4212 if (SubVT == MVT::i32) {
4213 NotOpc = AArch64::ORNWrr;
4214 ZeroReg = AArch64::WZR;
4216 assert(SubVT == MVT::i64);
4217 NotOpc = AArch64::ORNXrr;
4218 ZeroReg = AArch64::XZR;
4221 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4222 MachineSDNode *
Not =
4223 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4245 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4246 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4247 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4248 NewShiftAmt, SubReg);
4249 NewShiftAmt =
SDValue(Ext, 0);
4253 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4260 bool isReciprocal) {
4263 FVal = CN->getValueAPF();
4266 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4276 if (
unsigned FBits =
4289 bool isReciprocal) {
4290 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4291 N.getValueType().getScalarSizeInBits() ==
4292 N.getOperand(0).getValueType().getScalarSizeInBits())
4293 N =
N.getOperand(0);
4295 auto ImmToFloat = [RegWidth](
APInt Imm) {
4309 switch (
N->getOpcode()) {
4310 case AArch64ISD::MOVIshift:
4311 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4312 <<
N.getConstantOperandVal(1)));
4314 case AArch64ISD::FMOV:
4315 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4317 case AArch64ISD::DUP:
4319 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4327 if (
unsigned FBits =
4336bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4337 unsigned RegWidth) {
4342bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
4343 unsigned RegWidth) {
4345 CurDAG,
N, FixedPos, RegWidth,
false);
4348bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(
SDValue N,
4350 unsigned RegWidth) {
4352 CurDAG,
N, FixedPos, RegWidth,
true);
4355bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4357 unsigned RegWidth) {
4367 RegString.
split(Fields,
':');
4369 if (Fields.
size() == 1)
4373 &&
"Invalid number of fields in read register string");
4376 bool AllIntFields =
true;
4380 AllIntFields &= !
Field.getAsInteger(10, IntField);
4381 Ops.push_back(IntField);
4385 "Unexpected non-integer value in special register string.");
4390 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4398bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4400 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4403 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4405 unsigned Opcode64Bit = AArch64::MRS;
4410 const auto *TheReg =
4411 AArch64SysReg::lookupSysRegByName(RegString->getString());
4412 if (TheReg && TheReg->Readable &&
4413 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4414 Imm = TheReg->Encoding;
4420 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4421 Opcode64Bit = AArch64::ADR;
4430 RegString->getString());
4431 unsigned PseudoOp = 0;
4432 if (AArch64::GPR64RegClass.
contains(PReg))
4433 PseudoOp = AArch64::READ_REGISTER_GPR64;
4434 else if (AArch64::FPR64RegClass.
contains(PReg))
4435 PseudoOp = AArch64::READ_REGISTER_FPR64;
4436 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4437 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4438 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4447 SDValue InChain =
N->getOperand(0);
4448 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4449 if (!ReadIs128Bit) {
4450 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4451 {SysRegImm, InChain});
4453 SDNode *MRRS = CurDAG->getMachineNode(
4455 {MVT::Untyped , MVT::Other },
4456 {SysRegImm, InChain});
4460 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4462 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4468 ReplaceUses(
SDValue(
N, 2), OutChain);
4477bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4479 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4482 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4484 if (!WriteIs128Bit) {
4490 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4493 "Expected a constant integer expression.");
4494 unsigned Reg = PMapper->Encoding;
4495 uint64_t Immed =
N->getConstantOperandVal(2);
4496 CurDAG->SelectNodeTo(
4497 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4498 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4504 if (trySelectPState(
4505 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4506 AArch64::MSRpstateImm4))
4508 if (trySelectPState(
4509 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4510 AArch64::MSRpstateImm1))
4519 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4520 if (TheReg && TheReg->Writeable &&
4521 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4522 Imm = TheReg->Encoding;
4532 RegString->getString());
4533 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4534 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4535 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4536 N->getOperand(2).getValueType() == MVT::i64) {
4538 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4539 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4540 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4541 MVT::Other, {RegOp,
Copy});
4543 CurDAG->RemoveDeadNode(
N);
4551 if (!WriteIs128Bit) {
4552 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4553 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4554 N->getOperand(2), InChain);
4558 SDNode *Pair = CurDAG->getMachineNode(
4559 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4560 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4563 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4565 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4567 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4568 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4576bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4581 if (Subtarget->hasLSE())
return false;
4583 if (MemTy == MVT::i8)
4584 Opcode = AArch64::CMP_SWAP_8;
4585 else if (MemTy == MVT::i16)
4586 Opcode = AArch64::CMP_SWAP_16;
4587 else if (MemTy == MVT::i32)
4588 Opcode = AArch64::CMP_SWAP_32;
4589 else if (MemTy == MVT::i64)
4590 Opcode = AArch64::CMP_SWAP_64;
4594 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4595 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4597 SDNode *CmpSwap = CurDAG->getMachineNode(
4599 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4606 CurDAG->RemoveDeadNode(
N);
4611bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4612 SDValue &Shift,
bool Negate) {
4619 return SelectSVEAddSubImm(SDLoc(
N), Val, VT, Imm, Shift, Negate);
4622bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4631 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4638 if ((Val & ~0xff) == 0) {
4639 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4644 if ((Val & ~0xff00) == 0) {
4645 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4657bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4681 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4682 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4689 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4690 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4694 if (Val <= 65280 && Val % 256 == 0) {
4695 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4696 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4707bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4717 int32_t ImmVal, ShiftVal;
4722 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4723 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4727bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4729 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(), Imm);
4733bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4736 if (ImmVal >= -128 && ImmVal < 128) {
4737 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4743bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4745 uint64_t ImmVal = CNode->getZExtValue();
4755 ImmVal &= 0xFFFFFFFF;
4764 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4771bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4775 ImmVal = CI->getZExtValue();
4777 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4788 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4797bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4798 uint64_t
High,
bool AllowSaturation,
4801 uint64_t ImmVal = CN->getZExtValue();
4808 if (ImmVal >
High) {
4809 if (!AllowSaturation)
4814 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4821bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4835 const TargetLowering *TLI = getTargetLowering();
4838 SDValue FiOp = CurDAG->getTargetFrameIndex(
4840 int TagOffset =
N->getConstantOperandVal(3);
4842 SDNode *Out = CurDAG->getMachineNode(
4843 AArch64::TAGPstack,
DL, MVT::i64,
4844 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4845 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4846 ReplaceNode(
N, Out);
4850void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4852 "llvm.aarch64.tagp third argument must be an immediate");
4853 if (trySelectStackSlotTagP(
N))
4860 int TagOffset =
N->getConstantOperandVal(3);
4861 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4862 {
N->getOperand(1),
N->getOperand(2)});
4863 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4864 {
SDValue(N1, 0),
N->getOperand(2)});
4865 SDNode *N3 = CurDAG->getMachineNode(
4866 AArch64::ADDG,
DL, MVT::i64,
4867 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4868 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4872bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4876 if (
N->getConstantOperandVal(2) != 0)
4878 if (!
N->getOperand(0).isUndef())
4882 EVT VT =
N->getValueType(0);
4883 EVT InVT =
N->getOperand(1).getValueType();
4894 "Expected to insert into a packed scalable vector!");
4897 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4898 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4899 N->getOperand(1), RC));
4903bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4907 if (
N->getConstantOperandVal(1) != 0)
4911 EVT VT =
N->getValueType(0);
4912 EVT InVT =
N->getOperand(0).getValueType();
4923 "Expected to extract from a packed scalable vector!");
4926 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4927 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4928 N->getOperand(0), RC));
4932bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4938 EVT VT =
N->getValueType(0);
4951 (Subtarget->hasSVE2() ||
4952 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4953 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4956 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4960 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4961 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4962 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4969 bool IsXOROperand =
true;
4971 IsXOROperand =
false;
4977 APInt ShlAmt, ShrAmt;
4985 if (!IsXOROperand) {
4987 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4990 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4991 SDNode *SubRegToReg =
4992 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
5003 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5004 AArch64::XAR_ZZZI_D})) {
5005 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5030 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5040 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5048 bool IsXOROperand =
true;
5050 IsXOROperand =
false;
5053 R1 =
XOR.getOperand(0);
5054 R2 =
XOR.getOperand(1);
5064 if (ShAmt + HsAmt != VTSizeInBits)
5067 if (!IsXOROperand) {
5070 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5079 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5085 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5086 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5088 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5091 if (
R2.getValueType() == VT)
5092 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5097 SDValue SubReg = CurDAG->getTargetConstant(
5100 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5105 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5111 SDNode *XAR =
nullptr;
5115 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5116 AArch64::XAR_ZZZI_D}))
5117 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5119 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5122 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5128 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5129 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5132 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5133 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5136 SDValue SubReg = CurDAG->getTargetConstant(
5139 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5143 ReplaceNode(
N, XAR);
5150 assert(VT == MVT::i32 || VT == MVT::i64);
5152 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5155void AArch64DAGToDAGISel::Select(SDNode *Node) {
5157 if (
Node->isMachineOpcode()) {
5159 Node->setNodeId(-1);
5164 EVT VT =
Node->getValueType(0);
5166 switch (
Node->getOpcode()) {
5171 if (SelectCMP_SWAP(Node))
5176 case AArch64ISD::MRRS:
5177 if (tryReadRegister(Node))
5182 case AArch64ISD::MSRR:
5183 if (tryWriteRegister(Node))
5190 if (tryIndexedLoad(Node))
5199 if (tryBitfieldExtractOp(Node))
5201 if (tryBitfieldInsertInZeroOp(Node))
5206 if (tryShiftAmountMod(Node))
5211 if (tryBitfieldExtractOpFromSExt(Node))
5216 if (tryBitfieldInsertOp(Node))
5218 if (trySelectXAR(Node))
5223 if (trySelectCastScalableToFixedLengthVector(Node))
5229 if (trySelectCastFixedLengthToScalableVector(Node))
5234 case AArch64ISD::CSEL:
5235 if (tryFoldCselToFMaxMin(Node))
5243 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5254 const TargetLowering *TLI = getTargetLowering();
5255 SDValue TFI = CurDAG->getTargetFrameIndex(
5258 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5259 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5260 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5264 unsigned IntNo =
Node->getConstantOperandVal(1);
5268 case Intrinsic::aarch64_gcsss: {
5272 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5274 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5275 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5276 MVT::Other, Zero,
SDValue(SS1, 0));
5277 ReplaceNode(Node, SS2);
5280 case Intrinsic::aarch64_ldaxp:
5281 case Intrinsic::aarch64_ldxp: {
5283 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5288 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5289 MVT::Other, MemAddr, Chain);
5292 MachineMemOperand *MemOp =
5295 ReplaceNode(Node, Ld);
5298 case Intrinsic::aarch64_stlxp:
5299 case Intrinsic::aarch64_stxp: {
5301 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5309 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5311 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5313 MachineMemOperand *MemOp =
5317 ReplaceNode(Node, St);
5320 case Intrinsic::aarch64_neon_ld1x2:
5321 if (VT == MVT::v8i8) {
5322 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5324 }
else if (VT == MVT::v16i8) {
5325 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5327 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5328 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5330 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5331 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5333 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5334 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5336 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5337 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5339 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5340 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5342 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5343 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5347 case Intrinsic::aarch64_neon_ld1x3:
5348 if (VT == MVT::v8i8) {
5349 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5351 }
else if (VT == MVT::v16i8) {
5352 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5354 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5355 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5357 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5358 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5360 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5361 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5363 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5364 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5366 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5367 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5369 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5370 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5374 case Intrinsic::aarch64_neon_ld1x4:
5375 if (VT == MVT::v8i8) {
5376 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5378 }
else if (VT == MVT::v16i8) {
5379 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5381 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5382 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5384 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5385 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5387 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5388 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5390 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5391 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5393 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5394 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5396 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5397 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5401 case Intrinsic::aarch64_neon_ld2:
5402 if (VT == MVT::v8i8) {
5403 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5405 }
else if (VT == MVT::v16i8) {
5406 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5408 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5409 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5411 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5412 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5414 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5415 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5417 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5418 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5420 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5421 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5423 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5424 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5428 case Intrinsic::aarch64_neon_ld3:
5429 if (VT == MVT::v8i8) {
5430 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5432 }
else if (VT == MVT::v16i8) {
5433 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5435 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5436 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5438 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5439 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5441 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5442 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5444 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5445 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5447 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5448 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5450 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5451 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5455 case Intrinsic::aarch64_neon_ld4:
5456 if (VT == MVT::v8i8) {
5457 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5459 }
else if (VT == MVT::v16i8) {
5460 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5462 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5463 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5465 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5466 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5468 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5469 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5471 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5472 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5474 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5475 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5477 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5478 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5482 case Intrinsic::aarch64_neon_ld2r:
5483 if (VT == MVT::v8i8) {
5484 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5486 }
else if (VT == MVT::v16i8) {
5487 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5489 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5490 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5492 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5493 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5495 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5496 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5498 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5499 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5501 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5502 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5504 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5505 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5509 case Intrinsic::aarch64_neon_ld3r:
5510 if (VT == MVT::v8i8) {
5511 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5513 }
else if (VT == MVT::v16i8) {
5514 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5516 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5517 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5519 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5520 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5522 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5523 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5525 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5526 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5528 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5529 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5531 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5532 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5536 case Intrinsic::aarch64_neon_ld4r:
5537 if (VT == MVT::v8i8) {
5538 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5540 }
else if (VT == MVT::v16i8) {
5541 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5543 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5544 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5546 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5547 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5549 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5550 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5552 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5553 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5555 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5556 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5558 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5559 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5563 case Intrinsic::aarch64_neon_ld2lane:
5564 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5565 SelectLoadLane(Node, 2, AArch64::LD2i8);
5567 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5568 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5569 SelectLoadLane(Node, 2, AArch64::LD2i16);
5571 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5573 SelectLoadLane(Node, 2, AArch64::LD2i32);
5575 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5577 SelectLoadLane(Node, 2, AArch64::LD2i64);
5581 case Intrinsic::aarch64_neon_ld3lane:
5582 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5583 SelectLoadLane(Node, 3, AArch64::LD3i8);
5585 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5586 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5587 SelectLoadLane(Node, 3, AArch64::LD3i16);
5589 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5591 SelectLoadLane(Node, 3, AArch64::LD3i32);
5593 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5595 SelectLoadLane(Node, 3, AArch64::LD3i64);
5599 case Intrinsic::aarch64_neon_ld4lane:
5600 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5601 SelectLoadLane(Node, 4, AArch64::LD4i8);
5603 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5604 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5605 SelectLoadLane(Node, 4, AArch64::LD4i16);
5607 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5609 SelectLoadLane(Node, 4, AArch64::LD4i32);
5611 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5613 SelectLoadLane(Node, 4, AArch64::LD4i64);
5617 case Intrinsic::aarch64_ld64b:
5618 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5620 case Intrinsic::aarch64_sve_ld2q_sret: {
5621 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5624 case Intrinsic::aarch64_sve_ld3q_sret: {
5625 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5628 case Intrinsic::aarch64_sve_ld4q_sret: {
5629 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5632 case Intrinsic::aarch64_sve_ld2_sret: {
5633 if (VT == MVT::nxv16i8) {
5634 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5637 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5638 VT == MVT::nxv8bf16) {
5639 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5642 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5643 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5646 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5647 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5653 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5654 if (VT == MVT::nxv16i8) {
5655 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5656 SelectContiguousMultiVectorLoad(
5657 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5658 else if (Subtarget->hasSVE2p1())
5659 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5664 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5665 VT == MVT::nxv8bf16) {
5666 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5667 SelectContiguousMultiVectorLoad(
5668 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5669 else if (Subtarget->hasSVE2p1())
5670 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5675 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5676 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5677 SelectContiguousMultiVectorLoad(
5678 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5679 else if (Subtarget->hasSVE2p1())
5680 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5685 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5686 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5687 SelectContiguousMultiVectorLoad(
5688 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5689 else if (Subtarget->hasSVE2p1())
5690 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5698 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5699 if (VT == MVT::nxv16i8) {
5700 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5701 SelectContiguousMultiVectorLoad(
5702 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5703 else if (Subtarget->hasSVE2p1())
5704 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5709 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5710 VT == MVT::nxv8bf16) {
5711 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5712 SelectContiguousMultiVectorLoad(
5713 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5714 else if (Subtarget->hasSVE2p1())
5715 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5720 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5721 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5722 SelectContiguousMultiVectorLoad(
5723 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5724 else if (Subtarget->hasSVE2p1())
5725 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5730 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5731 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5732 SelectContiguousMultiVectorLoad(
5733 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5734 else if (Subtarget->hasSVE2p1())
5735 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5743 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5744 if (VT == MVT::nxv16i8) {
5745 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5746 SelectContiguousMultiVectorLoad(Node, 2, 0,
5747 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5748 AArch64::LDNT1B_2Z_PSEUDO);
5749 else if (Subtarget->hasSVE2p1())
5750 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5751 AArch64::LDNT1B_2Z);
5755 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5756 VT == MVT::nxv8bf16) {
5757 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5758 SelectContiguousMultiVectorLoad(Node, 2, 1,
5759 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5760 AArch64::LDNT1H_2Z_PSEUDO);
5761 else if (Subtarget->hasSVE2p1())
5762 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5763 AArch64::LDNT1H_2Z);
5767 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5768 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5769 SelectContiguousMultiVectorLoad(Node, 2, 2,
5770 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5771 AArch64::LDNT1W_2Z_PSEUDO);
5772 else if (Subtarget->hasSVE2p1())
5773 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5774 AArch64::LDNT1W_2Z);
5778 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5779 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5780 SelectContiguousMultiVectorLoad(Node, 2, 3,
5781 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5782 AArch64::LDNT1D_2Z_PSEUDO);
5783 else if (Subtarget->hasSVE2p1())
5784 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5785 AArch64::LDNT1D_2Z);
5792 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5793 if (VT == MVT::nxv16i8) {
5794 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5795 SelectContiguousMultiVectorLoad(Node, 4, 0,
5796 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5797 AArch64::LDNT1B_4Z_PSEUDO);
5798 else if (Subtarget->hasSVE2p1())
5799 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5800 AArch64::LDNT1B_4Z);
5804 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5805 VT == MVT::nxv8bf16) {
5806 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5807 SelectContiguousMultiVectorLoad(Node, 4, 1,
5808 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5809 AArch64::LDNT1H_4Z_PSEUDO);
5810 else if (Subtarget->hasSVE2p1())
5811 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5812 AArch64::LDNT1H_4Z);
5816 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5817 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5818 SelectContiguousMultiVectorLoad(Node, 4, 2,
5819 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5820 AArch64::LDNT1W_4Z_PSEUDO);
5821 else if (Subtarget->hasSVE2p1())
5822 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5823 AArch64::LDNT1W_4Z);
5827 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5828 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5829 SelectContiguousMultiVectorLoad(Node, 4, 3,
5830 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5831 AArch64::LDNT1D_4Z_PSEUDO);
5832 else if (Subtarget->hasSVE2p1())
5833 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5834 AArch64::LDNT1D_4Z);
5841 case Intrinsic::aarch64_sve_ld3_sret: {
5842 if (VT == MVT::nxv16i8) {
5843 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5846 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5847 VT == MVT::nxv8bf16) {
5848 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5851 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5852 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5855 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5856 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5862 case Intrinsic::aarch64_sve_ld4_sret: {
5863 if (VT == MVT::nxv16i8) {
5864 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5867 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5868 VT == MVT::nxv8bf16) {
5869 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5872 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5873 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5876 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5877 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5883 case Intrinsic::aarch64_sme_read_hor_vg2: {
5884 if (VT == MVT::nxv16i8) {
5885 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5886 AArch64::MOVA_2ZMXI_H_B);
5888 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5889 VT == MVT::nxv8bf16) {
5890 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5891 AArch64::MOVA_2ZMXI_H_H);
5893 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5894 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5895 AArch64::MOVA_2ZMXI_H_S);
5897 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5898 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5899 AArch64::MOVA_2ZMXI_H_D);
5904 case Intrinsic::aarch64_sme_read_ver_vg2: {
5905 if (VT == MVT::nxv16i8) {
5906 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5907 AArch64::MOVA_2ZMXI_V_B);
5909 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5910 VT == MVT::nxv8bf16) {
5911 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5912 AArch64::MOVA_2ZMXI_V_H);
5914 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5915 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5916 AArch64::MOVA_2ZMXI_V_S);
5918 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5919 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5920 AArch64::MOVA_2ZMXI_V_D);
5925 case Intrinsic::aarch64_sme_read_hor_vg4: {
5926 if (VT == MVT::nxv16i8) {
5927 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5928 AArch64::MOVA_4ZMXI_H_B);
5930 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5931 VT == MVT::nxv8bf16) {
5932 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5933 AArch64::MOVA_4ZMXI_H_H);
5935 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5936 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5937 AArch64::MOVA_4ZMXI_H_S);
5939 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5940 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5941 AArch64::MOVA_4ZMXI_H_D);
5946 case Intrinsic::aarch64_sme_read_ver_vg4: {
5947 if (VT == MVT::nxv16i8) {
5948 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5949 AArch64::MOVA_4ZMXI_V_B);
5951 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5952 VT == MVT::nxv8bf16) {
5953 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5954 AArch64::MOVA_4ZMXI_V_H);
5956 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5957 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5958 AArch64::MOVA_4ZMXI_V_S);
5960 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5961 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5962 AArch64::MOVA_4ZMXI_V_D);
5967 case Intrinsic::aarch64_sme_read_vg1x2: {
5968 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5969 AArch64::MOVA_VG2_2ZMXI);
5972 case Intrinsic::aarch64_sme_read_vg1x4: {
5973 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5974 AArch64::MOVA_VG4_4ZMXI);
5977 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5978 if (VT == MVT::nxv16i8) {
5979 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5981 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5982 VT == MVT::nxv8bf16) {
5983 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5985 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5986 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5988 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5989 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5994 case Intrinsic::aarch64_sme_readz_vert_x2: {
5995 if (VT == MVT::nxv16i8) {
5996 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5998 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5999 VT == MVT::nxv8bf16) {
6000 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
6002 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6003 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
6005 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6006 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
6011 case Intrinsic::aarch64_sme_readz_horiz_x4: {
6012 if (VT == MVT::nxv16i8) {
6013 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
6015 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6016 VT == MVT::nxv8bf16) {
6017 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6019 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6020 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6022 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6023 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6028 case Intrinsic::aarch64_sme_readz_vert_x4: {
6029 if (VT == MVT::nxv16i8) {
6030 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6032 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6033 VT == MVT::nxv8bf16) {
6034 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6036 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6037 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6039 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6040 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6045 case Intrinsic::aarch64_sme_readz_x2: {
6046 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6050 case Intrinsic::aarch64_sme_readz_x4: {
6051 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6055 case Intrinsic::swift_async_context_addr: {
6058 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6060 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6061 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6062 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6064 ReplaceUses(
SDValue(Node, 0), Res);
6066 CurDAG->RemoveDeadNode(Node);
6068 auto &MF = CurDAG->getMachineFunction();
6069 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6070 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6073 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6075 Node->getValueType(0),
6076 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6077 AArch64::LUTI2_4ZTZI_S}))
6079 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6082 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6084 Node->getValueType(0),
6085 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6087 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6090 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6092 Node->getValueType(0),
6093 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6094 AArch64::LUTI2_2ZTZI_S}))
6096 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6099 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6101 Node->getValueType(0),
6102 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6103 AArch64::LUTI4_2ZTZI_S}))
6105 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6108 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6109 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6112 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6113 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6116 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6118 Node->getValueType(0),
6119 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6120 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6122 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6124 Node->getValueType(0),
6125 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6126 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6128 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6130 Node->getValueType(0),
6131 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6132 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6134 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6136 Node->getValueType(0),
6137 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6138 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6140 case Intrinsic::ptrauth_resign_load_relative:
6141 SelectPtrauthResign(Node);
6146 unsigned IntNo =
Node->getConstantOperandVal(0);
6150 case Intrinsic::aarch64_tagp:
6154 case Intrinsic::ptrauth_auth:
6155 SelectPtrauthAuth(Node);
6158 case Intrinsic::ptrauth_resign:
6159 SelectPtrauthResign(Node);
6162 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6163 SelectPtrauthResignWithPC(Node);
6166 case Intrinsic::aarch64_neon_tbl2:
6167 SelectTable(Node, 2,
6168 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6171 case Intrinsic::aarch64_neon_tbl3:
6172 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6173 : AArch64::TBLv16i8Three,
6176 case Intrinsic::aarch64_neon_tbl4:
6177 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6178 : AArch64::TBLv16i8Four,
6181 case Intrinsic::aarch64_neon_tbx2:
6182 SelectTable(Node, 2,
6183 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6186 case Intrinsic::aarch64_neon_tbx3:
6187 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6188 : AArch64::TBXv16i8Three,
6191 case Intrinsic::aarch64_neon_tbx4:
6192 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6193 : AArch64::TBXv16i8Four,
6196 case Intrinsic::aarch64_sve_srshl_single_x2:
6198 Node->getValueType(0),
6199 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6200 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6201 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6203 case Intrinsic::aarch64_sve_srshl_single_x4:
6205 Node->getValueType(0),
6206 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6207 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6208 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6210 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6211 SelectMultiVectorLuti6LaneX4(Node, 2);
6213 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6214 SelectMultiVectorLuti6LaneX4(Node, 3);
6216 case Intrinsic::aarch64_sve_urshl_single_x2:
6218 Node->getValueType(0),
6219 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6220 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6221 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6223 case Intrinsic::aarch64_sve_urshl_single_x4:
6225 Node->getValueType(0),
6226 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6227 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6228 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6230 case Intrinsic::aarch64_sve_srshl_x2:
6232 Node->getValueType(0),
6233 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6234 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6235 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6237 case Intrinsic::aarch64_sve_srshl_x4:
6239 Node->getValueType(0),
6240 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6241 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6244 case Intrinsic::aarch64_sve_urshl_x2:
6246 Node->getValueType(0),
6247 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6248 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6251 case Intrinsic::aarch64_sve_urshl_x4:
6253 Node->getValueType(0),
6254 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6255 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6256 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6258 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6260 Node->getValueType(0),
6261 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6262 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6263 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6265 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6267 Node->getValueType(0),
6268 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6269 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6270 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6272 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6274 Node->getValueType(0),
6275 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6276 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6277 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6279 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6281 Node->getValueType(0),
6282 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6283 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6284 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6286 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6288 Node->getValueType(0),
6289 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6290 AArch64::FSCALE_2ZZ_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6293 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6295 Node->getValueType(0),
6296 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6297 AArch64::FSCALE_4ZZ_D}))
6298 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6300 case Intrinsic::aarch64_sme_fp8_scale_x2:
6302 Node->getValueType(0),
6303 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6304 AArch64::FSCALE_2Z2Z_D}))
6305 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6307 case Intrinsic::aarch64_sme_fp8_scale_x4:
6309 Node->getValueType(0),
6310 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6311 AArch64::FSCALE_4Z4Z_D}))
6312 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6314 case Intrinsic::aarch64_sve_whilege_x2:
6316 Node->getValueType(0),
6317 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6318 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6319 SelectWhilePair(Node,
Op);
6321 case Intrinsic::aarch64_sve_whilegt_x2:
6323 Node->getValueType(0),
6324 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6325 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6326 SelectWhilePair(Node,
Op);
6328 case Intrinsic::aarch64_sve_whilehi_x2:
6330 Node->getValueType(0),
6331 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6332 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6333 SelectWhilePair(Node,
Op);
6335 case Intrinsic::aarch64_sve_whilehs_x2:
6337 Node->getValueType(0),
6338 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6339 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6340 SelectWhilePair(Node,
Op);
6342 case Intrinsic::aarch64_sve_whilele_x2:
6344 Node->getValueType(0),
6345 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6346 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6347 SelectWhilePair(Node,
Op);
6349 case Intrinsic::aarch64_sve_whilelo_x2:
6351 Node->getValueType(0),
6352 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6353 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6354 SelectWhilePair(Node,
Op);
6356 case Intrinsic::aarch64_sve_whilels_x2:
6358 Node->getValueType(0),
6359 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6360 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6361 SelectWhilePair(Node,
Op);
6363 case Intrinsic::aarch64_sve_whilelt_x2:
6365 Node->getValueType(0),
6366 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6367 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6368 SelectWhilePair(Node,
Op);
6370 case Intrinsic::aarch64_sve_smax_single_x2:
6372 Node->getValueType(0),
6373 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6374 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6375 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6377 case Intrinsic::aarch64_sve_umax_single_x2:
6379 Node->getValueType(0),
6380 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6381 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6382 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6384 case Intrinsic::aarch64_sve_fmax_single_x2:
6386 Node->getValueType(0),
6387 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6388 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6389 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6391 case Intrinsic::aarch64_sve_smax_single_x4:
6393 Node->getValueType(0),
6394 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6395 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6396 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6398 case Intrinsic::aarch64_sve_umax_single_x4:
6400 Node->getValueType(0),
6401 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6402 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6403 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6405 case Intrinsic::aarch64_sve_fmax_single_x4:
6407 Node->getValueType(0),
6408 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6409 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6410 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6412 case Intrinsic::aarch64_sve_smin_single_x2:
6414 Node->getValueType(0),
6415 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6416 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6417 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6419 case Intrinsic::aarch64_sve_umin_single_x2:
6421 Node->getValueType(0),
6422 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6423 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6424 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6426 case Intrinsic::aarch64_sve_fmin_single_x2:
6428 Node->getValueType(0),
6429 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6430 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6431 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6433 case Intrinsic::aarch64_sve_smin_single_x4:
6435 Node->getValueType(0),
6436 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6437 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6438 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6440 case Intrinsic::aarch64_sve_umin_single_x4:
6442 Node->getValueType(0),
6443 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6444 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6445 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6447 case Intrinsic::aarch64_sve_fmin_single_x4:
6449 Node->getValueType(0),
6450 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6451 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6452 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6454 case Intrinsic::aarch64_sve_smax_x2:
6456 Node->getValueType(0),
6457 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6458 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6459 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6461 case Intrinsic::aarch64_sve_umax_x2:
6463 Node->getValueType(0),
6464 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6465 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6466 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6468 case Intrinsic::aarch64_sve_fmax_x2:
6470 Node->getValueType(0),
6471 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6472 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6473 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6475 case Intrinsic::aarch64_sve_smax_x4:
6477 Node->getValueType(0),
6478 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6479 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6480 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6482 case Intrinsic::aarch64_sve_umax_x4:
6484 Node->getValueType(0),
6485 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6486 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6487 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6489 case Intrinsic::aarch64_sve_fmax_x4:
6491 Node->getValueType(0),
6492 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6493 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6494 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6496 case Intrinsic::aarch64_sme_famax_x2:
6498 Node->getValueType(0),
6499 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6500 AArch64::FAMAX_2Z2Z_D}))
6501 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6503 case Intrinsic::aarch64_sme_famax_x4:
6505 Node->getValueType(0),
6506 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6507 AArch64::FAMAX_4Z4Z_D}))
6508 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6510 case Intrinsic::aarch64_sme_famin_x2:
6512 Node->getValueType(0),
6513 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6514 AArch64::FAMIN_2Z2Z_D}))
6515 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6517 case Intrinsic::aarch64_sme_famin_x4:
6519 Node->getValueType(0),
6520 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6521 AArch64::FAMIN_4Z4Z_D}))
6522 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6524 case Intrinsic::aarch64_sve_smin_x2:
6526 Node->getValueType(0),
6527 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6528 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6529 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6531 case Intrinsic::aarch64_sve_umin_x2:
6533 Node->getValueType(0),
6534 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6535 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6536 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6538 case Intrinsic::aarch64_sve_fmin_x2:
6540 Node->getValueType(0),
6541 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6542 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6543 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6545 case Intrinsic::aarch64_sve_smin_x4:
6547 Node->getValueType(0),
6548 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6549 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6550 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6552 case Intrinsic::aarch64_sve_umin_x4:
6554 Node->getValueType(0),
6555 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6556 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6557 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6559 case Intrinsic::aarch64_sve_fmin_x4:
6561 Node->getValueType(0),
6562 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6563 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6564 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6566 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6568 Node->getValueType(0),
6569 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6570 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6571 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6573 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6575 Node->getValueType(0),
6576 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6577 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6578 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6580 case Intrinsic::aarch64_sve_fminnm_single_x2:
6582 Node->getValueType(0),
6583 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6584 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6585 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6587 case Intrinsic::aarch64_sve_fminnm_single_x4:
6589 Node->getValueType(0),
6590 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6591 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6592 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6594 case Intrinsic::aarch64_sve_fscale_single_x4:
6595 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6597 case Intrinsic::aarch64_sve_fscale_single_x2:
6598 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6600 case Intrinsic::aarch64_sve_fmul_single_x4:
6602 Node->getValueType(0),
6603 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6604 AArch64::FMUL_4ZZ_D}))
6605 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6607 case Intrinsic::aarch64_sve_fmul_single_x2:
6609 Node->getValueType(0),
6610 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6611 AArch64::FMUL_2ZZ_D}))
6612 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6614 case Intrinsic::aarch64_sve_fmaxnm_x2:
6616 Node->getValueType(0),
6617 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6618 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6619 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6621 case Intrinsic::aarch64_sve_fmaxnm_x4:
6623 Node->getValueType(0),
6624 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6625 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6626 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6628 case Intrinsic::aarch64_sve_fminnm_x2:
6630 Node->getValueType(0),
6631 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6632 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6633 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6635 case Intrinsic::aarch64_sve_fminnm_x4:
6637 Node->getValueType(0),
6638 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6639 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6640 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6642 case Intrinsic::aarch64_sve_aese_lane_x2:
6643 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6645 case Intrinsic::aarch64_sve_aesd_lane_x2:
6646 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6648 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6649 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6651 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6652 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6654 case Intrinsic::aarch64_sve_aese_lane_x4:
6655 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6657 case Intrinsic::aarch64_sve_aesd_lane_x4:
6658 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6660 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6661 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6663 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6664 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6666 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6667 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6669 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6673 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6675 for (
unsigned I = 0;
I < 2;
I++)
6677 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6679 CurDAG->RemoveDeadNode(Node);
6682 case Intrinsic::aarch64_sve_fscale_x4:
6683 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6685 case Intrinsic::aarch64_sve_fscale_x2:
6686 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6688 case Intrinsic::aarch64_sve_fmul_x4:
6690 Node->getValueType(0),
6691 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6692 AArch64::FMUL_4Z4Z_D}))
6693 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6695 case Intrinsic::aarch64_sve_fmul_x2:
6697 Node->getValueType(0),
6698 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6699 AArch64::FMUL_2Z2Z_D}))
6700 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6702 case Intrinsic::aarch64_sve_fcvtzs_x2:
6703 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6705 case Intrinsic::aarch64_sve_scvtf_x2:
6706 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6708 case Intrinsic::aarch64_sve_fcvtzu_x2:
6709 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6711 case Intrinsic::aarch64_sve_ucvtf_x2:
6712 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6714 case Intrinsic::aarch64_sve_fcvtzs_x4:
6715 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6717 case Intrinsic::aarch64_sve_scvtf_x4:
6718 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6720 case Intrinsic::aarch64_sve_fcvtzu_x4:
6721 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6723 case Intrinsic::aarch64_sve_ucvtf_x4:
6724 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6726 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6727 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6729 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6730 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6732 case Intrinsic::aarch64_sve_sclamp_single_x2:
6734 Node->getValueType(0),
6735 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6736 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6737 SelectClamp(Node, 2,
Op);
6739 case Intrinsic::aarch64_sve_uclamp_single_x2:
6741 Node->getValueType(0),
6742 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6743 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6744 SelectClamp(Node, 2,
Op);
6746 case Intrinsic::aarch64_sve_fclamp_single_x2:
6748 Node->getValueType(0),
6749 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6750 AArch64::FCLAMP_VG2_2Z2Z_D}))
6751 SelectClamp(Node, 2,
Op);
6753 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6754 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6756 case Intrinsic::aarch64_sve_sclamp_single_x4:
6758 Node->getValueType(0),
6759 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6760 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6761 SelectClamp(Node, 4,
Op);
6763 case Intrinsic::aarch64_sve_uclamp_single_x4:
6765 Node->getValueType(0),
6766 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6767 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6768 SelectClamp(Node, 4,
Op);
6770 case Intrinsic::aarch64_sve_fclamp_single_x4:
6772 Node->getValueType(0),
6773 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6774 AArch64::FCLAMP_VG4_4Z4Z_D}))
6775 SelectClamp(Node, 4,
Op);
6777 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6778 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6780 case Intrinsic::aarch64_sve_add_single_x2:
6782 Node->getValueType(0),
6783 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6784 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6785 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6787 case Intrinsic::aarch64_sve_add_single_x4:
6789 Node->getValueType(0),
6790 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6791 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6792 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6794 case Intrinsic::aarch64_sve_zip_x2:
6796 Node->getValueType(0),
6797 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6798 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6799 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6801 case Intrinsic::aarch64_sve_zipq_x2:
6802 SelectUnaryMultiIntrinsic(Node, 2,
false,
6803 AArch64::ZIP_VG2_2ZZZ_Q);
6805 case Intrinsic::aarch64_sve_zip_x4:
6807 Node->getValueType(0),
6808 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6809 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6810 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6812 case Intrinsic::aarch64_sve_zipq_x4:
6813 SelectUnaryMultiIntrinsic(Node, 4,
true,
6814 AArch64::ZIP_VG4_4Z4Z_Q);
6816 case Intrinsic::aarch64_sve_uzp_x2:
6818 Node->getValueType(0),
6819 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6820 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6821 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6823 case Intrinsic::aarch64_sve_uzpq_x2:
6824 SelectUnaryMultiIntrinsic(Node, 2,
false,
6825 AArch64::UZP_VG2_2ZZZ_Q);
6827 case Intrinsic::aarch64_sve_uzp_x4:
6829 Node->getValueType(0),
6830 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6831 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6832 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6834 case Intrinsic::aarch64_sve_uzpq_x4:
6835 SelectUnaryMultiIntrinsic(Node, 4,
true,
6836 AArch64::UZP_VG4_4Z4Z_Q);
6838 case Intrinsic::aarch64_sve_sel_x2:
6840 Node->getValueType(0),
6841 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6842 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6843 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6845 case Intrinsic::aarch64_sve_sel_x4:
6847 Node->getValueType(0),
6848 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6849 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6850 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6852 case Intrinsic::aarch64_sve_frinta_x2:
6853 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6855 case Intrinsic::aarch64_sve_frinta_x4:
6856 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6858 case Intrinsic::aarch64_sve_frintm_x2:
6859 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6861 case Intrinsic::aarch64_sve_frintm_x4:
6862 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6864 case Intrinsic::aarch64_sve_frintn_x2:
6865 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6867 case Intrinsic::aarch64_sve_frintn_x4:
6868 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6870 case Intrinsic::aarch64_sve_frintp_x2:
6871 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6873 case Intrinsic::aarch64_sve_frintp_x4:
6874 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6876 case Intrinsic::aarch64_sve_sunpk_x2:
6878 Node->getValueType(0),
6879 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6880 AArch64::SUNPK_VG2_2ZZ_D}))
6881 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6883 case Intrinsic::aarch64_sve_uunpk_x2:
6885 Node->getValueType(0),
6886 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6887 AArch64::UUNPK_VG2_2ZZ_D}))
6888 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6890 case Intrinsic::aarch64_sve_sunpk_x4:
6892 Node->getValueType(0),
6893 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6894 AArch64::SUNPK_VG4_4Z2Z_D}))
6895 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6897 case Intrinsic::aarch64_sve_uunpk_x4:
6899 Node->getValueType(0),
6900 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6901 AArch64::UUNPK_VG4_4Z2Z_D}))
6902 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6904 case Intrinsic::aarch64_sve_pext_x2: {
6906 Node->getValueType(0),
6907 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6908 AArch64::PEXT_2PCI_D}))
6909 SelectPExtPair(Node,
Op);
6916 unsigned IntNo =
Node->getConstantOperandVal(1);
6917 if (
Node->getNumOperands() >= 3)
6918 VT =
Node->getOperand(2)->getValueType(0);
6922 case Intrinsic::aarch64_neon_st1x2: {
6923 if (VT == MVT::v8i8) {
6924 SelectStore(Node, 2, AArch64::ST1Twov8b);
6926 }
else if (VT == MVT::v16i8) {
6927 SelectStore(Node, 2, AArch64::ST1Twov16b);
6929 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6930 VT == MVT::v4bf16) {
6931 SelectStore(Node, 2, AArch64::ST1Twov4h);
6933 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6934 VT == MVT::v8bf16) {
6935 SelectStore(Node, 2, AArch64::ST1Twov8h);
6937 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6938 SelectStore(Node, 2, AArch64::ST1Twov2s);
6940 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6941 SelectStore(Node, 2, AArch64::ST1Twov4s);
6943 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6944 SelectStore(Node, 2, AArch64::ST1Twov2d);
6946 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6947 SelectStore(Node, 2, AArch64::ST1Twov1d);
6952 case Intrinsic::aarch64_neon_st1x3: {
6953 if (VT == MVT::v8i8) {
6954 SelectStore(Node, 3, AArch64::ST1Threev8b);
6956 }
else if (VT == MVT::v16i8) {
6957 SelectStore(Node, 3, AArch64::ST1Threev16b);
6959 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6960 VT == MVT::v4bf16) {
6961 SelectStore(Node, 3, AArch64::ST1Threev4h);
6963 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6964 VT == MVT::v8bf16) {
6965 SelectStore(Node, 3, AArch64::ST1Threev8h);
6967 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6968 SelectStore(Node, 3, AArch64::ST1Threev2s);
6970 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6971 SelectStore(Node, 3, AArch64::ST1Threev4s);
6973 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6974 SelectStore(Node, 3, AArch64::ST1Threev2d);
6976 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6977 SelectStore(Node, 3, AArch64::ST1Threev1d);
6982 case Intrinsic::aarch64_neon_st1x4: {
6983 if (VT == MVT::v8i8) {
6984 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6986 }
else if (VT == MVT::v16i8) {
6987 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6989 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6990 VT == MVT::v4bf16) {
6991 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6993 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6994 VT == MVT::v8bf16) {
6995 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6997 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6998 SelectStore(Node, 4, AArch64::ST1Fourv2s);
7000 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7001 SelectStore(Node, 4, AArch64::ST1Fourv4s);
7003 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7004 SelectStore(Node, 4, AArch64::ST1Fourv2d);
7006 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7007 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7012 case Intrinsic::aarch64_neon_st2: {
7013 if (VT == MVT::v8i8) {
7014 SelectStore(Node, 2, AArch64::ST2Twov8b);
7016 }
else if (VT == MVT::v16i8) {
7017 SelectStore(Node, 2, AArch64::ST2Twov16b);
7019 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7020 VT == MVT::v4bf16) {
7021 SelectStore(Node, 2, AArch64::ST2Twov4h);
7023 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7024 VT == MVT::v8bf16) {
7025 SelectStore(Node, 2, AArch64::ST2Twov8h);
7027 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7028 SelectStore(Node, 2, AArch64::ST2Twov2s);
7030 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7031 SelectStore(Node, 2, AArch64::ST2Twov4s);
7033 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7034 SelectStore(Node, 2, AArch64::ST2Twov2d);
7036 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7037 SelectStore(Node, 2, AArch64::ST1Twov1d);
7042 case Intrinsic::aarch64_neon_st3: {
7043 if (VT == MVT::v8i8) {
7044 SelectStore(Node, 3, AArch64::ST3Threev8b);
7046 }
else if (VT == MVT::v16i8) {
7047 SelectStore(Node, 3, AArch64::ST3Threev16b);
7049 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7050 VT == MVT::v4bf16) {
7051 SelectStore(Node, 3, AArch64::ST3Threev4h);
7053 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7054 VT == MVT::v8bf16) {
7055 SelectStore(Node, 3, AArch64::ST3Threev8h);
7057 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7058 SelectStore(Node, 3, AArch64::ST3Threev2s);
7060 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7061 SelectStore(Node, 3, AArch64::ST3Threev4s);
7063 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7064 SelectStore(Node, 3, AArch64::ST3Threev2d);
7066 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7067 SelectStore(Node, 3, AArch64::ST1Threev1d);
7072 case Intrinsic::aarch64_neon_st4: {
7073 if (VT == MVT::v8i8) {
7074 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7076 }
else if (VT == MVT::v16i8) {
7077 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7079 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7080 VT == MVT::v4bf16) {
7081 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7083 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7084 VT == MVT::v8bf16) {
7085 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7087 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7088 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7090 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7091 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7093 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7094 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7096 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7097 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7102 case Intrinsic::aarch64_neon_st2lane: {
7103 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7104 SelectStoreLane(Node, 2, AArch64::ST2i8);
7106 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7107 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7108 SelectStoreLane(Node, 2, AArch64::ST2i16);
7110 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7112 SelectStoreLane(Node, 2, AArch64::ST2i32);
7114 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7116 SelectStoreLane(Node, 2, AArch64::ST2i64);
7121 case Intrinsic::aarch64_neon_st3lane: {
7122 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7123 SelectStoreLane(Node, 3, AArch64::ST3i8);
7125 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7126 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7127 SelectStoreLane(Node, 3, AArch64::ST3i16);
7129 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7131 SelectStoreLane(Node, 3, AArch64::ST3i32);
7133 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7135 SelectStoreLane(Node, 3, AArch64::ST3i64);
7140 case Intrinsic::aarch64_neon_st4lane: {
7141 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7142 SelectStoreLane(Node, 4, AArch64::ST4i8);
7144 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7145 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7146 SelectStoreLane(Node, 4, AArch64::ST4i16);
7148 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7150 SelectStoreLane(Node, 4, AArch64::ST4i32);
7152 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7154 SelectStoreLane(Node, 4, AArch64::ST4i64);
7159 case Intrinsic::aarch64_sve_st2q: {
7160 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7163 case Intrinsic::aarch64_sve_st3q: {
7164 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7167 case Intrinsic::aarch64_sve_st4q: {
7168 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7171 case Intrinsic::aarch64_sve_st2: {
7172 if (VT == MVT::nxv16i8) {
7173 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7175 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7176 VT == MVT::nxv8bf16) {
7177 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7179 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7180 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7182 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7183 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7188 case Intrinsic::aarch64_sve_st3: {
7189 if (VT == MVT::nxv16i8) {
7190 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7192 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7193 VT == MVT::nxv8bf16) {
7194 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7196 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7197 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7199 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7200 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7205 case Intrinsic::aarch64_sve_st4: {
7206 if (VT == MVT::nxv16i8) {
7207 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7209 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7210 VT == MVT::nxv8bf16) {
7211 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7213 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7214 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7216 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7217 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7225 case AArch64ISD::LD2post: {
7226 if (VT == MVT::v8i8) {
7227 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7229 }
else if (VT == MVT::v16i8) {
7230 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7232 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7233 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7235 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7236 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7238 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7239 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7241 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7242 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7244 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7245 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7247 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7248 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7253 case AArch64ISD::LD3post: {
7254 if (VT == MVT::v8i8) {
7255 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7257 }
else if (VT == MVT::v16i8) {
7258 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7260 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7261 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7263 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7264 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7266 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7267 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7269 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7270 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7272 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7273 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7275 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7276 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7281 case AArch64ISD::LD4post: {
7282 if (VT == MVT::v8i8) {
7283 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7285 }
else if (VT == MVT::v16i8) {
7286 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7288 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7289 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7291 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7292 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7294 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7295 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7297 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7298 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7300 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7301 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7303 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7304 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7309 case AArch64ISD::LD1x2post: {
7310 if (VT == MVT::v8i8) {
7311 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7313 }
else if (VT == MVT::v16i8) {
7314 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7316 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7317 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7319 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7320 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7322 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7323 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7325 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7326 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7328 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7329 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7331 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7332 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7337 case AArch64ISD::LD1x3post: {
7338 if (VT == MVT::v8i8) {
7339 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7341 }
else if (VT == MVT::v16i8) {
7342 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7344 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7345 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7347 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7348 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7350 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7351 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7353 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7354 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7356 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7357 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7359 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7360 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7365 case AArch64ISD::LD1x4post: {
7366 if (VT == MVT::v8i8) {
7367 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7369 }
else if (VT == MVT::v16i8) {
7370 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7372 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7373 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7375 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7376 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7378 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7379 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7381 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7382 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7384 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7385 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7387 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7388 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7393 case AArch64ISD::LD1DUPpost: {
7394 if (VT == MVT::v8i8) {
7395 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7397 }
else if (VT == MVT::v16i8) {
7398 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7400 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7401 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7403 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7404 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7406 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7407 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7409 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7410 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7412 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7413 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7415 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7416 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7421 case AArch64ISD::LD2DUPpost: {
7422 if (VT == MVT::v8i8) {
7423 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7425 }
else if (VT == MVT::v16i8) {
7426 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7428 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7429 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7431 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7432 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7434 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7435 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7437 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7438 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7440 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7441 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7443 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7444 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7449 case AArch64ISD::LD3DUPpost: {
7450 if (VT == MVT::v8i8) {
7451 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7453 }
else if (VT == MVT::v16i8) {
7454 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7456 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7457 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7459 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7460 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7462 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7463 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7465 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7466 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7468 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7469 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7471 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7472 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7477 case AArch64ISD::LD4DUPpost: {
7478 if (VT == MVT::v8i8) {
7479 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7481 }
else if (VT == MVT::v16i8) {
7482 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7484 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7485 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7487 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7488 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7490 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7491 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7493 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7494 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7496 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7497 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7499 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7500 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7505 case AArch64ISD::LD1LANEpost: {
7506 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7507 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7509 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7510 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7511 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7513 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7515 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7517 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7519 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7524 case AArch64ISD::LD2LANEpost: {
7525 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7526 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7528 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7529 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7530 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7532 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7534 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7536 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7538 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7543 case AArch64ISD::LD3LANEpost: {
7544 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7545 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7547 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7548 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7549 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7551 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7553 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7555 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7557 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7562 case AArch64ISD::LD4LANEpost: {
7563 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7564 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7566 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7567 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7568 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7570 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7572 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7574 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7576 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7581 case AArch64ISD::ST2post: {
7582 VT =
Node->getOperand(1).getValueType();
7583 if (VT == MVT::v8i8) {
7584 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7586 }
else if (VT == MVT::v16i8) {
7587 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7589 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7590 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7592 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7593 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7595 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7596 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7598 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7599 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7601 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7602 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7604 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7605 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7610 case AArch64ISD::ST3post: {
7611 VT =
Node->getOperand(1).getValueType();
7612 if (VT == MVT::v8i8) {
7613 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7615 }
else if (VT == MVT::v16i8) {
7616 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7618 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7619 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7621 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7622 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7624 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7625 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7627 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7628 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7630 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7631 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7633 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7634 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7639 case AArch64ISD::ST4post: {
7640 VT =
Node->getOperand(1).getValueType();
7641 if (VT == MVT::v8i8) {
7642 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7644 }
else if (VT == MVT::v16i8) {
7645 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7647 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7648 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7650 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7651 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7653 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7654 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7656 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7657 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7659 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7660 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7662 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7663 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7668 case AArch64ISD::ST1x2post: {
7669 VT =
Node->getOperand(1).getValueType();
7670 if (VT == MVT::v8i8) {
7671 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7673 }
else if (VT == MVT::v16i8) {
7674 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7676 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7677 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7679 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7680 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7682 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7683 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7685 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7686 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7688 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7689 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7691 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7692 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7697 case AArch64ISD::ST1x3post: {
7698 VT =
Node->getOperand(1).getValueType();
7699 if (VT == MVT::v8i8) {
7700 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7702 }
else if (VT == MVT::v16i8) {
7703 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7705 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7706 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7708 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7709 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7711 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7712 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7714 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7715 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7717 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7718 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7720 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7721 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7726 case AArch64ISD::ST1x4post: {
7727 VT =
Node->getOperand(1).getValueType();
7728 if (VT == MVT::v8i8) {
7729 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7731 }
else if (VT == MVT::v16i8) {
7732 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7734 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7735 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7737 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7738 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7740 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7741 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7743 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7744 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7746 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7747 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7749 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7750 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7755 case AArch64ISD::ST2LANEpost: {
7756 VT =
Node->getOperand(1).getValueType();
7757 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7758 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7760 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7761 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7762 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7764 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7766 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7768 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7770 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7775 case AArch64ISD::ST3LANEpost: {
7776 VT =
Node->getOperand(1).getValueType();
7777 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7778 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7780 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7781 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7782 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7784 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7786 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7788 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7790 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7795 case AArch64ISD::ST4LANEpost: {
7796 VT =
Node->getOperand(1).getValueType();
7797 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7798 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7800 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7801 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7802 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7804 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7806 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7808 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7810 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7825 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7837 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7841 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7842 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7864 return MemIntr->getMemoryVT();
7871 DataVT =
Load->getValueType(0);
7873 DataVT =
Load->getValueType(0);
7875 DataVT =
Store->getValue().getValueType();
7877 DataVT =
Store->getValue().getValueType();
7884 const unsigned Opcode = Root->
getOpcode();
7888 case AArch64ISD::LD1_MERGE_ZERO:
7889 case AArch64ISD::LD1S_MERGE_ZERO:
7890 case AArch64ISD::LDNF1_MERGE_ZERO:
7891 case AArch64ISD::LDNF1S_MERGE_ZERO:
7893 case AArch64ISD::ST1_PRED:
7905 case Intrinsic::aarch64_sme_ldr:
7906 case Intrinsic::aarch64_sme_str:
7907 return MVT::nxv16i8;
7908 case Intrinsic::aarch64_sve_prf:
7913 case Intrinsic::aarch64_sve_ld2_sret:
7914 case Intrinsic::aarch64_sve_ld2q_sret:
7917 case Intrinsic::aarch64_sve_st2q:
7920 case Intrinsic::aarch64_sve_ld3_sret:
7921 case Intrinsic::aarch64_sve_ld3q_sret:
7924 case Intrinsic::aarch64_sve_st3q:
7927 case Intrinsic::aarch64_sve_ld4_sret:
7928 case Intrinsic::aarch64_sve_ld4q_sret:
7931 case Intrinsic::aarch64_sve_st4q:
7934 case Intrinsic::aarch64_sve_ld1_pn_x2:
7935 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7938 case Intrinsic::aarch64_sve_ld1_pn_x4:
7939 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7942 case Intrinsic::aarch64_sve_st1_pn_x2:
7943 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7946 case Intrinsic::aarch64_sve_st1_pn_x4:
7947 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7950 case Intrinsic::aarch64_sve_ld1udq:
7951 case Intrinsic::aarch64_sve_st1dq:
7952 return EVT(MVT::nxv1i64);
7953 case Intrinsic::aarch64_sve_ld1uwq:
7954 case Intrinsic::aarch64_sve_st1wq:
7955 return EVT(MVT::nxv1i32);
7962template <
int64_t Min,
int64_t Max>
7963bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7967 const DataLayout &
DL = CurDAG->getDataLayout();
7968 const MachineFrameInfo &MFI = MF->getFrameInfo();
7976 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7990 int64_t MulImm = std::numeric_limits<int64_t>::max();
7994 int64_t ByteOffset =
C->getSExtValue();
7995 const auto KnownVScale =
7998 if (!KnownVScale || ByteOffset % KnownVScale != 0)
8001 MulImm = ByteOffset / KnownVScale;
8008 if ((MulImm % MemWidthBytes) != 0)
8011 int64_t
Offset = MulImm / MemWidthBytes;
8015 Base =
N.getOperand(0);
8024 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8030bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
8049 int64_t ImmOff =
C->getSExtValue();
8050 unsigned Size = 1 << Scale;
8059 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8061 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8072 if (
C->getZExtValue() == Scale) {
8081bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
8082 const AArch64TargetLowering *TLI =
8083 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8088bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
8089 return N.getValueType().isScalableVectorOf(MVT::i1);
8092bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
8097 int64_t ImmOff =
C->getSExtValue();
8098 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8099 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8104 if (
SDValue C = MatchConstantOffset(
N)) {
8111 if (CurDAG->isBaseWithConstantOffset(
N)) {
8112 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
8113 Base =
N.getOperand(0);
8121 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8125bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
8145 uint64_t LowerBound = 0, UpperBound = 64;
8163 if (CN->getAPIntValue().uge(LowerBound) &&
8164 CN->getAPIntValue().ult(UpperBound)) {
8166 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8174template <
bool MatchCBB>
8181 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8183 Reg =
N.getOperand(0);
8185 SDLoc(
N), MVT::i32);
8193 Reg =
N.getOperand(0);
8213bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *
N) {
8214 EVT VT =
N->getValueType(0);
8225 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8234 unsigned CondCode = CC->getZExtValue();
8237 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8239 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8240 else if (VT == MVT::f32)
8241 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8242 else if (VT == MVT::f64)
8243 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8251 if (TVal == CmpLHS && FVal == CmpRHS)
8256 if (TVal == CmpLHS && FVal == CmpRHS)
8265 unsigned Opc = getOpc(VT, isMax);
8271 if (!CFP || CFP->getValueAPF().isNaN())
8276 if (CFP->isZero() && !
N->getFlags().hasNoSignedZeros())
8282 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8285 CurDAG->SelectNodeTo(
N,
Opc, VT, CmpLHS, CmpRHS);
8289void AArch64DAGToDAGISel::PreprocessISelDAG() {
8290 bool MadeChange =
false;
8296 switch (
N.getOpcode()) {
8298 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8299 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8300 ScalarTy ==
N.getOperand(0).getValueType())
8305 case AArch64ISD::VSHL: {
8308 EVT VT =
N.getValueType(0);
8315 if (
B.getOpcode() ==
A.getOpcode())
8328 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8334 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(&
N, 0), Result);
8340 CurDAG->RemoveDeadNodes();
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static std::optional< APInt > GetNEONSplatValue(SDValue N)
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static SDValue addBitcastHints(SelectionDAG &DAG, SDNode &N)
addBitcastHints - This method adds bitcast hints to the operands of a node to help instruction select...
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static std::optional< APInt > DecodeNEONSplat(SDValue N)
static bool checkCVTFixedPointOperandWithFBitsForVectors(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static SDValue getZeroRegister(SelectionDAG &DAG, SDLoc DL, EVT VT)
Returns a copy from WZR or XZR.
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static APInt DecodeFMOVImm(uint64_t Imm, unsigned RegWidth)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec)
Builds an integer vector type large enough to hold NumVec instances of VecVT.
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-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)
Contains matchers for matching SelectionDAG nodes and values.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64RegisterInfo * getRegisterInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N) const
Register matchRegisterName(StringRef RegName) const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static const fltSemantics & IEEEhalf()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
unsigned getID() const
getID() - Return the register class ID number.
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, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
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.
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static constexpr unsigned SVEBitsPerBlock
@ POISON
POISON - A poison node.
@ 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).
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
auto m_SExt(const Opnd &Op)
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
NUses_match< 1, Value_match > m_OneUse()
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)
@ Known
Known to have no common set bits.
@ 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.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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.
MCRegisterClass TargetRegisterClass
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.