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);
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);
700 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
701 N.getValueType().getScalarType().getSimpleVT(),
707bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(
SDValue N,
710 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal,
Imm);
719 int64_t ImmVal = ImmAPIntVal->getSExtValue();
720 if (ImmVal < -128 || ImmVal > 127)
723 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
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>
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);
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;
1876 (!Subtarget->
isLittleEndian() || (Subtarget->requiresStrictAlign() &&
1879 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1880 else if (VT == MVT::i32) {
1882 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1884 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1886 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1892 }
else if (VT == MVT::i16) {
1894 if (DstVT == MVT::i64)
1895 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1897 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1899 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1900 InsertTo64 = DstVT == MVT::i64;
1905 }
else if (VT == MVT::i8) {
1907 if (DstVT == MVT::i64)
1908 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1910 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1912 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1913 InsertTo64 = DstVT == MVT::i64;
1918 }
else if (VT == MVT::f16) {
1919 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1920 }
else if (VT == MVT::bf16) {
1921 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1922 }
else if (VT == MVT::f32) {
1923 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1924 }
else if (VT == MVT::f64 || (VT.
is64BitVector() && !UseLd1)) {
1925 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1927 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1929 if (IsPre || OffsetVal != 8)
1933 Opcode = AArch64::LD1Onev8b_POST;
1936 Opcode = AArch64::LD1Onev4h_POST;
1939 Opcode = AArch64::LD1Onev2s_POST;
1942 Opcode = AArch64::LD1Onev1d_POST;
1948 if (IsPre || OffsetVal != 16)
1952 Opcode = AArch64::LD1Onev16b_POST;
1955 Opcode = AArch64::LD1Onev8h_POST;
1958 Opcode = AArch64::LD1Onev4s_POST;
1961 Opcode = AArch64::LD1Onev2d_POST;
1972 SDValue Offset = UseLd1 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1973 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1975 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1985 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1986 LoadedVal =
SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
1987 MVT::i64, LoadedVal, SubReg),
1991 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1994 CurDAG->RemoveDeadNode(
N);
1998void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1999 unsigned SubRegIdx) {
2001 EVT VT =
N->getValueType(0);
2007 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2009 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2011 for (
unsigned i = 0; i < NumVecs; ++i)
2013 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2020 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2024 CurDAG->RemoveDeadNode(
N);
2027void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2028 unsigned Opc,
unsigned SubRegIdx) {
2030 EVT VT =
N->getValueType(0);
2037 const EVT ResTys[] = {MVT::i64,
2038 MVT::Untyped, MVT::Other};
2040 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2048 ReplaceUses(
SDValue(
N, 0), SuperReg);
2050 for (
unsigned i = 0; i < NumVecs; ++i)
2052 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2060 CurDAG->RemoveDeadNode(
N);
2066std::tuple<unsigned, SDValue, SDValue>
2067AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2073 SDValue NewOffset = OldOffset;
2075 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2076 N, OldBase, NewBase, NewOffset);
2080 const bool IsRegReg =
2081 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2084 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2097template <SelectTypeKind Kind>
2109 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2114 if (EltVT != MVT::i1)
2118 if (EltVT == MVT::bf16)
2120 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2150void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2153 if (
Imm->getZExtValue() > 1)
2157 EVT VT =
N->getValueType(0);
2159 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2162 for (
unsigned I = 0;
I < 2; ++
I)
2163 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2164 AArch64::psub0 +
I,
DL, VT, SuperReg));
2166 CurDAG->RemoveDeadNode(
N);
2169void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2171 EVT VT =
N->getValueType(0);
2175 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2178 for (
unsigned I = 0;
I < 2; ++
I)
2179 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2180 AArch64::psub0 +
I,
DL, VT, SuperReg));
2182 CurDAG->RemoveDeadNode(
N);
2185void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2187 EVT VT =
N->getValueType(0);
2191 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2193 for (
unsigned i = 0; i < NumVecs; ++i)
2194 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2195 AArch64::zsub0 + i,
DL, VT, SuperReg));
2197 CurDAG->RemoveDeadNode(
N);
2200void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2203 EVT VT =
N->getValueType(0);
2205 Ops.push_back(
N->getOperand(0));
2208 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2211 for (
unsigned i = 0; i < NumVecs; ++i)
2212 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2213 AArch64::zsub0 + i,
DL, VT, SuperReg));
2216 unsigned ChainIdx = NumVecs;
2218 CurDAG->RemoveDeadNode(
N);
2221void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2226 assert(Opcode != 0 &&
"Unexpected opcode");
2229 EVT VT =
N->getValueType(0);
2230 SDUse *OpsIter =
N->op_begin() + 1;
2233 auto GetMultiVecOperand = [&]() {
2236 return createZMulTuple(Regs);
2240 Ops.push_back(*OpsIter++);
2242 Ops.push_back(GetMultiVecOperand());
2244 Ops.push_back(GetMultiVecOperand());
2246 Ops.push_back(*OpsIter++);
2249 Ops.append(OpsIter,
N->op_end());
2251 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2253 for (
unsigned i = 0; i < NumVecs; ++i)
2254 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2255 AArch64::zsub0 + i,
DL, VT, SuperReg));
2257 CurDAG->RemoveDeadNode(
N);
2260void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2261 unsigned Scale,
unsigned Opc_ri,
2262 unsigned Opc_rr,
bool IsIntr) {
2263 assert(Scale < 5 &&
"Invalid scaling value.");
2265 EVT VT =
N->getValueType(0);
2272 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2273 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2279 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2281 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2283 for (
unsigned i = 0; i < NumVecs; ++i)
2284 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2285 AArch64::zsub0 + i,
DL, VT, SuperReg));
2288 unsigned ChainIdx = NumVecs;
2290 CurDAG->RemoveDeadNode(
N);
2293void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2298 assert(Scale < 4 &&
"Invalid scaling value.");
2300 EVT VT =
N->getValueType(0);
2308 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2314 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2316 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2318 for (
unsigned i = 0; i < NumVecs; ++i)
2319 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2320 AArch64::zsub0 + i,
DL, VT, SuperReg));
2323 unsigned ChainIdx = NumVecs;
2325 CurDAG->RemoveDeadNode(
N);
2328void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2330 if (
N->getValueType(0) != MVT::nxv4f32)
2332 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2335void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2336 unsigned NumOutVecs,
2340 if (
Imm->getZExtValue() > MaxImm)
2344 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2350 EVT VT =
Node->getValueType(0);
2353 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2356 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2357 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2358 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2361 unsigned ChainIdx = NumOutVecs;
2363 CurDAG->RemoveDeadNode(Node);
2366void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2367 unsigned NumIndexVecs) {
2368 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2369 "unexpected number of index vectors");
2371 constexpr unsigned FirstIndexOp = 3;
2372 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2374 if (!
Imm ||
Imm->getZExtValue() > 1)
2380 unsigned Lane =
Imm->getZExtValue();
2381 unsigned IndexOp = FirstIndexOp;
2382 if (NumIndexVecs == 3)
2385 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2387 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2388 SDValue Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2391 EVT VT =
Node->getValueType(0);
2393 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2396 for (
unsigned I = 0;
I < 4; ++
I)
2397 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2398 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2400 CurDAG->RemoveDeadNode(Node);
2403void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2404 unsigned NumOutVecs,
2406 unsigned NumInVecs) {
2407 assert((NumInVecs == 2 || NumInVecs == 3) &&
2408 "unexpected number of input vectors");
2411 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2415 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2419 EVT VT =
Node->getValueType(0);
2422 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2425 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2426 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2427 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2430 CurDAG->RemoveDeadNode(Node);
2433void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2436 EVT VT =
N->getValueType(0);
2439 SDValue Zd = createZMulTuple(Regs);
2440 SDValue Zn =
N->getOperand(1 + NumVecs);
2441 SDValue Zm =
N->getOperand(2 + NumVecs);
2447 for (
unsigned i = 0; i < NumVecs; ++i)
2448 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2449 AArch64::zsub0 + i,
DL, VT, SuperReg));
2451 CurDAG->RemoveDeadNode(
N);
2481template <
unsigned MaxIdx,
unsigned Scale>
2482void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2483 unsigned BaseReg,
unsigned Op) {
2484 unsigned TileNum = 0;
2485 if (BaseReg != AArch64::ZA)
2486 TileNum =
N->getConstantOperandVal(2);
2492 if (BaseReg == AArch64::ZA)
2497 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2501 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2503 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2505 EVT VT =
N->getValueType(0);
2506 for (
unsigned I = 0;
I < NumVecs; ++
I)
2508 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2511 unsigned ChainIdx = NumVecs;
2513 CurDAG->RemoveDeadNode(
N);
2516void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2517 unsigned Op,
unsigned MaxIdx,
2518 unsigned Scale,
unsigned BaseReg) {
2523 if (BaseReg != AArch64::ZA)
2527 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2534 if (BaseReg != AArch64::ZA )
2535 Ops.push_back(
N->getOperand(2));
2538 Ops.push_back(
N->getOperand(0));
2539 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2541 EVT VT =
N->getValueType(0);
2542 for (
unsigned I = 0;
I < NumVecs; ++
I)
2544 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2548 unsigned ChainIdx = NumVecs;
2550 CurDAG->RemoveDeadNode(
N);
2553void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2554 unsigned NumOutVecs,
2558 EVT VT =
N->getValueType(0);
2559 unsigned NumInVecs =
N->getNumOperands() - 1;
2563 assert((NumInVecs == 2 || NumInVecs == 4) &&
2564 "Don't know how to handle multi-register input!");
2566 Ops.push_back(createZMulTuple(Regs));
2569 for (
unsigned I = 0;
I < NumInVecs;
I++)
2570 Ops.push_back(
N->getOperand(1 +
I));
2573 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2576 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2577 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2578 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2579 CurDAG->RemoveDeadNode(
N);
2582void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2585 EVT VT =
N->getOperand(2)->getValueType(0);
2593 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2602void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2603 unsigned Scale,
unsigned Opc_rr,
2609 SDValue RegSeq = createZTuple(Regs);
2615 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2616 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2622 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2631void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2634 EVT VT =
N->getOperand(2)->getValueType(0);
2635 const EVT ResTys[] = {MVT::i64,
2647 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2691void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2694 EVT VT =
N->getValueType(0);
2706 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2708 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2710 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2712 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2716 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2717 AArch64::qsub2, AArch64::qsub3 };
2718 for (
unsigned i = 0; i < NumVecs; ++i) {
2719 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2726 CurDAG->RemoveDeadNode(
N);
2729void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2732 EVT VT =
N->getValueType(0);
2744 const EVT ResTys[] = {MVT::i64,
2747 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2750 CurDAG->getTargetConstant(LaneNo, dl,
2755 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2767 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2768 AArch64::qsub2, AArch64::qsub3 };
2769 for (
unsigned i = 0; i < NumVecs; ++i) {
2770 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2780 CurDAG->RemoveDeadNode(
N);
2783void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2786 EVT VT =
N->getOperand(2)->getValueType(0);
2798 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2800 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2802 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2811void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2814 EVT VT =
N->getOperand(2)->getValueType(0);
2826 const EVT ResTys[] = {MVT::i64,
2829 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2831 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2835 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2846 unsigned &LSB,
unsigned &MSB,
2847 unsigned NumberOfIgnoredLowBits,
2848 bool BiggerPattern) {
2850 "N must be a AND operation to call this function");
2852 EVT VT =
N->getValueType(0);
2857 assert((VT == MVT::i32 || VT == MVT::i64) &&
2858 "Type checking must have been done before calling this function");
2872 const SDNode *Op0 =
N->getOperand(0).getNode();
2879 if (AndImm & (AndImm + 1))
2882 bool ClampMSB =
false;
2902 ClampMSB = (VT == MVT::i32);
2903 }
else if (BiggerPattern) {
2909 Opd0 =
N->getOperand(0);
2915 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2918 <<
": Found large shift immediate, this should not happen\n"));
2932 MSB = MSB > 31 ? 31 : MSB;
2934 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2939 SDValue &Opd0,
unsigned &Immr,
2943 EVT VT =
N->getValueType(0);
2945 assert((VT == MVT::i32 || VT == MVT::i64) &&
2946 "Type checking must have been done before calling this function");
2950 Op =
Op->getOperand(0);
2951 VT =
Op->getValueType(0);
2960 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2964 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2965 Opd0 =
Op.getOperand(0);
2967 Imms = ShiftImm + Width - 1;
2995 Opd0 =
N->getOperand(0).getOperand(0);
3005 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3012 unsigned &Immr,
unsigned &Imms,
3013 bool BiggerPattern) {
3015 "N must be a SHR/SRA operation to call this function");
3017 EVT VT =
N->getValueType(0);
3022 assert((VT == MVT::i32 || VT == MVT::i64) &&
3023 "Type checking must have been done before calling this function");
3033 Opd0 =
N->getOperand(0).getOperand(0);
3034 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3040 Opd0 =
N->getOperand(0).getOperand(0);
3043 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3044 }
else if (BiggerPattern) {
3048 Opd0 =
N->getOperand(0);
3057 <<
": Found large shift immediate, this should not happen\n"));
3066 "bad amount in shift node!");
3067 int immr = SrlImm - ShlImm;
3072 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3074 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3078bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
3081 EVT VT =
N->getValueType(0);
3082 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
3083 if (VT != MVT::i64 || NarrowVT != MVT::i32)
3094 unsigned Immr = ShiftImm;
3096 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3097 CurDAG->getTargetConstant(Imms, dl, VT)};
3098 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
3103 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3104 unsigned NumberOfIgnoredLowBits = 0,
3105 bool BiggerPattern =
false) {
3106 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3109 switch (
N->getOpcode()) {
3111 if (!
N->isMachineOpcode())
3116 NumberOfIgnoredLowBits, BiggerPattern);
3125 unsigned NOpc =
N->getMachineOpcode();
3129 case AArch64::SBFMWri:
3130 case AArch64::UBFMWri:
3131 case AArch64::SBFMXri:
3132 case AArch64::UBFMXri:
3134 Opd0 =
N->getOperand(0);
3135 Immr =
N->getConstantOperandVal(1);
3136 Imms =
N->getConstantOperandVal(2);
3143bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3144 unsigned Opc, Immr, Imms;
3149 EVT VT =
N->getValueType(0);
3154 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3155 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3156 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3158 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3159 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3165 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3166 CurDAG->getTargetConstant(Imms, dl, VT)};
3167 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3176 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3177 assert((VT == MVT::i32 || VT == MVT::i64) &&
3178 "i32 or i64 mask type expected!");
3182 APInt SignificantDstMask =
3186 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3187 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3220 APInt OpUsefulBits(UsefulBits);
3224 OpUsefulBits <<= MSB -
Imm + 1;
3229 OpUsefulBits <<=
Imm;
3231 OpUsefulBits <<= MSB + 1;
3240 UsefulBits &= OpUsefulBits;
3257 APInt Mask(UsefulBits);
3258 Mask.clearAllBits();
3266 Mask.lshrInPlace(ShiftAmt);
3272 Mask.lshrInPlace(ShiftAmt);
3288 APInt OpUsefulBits(UsefulBits);
3302 OpUsefulBits <<= Width;
3305 if (
Op.getOperand(1) == Orig) {
3307 Mask = ResultUsefulBits & OpUsefulBits;
3311 if (
Op.getOperand(0) == Orig)
3313 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3319 OpUsefulBits <<= Width;
3321 OpUsefulBits <<= LSB;
3323 if (
Op.getOperand(1) == Orig) {
3325 Mask = ResultUsefulBits & OpUsefulBits;
3326 Mask.lshrInPlace(LSB);
3329 if (
Op.getOperand(0) == Orig)
3330 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3347 case AArch64::ANDSWri:
3348 case AArch64::ANDSXri:
3349 case AArch64::ANDWri:
3350 case AArch64::ANDXri:
3354 case AArch64::UBFMWri:
3355 case AArch64::UBFMXri:
3358 case AArch64::ORRWrs:
3359 case AArch64::ORRXrs:
3364 case AArch64::BFMWri:
3365 case AArch64::BFMXri:
3368 case AArch64::STRBBui:
3369 case AArch64::STURBBi:
3375 case AArch64::STRHHui:
3376 case AArch64::STURHHi:
3389 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3391 UsefulBits =
APInt(Bitwidth, 0);
3400 UsersUsefulBits |= UsefulBitsForUse;
3405 UsefulBits &= UsersUsefulBits;
3415 EVT VT =
Op.getValueType();
3418 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3421 if (ShlAmount > 0) {
3424 UBFMOpc, dl, VT,
Op,
3429 assert(ShlAmount < 0 &&
"expected right shift");
3430 int ShrAmount = -ShlAmount;
3456 bool BiggerPattern,
SDValue &Src,
3457 int &DstLSB,
int &Width) {
3458 EVT VT =
Op.getValueType();
3471 switch (
Op.getOpcode()) {
3476 NonZeroBits, Src, DstLSB, Width);
3479 NonZeroBits, Src, DstLSB, Width);
3492 EVT VT =
Op.getValueType();
3493 assert((VT == MVT::i32 || VT == MVT::i64) &&
3494 "Caller guarantees VT is one of i32 or i64");
3507 assert((~AndImm & NonZeroBits) == 0 &&
3508 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3537 if (!BiggerPattern && !AndOp0.
hasOneUse())
3556 <<
"Found large Width in bit-field-positioning -- this indicates no "
3557 "proper combining / constant folding was performed\n");
3566 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3581 "Op.getNode() should be a SHL node to call this function");
3583 "Op.getNode() should shift ShlImm to call this function");
3590 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3614 EVT VT =
Op.getValueType();
3615 assert((VT == MVT::i32 || VT == MVT::i64) &&
3616 "Caller guarantees that type is i32 or i64");
3623 if (!BiggerPattern && !
Op.hasOneUse())
3632 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3640 assert(VT == MVT::i32 || VT == MVT::i64);
3651 EVT VT =
N->getValueType(0);
3652 if (VT != MVT::i32 && VT != MVT::i64)
3670 if (!
And.hasOneUse() ||
3687 if ((OrImm & NotKnownZero) != 0) {
3699 unsigned ImmS = Width - 1;
3705 bool IsBFI = LSB != 0;
3710 unsigned OrChunks = 0, BFIChunks = 0;
3711 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3712 if (((OrImm >> Shift) & 0xFFFF) != 0)
3714 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3717 if (BFIChunks > OrChunks)
3723 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3731 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3740 if (!Dst.hasOneUse())
3743 EVT VT = Dst.getValueType();
3744 assert((VT == MVT::i32 || VT == MVT::i64) &&
3745 "Caller should guarantee that VT is one of i32 or i64");
3773 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3774 unsigned MaskWidth =
3777 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3783 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3784 ShiftedOperand =
SDValue(UBFMNode, 0);
3813 const bool BiggerPattern) {
3814 EVT VT =
N->getValueType(0);
3815 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3816 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3817 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3818 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3819 assert((VT == MVT::i32 || VT == MVT::i64) &&
3820 "Expect result type to be i32 or i64 since N is combinable to BFM");
3827 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3830 if (BiggerPattern) {
3853 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3915 EVT VT =
N->getValueType(0);
3916 if (VT != MVT::i32 && VT != MVT::i64)
3924 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3925 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3945 for (
int I = 0;
I < 4; ++
I) {
3948 unsigned ImmR, ImmS;
3949 bool BiggerPattern =
I / 2;
3950 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3952 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3958 NumberOfIgnoredLowBits, BiggerPattern)) {
3961 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3962 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3967 Width = ImmS - ImmR + 1;
3978 Src, DstLSB, Width)) {
3986 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3996 APInt BitsToBeInserted =
3999 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4023 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4056 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4058 if (Src->hasOneUse() &&
4061 Src = Src->getOperand(0);
4071 unsigned ImmS = Width - 1;
4077 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4085bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4094 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4107bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4111 EVT VT =
N->getValueType(0);
4112 if (VT != MVT::i32 && VT != MVT::i64)
4118 Op0, DstLSB, Width))
4124 unsigned ImmS = Width - 1;
4127 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4128 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4129 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4130 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4136bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4137 EVT VT =
N->getValueType(0);
4140 switch (
N->getOpcode()) {
4142 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4145 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4148 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4151 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4159 if (VT == MVT::i32) {
4162 }
else if (VT == MVT::i64) {
4168 SDValue ShiftAmt =
N->getOperand(1);
4188 (Add0Imm %
Size == 0)) {
4194 if (SubVT == MVT::i32) {
4195 NegOpc = AArch64::SUBWrr;
4196 ZeroReg = AArch64::WZR;
4198 assert(SubVT == MVT::i64);
4199 NegOpc = AArch64::SUBXrr;
4200 ZeroReg = AArch64::XZR;
4203 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4204 MachineSDNode *Neg =
4205 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4206 NewShiftAmt =
SDValue(Neg, 0);
4214 if (SubVT == MVT::i32) {
4215 NotOpc = AArch64::ORNWrr;
4216 ZeroReg = AArch64::WZR;
4218 assert(SubVT == MVT::i64);
4219 NotOpc = AArch64::ORNXrr;
4220 ZeroReg = AArch64::XZR;
4223 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4224 MachineSDNode *
Not =
4225 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4247 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4248 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4249 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4250 NewShiftAmt, SubReg);
4251 NewShiftAmt =
SDValue(Ext, 0);
4255 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4262 bool isReciprocal) {
4265 FVal = CN->getValueAPF();
4268 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4278 if (
unsigned FBits =
4291 bool isReciprocal) {
4292 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4293 N.getValueType().getScalarSizeInBits() ==
4294 N.getOperand(0).getValueType().getScalarSizeInBits())
4295 N =
N.getOperand(0);
4297 auto ImmToFloat = [RegWidth](
APInt Imm) {
4311 switch (
N->getOpcode()) {
4312 case AArch64ISD::MOVIshift:
4313 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4314 <<
N.getConstantOperandVal(1)));
4316 case AArch64ISD::FMOV:
4317 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4319 case AArch64ISD::DUP:
4321 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4329 if (
unsigned FBits =
4338bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4339 unsigned RegWidth) {
4344bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
4345 unsigned RegWidth) {
4347 CurDAG,
N, FixedPos, RegWidth,
false);
4350bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(
SDValue N,
4352 unsigned RegWidth) {
4354 CurDAG,
N, FixedPos, RegWidth,
true);
4357bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4359 unsigned RegWidth) {
4369 RegString.
split(Fields,
':');
4371 if (Fields.
size() == 1)
4375 &&
"Invalid number of fields in read register string");
4378 bool AllIntFields =
true;
4382 AllIntFields &= !
Field.getAsInteger(10, IntField);
4383 Ops.push_back(IntField);
4387 "Unexpected non-integer value in special register string.");
4392 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4400bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4402 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4405 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4407 unsigned Opcode64Bit = AArch64::MRS;
4412 const auto *TheReg =
4413 AArch64SysReg::lookupSysRegByName(RegString->getString());
4414 if (TheReg && TheReg->Readable &&
4415 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4416 Imm = TheReg->Encoding;
4422 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4423 Opcode64Bit = AArch64::ADR;
4432 RegString->getString());
4433 unsigned PseudoOp = 0;
4434 if (AArch64::GPR64RegClass.
contains(PReg))
4435 PseudoOp = AArch64::READ_REGISTER_GPR64;
4436 else if (AArch64::FPR64RegClass.
contains(PReg))
4437 PseudoOp = AArch64::READ_REGISTER_FPR64;
4438 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4439 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4440 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4449 SDValue InChain =
N->getOperand(0);
4450 SDValue SysRegImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
4451 if (!ReadIs128Bit) {
4452 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4453 {SysRegImm, InChain});
4455 SDNode *MRRS = CurDAG->getMachineNode(
4457 {MVT::Untyped , MVT::Other },
4458 {SysRegImm, InChain});
4462 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4464 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4470 ReplaceUses(
SDValue(
N, 2), OutChain);
4479bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4481 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4484 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4486 if (!WriteIs128Bit) {
4492 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4495 "Expected a constant integer expression.");
4496 unsigned Reg = PMapper->Encoding;
4497 uint64_t Immed =
N->getConstantOperandVal(2);
4498 CurDAG->SelectNodeTo(
4499 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4500 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4506 if (trySelectPState(
4507 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4508 AArch64::MSRpstateImm4))
4510 if (trySelectPState(
4511 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4512 AArch64::MSRpstateImm1))
4521 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4522 if (TheReg && TheReg->Writeable &&
4523 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4524 Imm = TheReg->Encoding;
4534 RegString->getString());
4535 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4536 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4537 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4538 N->getOperand(2).getValueType() == MVT::i64) {
4540 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4541 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4542 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4543 MVT::Other, {RegOp,
Copy});
4545 CurDAG->RemoveDeadNode(
N);
4553 if (!WriteIs128Bit) {
4554 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4555 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4556 N->getOperand(2), InChain);
4560 SDNode *Pair = CurDAG->getMachineNode(
4561 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4562 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4565 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4567 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4569 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4570 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4578bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4583 if (Subtarget->hasLSE())
return false;
4585 if (MemTy == MVT::i8)
4586 Opcode = AArch64::CMP_SWAP_8;
4587 else if (MemTy == MVT::i16)
4588 Opcode = AArch64::CMP_SWAP_16;
4589 else if (MemTy == MVT::i32)
4590 Opcode = AArch64::CMP_SWAP_32;
4591 else if (MemTy == MVT::i64)
4592 Opcode = AArch64::CMP_SWAP_64;
4596 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4597 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4599 SDNode *CmpSwap = CurDAG->getMachineNode(
4601 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4608 CurDAG->RemoveDeadNode(
N);
4614 SDValue &Shift,
bool Negate) {
4621 return SelectSVEAddSubImm(SDLoc(
N), Val, VT,
Imm, Shift, Negate);
4624bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4633 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4640 if ((Val & ~0xff) == 0) {
4641 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4646 if ((Val & ~0xff00) == 0) {
4647 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4659bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4683 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4684 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4691 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4692 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4696 if (Val <= 65280 && Val % 256 == 0) {
4697 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4698 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4719 int32_t ImmVal, ShiftVal;
4724 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4725 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4731 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(),
Imm);
4735bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4738 if (ImmVal >= -128 && ImmVal < 128) {
4739 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4747 uint64_t ImmVal = CNode->getZExtValue();
4757 ImmVal &= 0xFFFFFFFF;
4766 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4777 ImmVal = CI->getZExtValue();
4779 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4790 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4803 uint64_t ImmVal = CN->getZExtValue();
4810 if (ImmVal >
High) {
4811 if (!AllowSaturation)
4816 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4823bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4837 const TargetLowering *TLI = getTargetLowering();
4840 SDValue FiOp = CurDAG->getTargetFrameIndex(
4842 int TagOffset =
N->getConstantOperandVal(3);
4844 SDNode *Out = CurDAG->getMachineNode(
4845 AArch64::TAGPstack,
DL, MVT::i64,
4846 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4847 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4848 ReplaceNode(
N, Out);
4852void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4854 "llvm.aarch64.tagp third argument must be an immediate");
4855 if (trySelectStackSlotTagP(
N))
4862 int TagOffset =
N->getConstantOperandVal(3);
4863 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4864 {
N->getOperand(1),
N->getOperand(2)});
4865 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4866 {
SDValue(N1, 0),
N->getOperand(2)});
4867 SDNode *N3 = CurDAG->getMachineNode(
4868 AArch64::ADDG,
DL, MVT::i64,
4869 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4870 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4874bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4878 if (
N->getConstantOperandVal(2) != 0)
4880 if (!
N->getOperand(0).isUndef())
4884 EVT VT =
N->getValueType(0);
4885 EVT InVT =
N->getOperand(1).getValueType();
4896 "Expected to insert into a packed scalable vector!");
4899 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4900 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4901 N->getOperand(1), RC));
4905bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4909 if (
N->getConstantOperandVal(1) != 0)
4913 EVT VT =
N->getValueType(0);
4914 EVT InVT =
N->getOperand(0).getValueType();
4925 "Expected to extract from a packed scalable vector!");
4928 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4929 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4930 N->getOperand(0), RC));
4934bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4940 EVT VT =
N->getValueType(0);
4953 (Subtarget->hasSVE2() ||
4954 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4955 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4958 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4962 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4963 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4964 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4971 bool IsXOROperand =
true;
4973 IsXOROperand =
false;
4979 APInt ShlAmt, ShrAmt;
4987 if (!IsXOROperand) {
4989 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4992 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4993 SDNode *SubRegToReg =
4994 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
5005 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5006 AArch64::XAR_ZZZI_D})) {
5007 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5032 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5042 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5050 bool IsXOROperand =
true;
5052 IsXOROperand =
false;
5055 R1 =
XOR.getOperand(0);
5056 R2 =
XOR.getOperand(1);
5066 if (ShAmt + HsAmt != VTSizeInBits)
5069 if (!IsXOROperand) {
5072 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5081 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5087 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5088 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5090 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5093 if (
R2.getValueType() == VT)
5094 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5099 SDValue SubReg = CurDAG->getTargetConstant(
5102 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5107 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5113 SDNode *XAR =
nullptr;
5117 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5118 AArch64::XAR_ZZZI_D}))
5119 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5121 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5124 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5130 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5131 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5134 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5135 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5138 SDValue SubReg = CurDAG->getTargetConstant(
5141 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5145 ReplaceNode(
N, XAR);
5152 assert(VT == MVT::i32 || VT == MVT::i64);
5154 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5157void AArch64DAGToDAGISel::Select(SDNode *Node) {
5159 if (
Node->isMachineOpcode()) {
5161 Node->setNodeId(-1);
5166 EVT VT =
Node->getValueType(0);
5168 switch (
Node->getOpcode()) {
5173 if (SelectCMP_SWAP(Node))
5178 case AArch64ISD::MRRS:
5179 if (tryReadRegister(Node))
5184 case AArch64ISD::MSRR:
5185 if (tryWriteRegister(Node))
5192 if (tryIndexedLoad(Node))
5201 if (tryBitfieldExtractOp(Node))
5203 if (tryBitfieldInsertInZeroOp(Node))
5208 if (tryShiftAmountMod(Node))
5213 if (tryBitfieldExtractOpFromSExt(Node))
5218 if (tryBitfieldInsertOp(Node))
5220 if (trySelectXAR(Node))
5225 if (trySelectCastScalableToFixedLengthVector(Node))
5231 if (trySelectCastFixedLengthToScalableVector(Node))
5236 case AArch64ISD::CSEL:
5237 if (tryFoldCselToFMaxMin(Node))
5245 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5256 const TargetLowering *TLI = getTargetLowering();
5257 SDValue TFI = CurDAG->getTargetFrameIndex(
5260 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5261 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5262 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5266 unsigned IntNo =
Node->getConstantOperandVal(1);
5270 case Intrinsic::aarch64_gcsss: {
5274 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5276 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5277 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5278 MVT::Other, Zero,
SDValue(SS1, 0));
5279 ReplaceNode(Node, SS2);
5282 case Intrinsic::aarch64_ldaxp:
5283 case Intrinsic::aarch64_ldxp: {
5285 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5290 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5291 MVT::Other, MemAddr, Chain);
5294 MachineMemOperand *MemOp =
5297 ReplaceNode(Node, Ld);
5300 case Intrinsic::aarch64_stlxp:
5301 case Intrinsic::aarch64_stxp: {
5303 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5311 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5313 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5315 MachineMemOperand *MemOp =
5319 ReplaceNode(Node, St);
5322 case Intrinsic::aarch64_neon_ld1x2:
5323 if (VT == MVT::v8i8) {
5324 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5326 }
else if (VT == MVT::v16i8) {
5327 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5329 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5330 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5332 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5333 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5335 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5336 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5338 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5339 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5341 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5342 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5344 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5345 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5349 case Intrinsic::aarch64_neon_ld1x3:
5350 if (VT == MVT::v8i8) {
5351 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5353 }
else if (VT == MVT::v16i8) {
5354 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5356 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5357 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5359 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5360 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5362 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5363 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5365 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5366 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5368 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5369 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5371 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5372 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5376 case Intrinsic::aarch64_neon_ld1x4:
5377 if (VT == MVT::v8i8) {
5378 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5380 }
else if (VT == MVT::v16i8) {
5381 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5383 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5384 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5386 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5387 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5389 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5390 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5392 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5393 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5395 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5396 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5398 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5399 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5403 case Intrinsic::aarch64_neon_ld2:
5404 if (VT == MVT::v8i8) {
5405 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5407 }
else if (VT == MVT::v16i8) {
5408 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5410 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5411 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5413 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5414 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5416 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5417 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5419 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5420 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5422 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5423 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5425 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5426 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5430 case Intrinsic::aarch64_neon_ld3:
5431 if (VT == MVT::v8i8) {
5432 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5434 }
else if (VT == MVT::v16i8) {
5435 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5437 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5438 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5440 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5441 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5443 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5444 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5446 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5447 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5449 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5450 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5452 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5453 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5457 case Intrinsic::aarch64_neon_ld4:
5458 if (VT == MVT::v8i8) {
5459 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5461 }
else if (VT == MVT::v16i8) {
5462 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5464 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5465 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5467 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5468 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5470 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5471 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5473 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5474 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5476 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5477 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5479 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5480 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5484 case Intrinsic::aarch64_neon_ld2r:
5485 if (VT == MVT::v8i8) {
5486 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5488 }
else if (VT == MVT::v16i8) {
5489 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5491 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5492 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5494 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5495 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5497 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5498 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5500 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5501 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5503 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5504 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5506 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5507 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5511 case Intrinsic::aarch64_neon_ld3r:
5512 if (VT == MVT::v8i8) {
5513 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5515 }
else if (VT == MVT::v16i8) {
5516 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5518 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5519 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5521 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5522 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5524 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5525 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5527 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5528 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5530 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5531 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5533 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5534 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5538 case Intrinsic::aarch64_neon_ld4r:
5539 if (VT == MVT::v8i8) {
5540 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5542 }
else if (VT == MVT::v16i8) {
5543 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5545 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5546 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5548 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5549 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5551 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5552 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5554 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5555 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5557 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5558 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5560 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5561 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5565 case Intrinsic::aarch64_neon_ld2lane:
5566 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5567 SelectLoadLane(Node, 2, AArch64::LD2i8);
5569 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5570 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5571 SelectLoadLane(Node, 2, AArch64::LD2i16);
5573 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5575 SelectLoadLane(Node, 2, AArch64::LD2i32);
5577 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5579 SelectLoadLane(Node, 2, AArch64::LD2i64);
5583 case Intrinsic::aarch64_neon_ld3lane:
5584 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5585 SelectLoadLane(Node, 3, AArch64::LD3i8);
5587 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5588 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5589 SelectLoadLane(Node, 3, AArch64::LD3i16);
5591 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5593 SelectLoadLane(Node, 3, AArch64::LD3i32);
5595 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5597 SelectLoadLane(Node, 3, AArch64::LD3i64);
5601 case Intrinsic::aarch64_neon_ld4lane:
5602 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5603 SelectLoadLane(Node, 4, AArch64::LD4i8);
5605 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5606 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5607 SelectLoadLane(Node, 4, AArch64::LD4i16);
5609 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5611 SelectLoadLane(Node, 4, AArch64::LD4i32);
5613 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5615 SelectLoadLane(Node, 4, AArch64::LD4i64);
5619 case Intrinsic::aarch64_ld64b:
5620 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5622 case Intrinsic::aarch64_sve_ld2q_sret: {
5623 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5626 case Intrinsic::aarch64_sve_ld3q_sret: {
5627 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5630 case Intrinsic::aarch64_sve_ld4q_sret: {
5631 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5634 case Intrinsic::aarch64_sve_ld2_sret: {
5635 if (VT == MVT::nxv16i8) {
5636 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5639 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5640 VT == MVT::nxv8bf16) {
5641 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5644 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5645 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5648 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5649 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5655 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5656 if (VT == MVT::nxv16i8) {
5657 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5658 SelectContiguousMultiVectorLoad(
5659 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5660 else if (Subtarget->hasSVE2p1())
5661 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5666 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5667 VT == MVT::nxv8bf16) {
5668 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5669 SelectContiguousMultiVectorLoad(
5670 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5671 else if (Subtarget->hasSVE2p1())
5672 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5677 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5678 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5679 SelectContiguousMultiVectorLoad(
5680 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5681 else if (Subtarget->hasSVE2p1())
5682 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5687 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5688 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5689 SelectContiguousMultiVectorLoad(
5690 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5691 else if (Subtarget->hasSVE2p1())
5692 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5700 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5701 if (VT == MVT::nxv16i8) {
5702 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5703 SelectContiguousMultiVectorLoad(
5704 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5705 else if (Subtarget->hasSVE2p1())
5706 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5711 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5712 VT == MVT::nxv8bf16) {
5713 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5714 SelectContiguousMultiVectorLoad(
5715 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5716 else if (Subtarget->hasSVE2p1())
5717 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5722 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5723 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5724 SelectContiguousMultiVectorLoad(
5725 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5726 else if (Subtarget->hasSVE2p1())
5727 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5732 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5733 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5734 SelectContiguousMultiVectorLoad(
5735 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5736 else if (Subtarget->hasSVE2p1())
5737 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5745 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5746 if (VT == MVT::nxv16i8) {
5747 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5748 SelectContiguousMultiVectorLoad(Node, 2, 0,
5749 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5750 AArch64::LDNT1B_2Z_PSEUDO);
5751 else if (Subtarget->hasSVE2p1())
5752 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5753 AArch64::LDNT1B_2Z);
5757 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5758 VT == MVT::nxv8bf16) {
5759 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5760 SelectContiguousMultiVectorLoad(Node, 2, 1,
5761 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5762 AArch64::LDNT1H_2Z_PSEUDO);
5763 else if (Subtarget->hasSVE2p1())
5764 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5765 AArch64::LDNT1H_2Z);
5769 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5770 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5771 SelectContiguousMultiVectorLoad(Node, 2, 2,
5772 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5773 AArch64::LDNT1W_2Z_PSEUDO);
5774 else if (Subtarget->hasSVE2p1())
5775 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5776 AArch64::LDNT1W_2Z);
5780 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5781 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5782 SelectContiguousMultiVectorLoad(Node, 2, 3,
5783 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5784 AArch64::LDNT1D_2Z_PSEUDO);
5785 else if (Subtarget->hasSVE2p1())
5786 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5787 AArch64::LDNT1D_2Z);
5794 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5795 if (VT == MVT::nxv16i8) {
5796 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5797 SelectContiguousMultiVectorLoad(Node, 4, 0,
5798 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5799 AArch64::LDNT1B_4Z_PSEUDO);
5800 else if (Subtarget->hasSVE2p1())
5801 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5802 AArch64::LDNT1B_4Z);
5806 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5807 VT == MVT::nxv8bf16) {
5808 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5809 SelectContiguousMultiVectorLoad(Node, 4, 1,
5810 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5811 AArch64::LDNT1H_4Z_PSEUDO);
5812 else if (Subtarget->hasSVE2p1())
5813 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5814 AArch64::LDNT1H_4Z);
5818 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5819 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5820 SelectContiguousMultiVectorLoad(Node, 4, 2,
5821 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5822 AArch64::LDNT1W_4Z_PSEUDO);
5823 else if (Subtarget->hasSVE2p1())
5824 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5825 AArch64::LDNT1W_4Z);
5829 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5830 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5831 SelectContiguousMultiVectorLoad(Node, 4, 3,
5832 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5833 AArch64::LDNT1D_4Z_PSEUDO);
5834 else if (Subtarget->hasSVE2p1())
5835 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5836 AArch64::LDNT1D_4Z);
5843 case Intrinsic::aarch64_sve_ld3_sret: {
5844 if (VT == MVT::nxv16i8) {
5845 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5848 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5849 VT == MVT::nxv8bf16) {
5850 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5853 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5854 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5857 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5858 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5864 case Intrinsic::aarch64_sve_ld4_sret: {
5865 if (VT == MVT::nxv16i8) {
5866 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5869 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5870 VT == MVT::nxv8bf16) {
5871 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5874 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5875 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5878 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5879 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5885 case Intrinsic::aarch64_sme_read_hor_vg2: {
5886 if (VT == MVT::nxv16i8) {
5887 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5888 AArch64::MOVA_2ZMXI_H_B);
5890 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5891 VT == MVT::nxv8bf16) {
5892 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5893 AArch64::MOVA_2ZMXI_H_H);
5895 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5896 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5897 AArch64::MOVA_2ZMXI_H_S);
5899 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5900 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5901 AArch64::MOVA_2ZMXI_H_D);
5906 case Intrinsic::aarch64_sme_read_ver_vg2: {
5907 if (VT == MVT::nxv16i8) {
5908 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5909 AArch64::MOVA_2ZMXI_V_B);
5911 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5912 VT == MVT::nxv8bf16) {
5913 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5914 AArch64::MOVA_2ZMXI_V_H);
5916 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5917 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5918 AArch64::MOVA_2ZMXI_V_S);
5920 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5921 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5922 AArch64::MOVA_2ZMXI_V_D);
5927 case Intrinsic::aarch64_sme_read_hor_vg4: {
5928 if (VT == MVT::nxv16i8) {
5929 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5930 AArch64::MOVA_4ZMXI_H_B);
5932 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5933 VT == MVT::nxv8bf16) {
5934 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5935 AArch64::MOVA_4ZMXI_H_H);
5937 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5938 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5939 AArch64::MOVA_4ZMXI_H_S);
5941 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5942 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5943 AArch64::MOVA_4ZMXI_H_D);
5948 case Intrinsic::aarch64_sme_read_ver_vg4: {
5949 if (VT == MVT::nxv16i8) {
5950 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5951 AArch64::MOVA_4ZMXI_V_B);
5953 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5954 VT == MVT::nxv8bf16) {
5955 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5956 AArch64::MOVA_4ZMXI_V_H);
5958 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5959 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5960 AArch64::MOVA_4ZMXI_V_S);
5962 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5963 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5964 AArch64::MOVA_4ZMXI_V_D);
5969 case Intrinsic::aarch64_sme_read_vg1x2: {
5970 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5971 AArch64::MOVA_VG2_2ZMXI);
5974 case Intrinsic::aarch64_sme_read_vg1x4: {
5975 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5976 AArch64::MOVA_VG4_4ZMXI);
5979 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5980 if (VT == MVT::nxv16i8) {
5981 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5983 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5984 VT == MVT::nxv8bf16) {
5985 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5987 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5988 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5990 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5991 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5996 case Intrinsic::aarch64_sme_readz_vert_x2: {
5997 if (VT == MVT::nxv16i8) {
5998 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
6000 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6001 VT == MVT::nxv8bf16) {
6002 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
6004 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6005 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
6007 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6008 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
6013 case Intrinsic::aarch64_sme_readz_horiz_x4: {
6014 if (VT == MVT::nxv16i8) {
6015 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
6017 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6018 VT == MVT::nxv8bf16) {
6019 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6021 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6022 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6024 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6025 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6030 case Intrinsic::aarch64_sme_readz_vert_x4: {
6031 if (VT == MVT::nxv16i8) {
6032 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6034 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6035 VT == MVT::nxv8bf16) {
6036 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6038 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6039 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6041 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6042 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6047 case Intrinsic::aarch64_sme_readz_x2: {
6048 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6052 case Intrinsic::aarch64_sme_readz_x4: {
6053 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6057 case Intrinsic::swift_async_context_addr: {
6060 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6062 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6063 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6064 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6066 ReplaceUses(
SDValue(Node, 0), Res);
6068 CurDAG->RemoveDeadNode(Node);
6070 auto &MF = CurDAG->getMachineFunction();
6071 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6072 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6075 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6077 Node->getValueType(0),
6078 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6079 AArch64::LUTI2_4ZTZI_S}))
6081 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6084 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6086 Node->getValueType(0),
6087 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6089 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6092 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6094 Node->getValueType(0),
6095 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6096 AArch64::LUTI2_2ZTZI_S}))
6098 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6101 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6103 Node->getValueType(0),
6104 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6105 AArch64::LUTI4_2ZTZI_S}))
6107 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6110 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6111 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6114 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6115 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6118 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6120 Node->getValueType(0),
6121 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6122 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6124 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6126 Node->getValueType(0),
6127 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6128 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6130 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6132 Node->getValueType(0),
6133 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6134 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6136 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6138 Node->getValueType(0),
6139 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6140 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6142 case Intrinsic::ptrauth_resign_load_relative:
6143 SelectPtrauthResign(Node);
6148 unsigned IntNo =
Node->getConstantOperandVal(0);
6152 case Intrinsic::aarch64_tagp:
6156 case Intrinsic::ptrauth_auth:
6157 SelectPtrauthAuth(Node);
6160 case Intrinsic::ptrauth_resign:
6161 SelectPtrauthResign(Node);
6164 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6165 SelectPtrauthResignWithPC(Node);
6168 case Intrinsic::aarch64_neon_tbl2:
6169 SelectTable(Node, 2,
6170 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6173 case Intrinsic::aarch64_neon_tbl3:
6174 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6175 : AArch64::TBLv16i8Three,
6178 case Intrinsic::aarch64_neon_tbl4:
6179 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6180 : AArch64::TBLv16i8Four,
6183 case Intrinsic::aarch64_neon_tbx2:
6184 SelectTable(Node, 2,
6185 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6188 case Intrinsic::aarch64_neon_tbx3:
6189 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6190 : AArch64::TBXv16i8Three,
6193 case Intrinsic::aarch64_neon_tbx4:
6194 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6195 : AArch64::TBXv16i8Four,
6198 case Intrinsic::aarch64_sve_srshl_single_x2:
6200 Node->getValueType(0),
6201 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6202 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6203 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6205 case Intrinsic::aarch64_sve_srshl_single_x4:
6207 Node->getValueType(0),
6208 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6209 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6210 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6212 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6213 SelectMultiVectorLuti6LaneX4(Node, 2);
6215 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6216 SelectMultiVectorLuti6LaneX4(Node, 3);
6218 case Intrinsic::aarch64_sve_urshl_single_x2:
6220 Node->getValueType(0),
6221 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6222 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6223 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6225 case Intrinsic::aarch64_sve_urshl_single_x4:
6227 Node->getValueType(0),
6228 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6229 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6230 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6232 case Intrinsic::aarch64_sve_srshl_x2:
6234 Node->getValueType(0),
6235 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6236 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6237 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6239 case Intrinsic::aarch64_sve_srshl_x4:
6241 Node->getValueType(0),
6242 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6243 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6244 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6246 case Intrinsic::aarch64_sve_urshl_x2:
6248 Node->getValueType(0),
6249 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6250 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6251 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6253 case Intrinsic::aarch64_sve_urshl_x4:
6255 Node->getValueType(0),
6256 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6257 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6258 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6260 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6262 Node->getValueType(0),
6263 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6264 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6265 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6267 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6269 Node->getValueType(0),
6270 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6271 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6272 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6274 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6276 Node->getValueType(0),
6277 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6278 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6279 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6281 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6283 Node->getValueType(0),
6284 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6285 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6286 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6288 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6290 Node->getValueType(0),
6291 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6292 AArch64::FSCALE_2ZZ_D}))
6293 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6295 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6297 Node->getValueType(0),
6298 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6299 AArch64::FSCALE_4ZZ_D}))
6300 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6302 case Intrinsic::aarch64_sme_fp8_scale_x2:
6304 Node->getValueType(0),
6305 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6306 AArch64::FSCALE_2Z2Z_D}))
6307 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6309 case Intrinsic::aarch64_sme_fp8_scale_x4:
6311 Node->getValueType(0),
6312 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6313 AArch64::FSCALE_4Z4Z_D}))
6314 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6316 case Intrinsic::aarch64_sve_whilege_x2:
6318 Node->getValueType(0),
6319 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6320 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6321 SelectWhilePair(Node,
Op);
6323 case Intrinsic::aarch64_sve_whilegt_x2:
6325 Node->getValueType(0),
6326 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6327 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6328 SelectWhilePair(Node,
Op);
6330 case Intrinsic::aarch64_sve_whilehi_x2:
6332 Node->getValueType(0),
6333 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6334 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6335 SelectWhilePair(Node,
Op);
6337 case Intrinsic::aarch64_sve_whilehs_x2:
6339 Node->getValueType(0),
6340 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6341 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6342 SelectWhilePair(Node,
Op);
6344 case Intrinsic::aarch64_sve_whilele_x2:
6346 Node->getValueType(0),
6347 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6348 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6349 SelectWhilePair(Node,
Op);
6351 case Intrinsic::aarch64_sve_whilelo_x2:
6353 Node->getValueType(0),
6354 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6355 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6356 SelectWhilePair(Node,
Op);
6358 case Intrinsic::aarch64_sve_whilels_x2:
6360 Node->getValueType(0),
6361 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6362 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6363 SelectWhilePair(Node,
Op);
6365 case Intrinsic::aarch64_sve_whilelt_x2:
6367 Node->getValueType(0),
6368 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6369 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6370 SelectWhilePair(Node,
Op);
6372 case Intrinsic::aarch64_sve_smax_single_x2:
6374 Node->getValueType(0),
6375 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6376 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6377 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6379 case Intrinsic::aarch64_sve_umax_single_x2:
6381 Node->getValueType(0),
6382 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6383 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6384 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6386 case Intrinsic::aarch64_sve_fmax_single_x2:
6388 Node->getValueType(0),
6389 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6390 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6391 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6393 case Intrinsic::aarch64_sve_smax_single_x4:
6395 Node->getValueType(0),
6396 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6397 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6398 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6400 case Intrinsic::aarch64_sve_umax_single_x4:
6402 Node->getValueType(0),
6403 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6404 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6405 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6407 case Intrinsic::aarch64_sve_fmax_single_x4:
6409 Node->getValueType(0),
6410 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6411 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6412 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6414 case Intrinsic::aarch64_sve_smin_single_x2:
6416 Node->getValueType(0),
6417 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6418 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6419 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6421 case Intrinsic::aarch64_sve_umin_single_x2:
6423 Node->getValueType(0),
6424 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6425 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6426 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6428 case Intrinsic::aarch64_sve_fmin_single_x2:
6430 Node->getValueType(0),
6431 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6432 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6433 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6435 case Intrinsic::aarch64_sve_smin_single_x4:
6437 Node->getValueType(0),
6438 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6439 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6440 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6442 case Intrinsic::aarch64_sve_umin_single_x4:
6444 Node->getValueType(0),
6445 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6446 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6447 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6449 case Intrinsic::aarch64_sve_fmin_single_x4:
6451 Node->getValueType(0),
6452 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6453 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6454 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6456 case Intrinsic::aarch64_sve_smax_x2:
6458 Node->getValueType(0),
6459 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6460 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6461 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6463 case Intrinsic::aarch64_sve_umax_x2:
6465 Node->getValueType(0),
6466 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6467 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6468 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6470 case Intrinsic::aarch64_sve_fmax_x2:
6472 Node->getValueType(0),
6473 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6474 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6475 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6477 case Intrinsic::aarch64_sve_smax_x4:
6479 Node->getValueType(0),
6480 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6481 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6482 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6484 case Intrinsic::aarch64_sve_umax_x4:
6486 Node->getValueType(0),
6487 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6488 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6489 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6491 case Intrinsic::aarch64_sve_fmax_x4:
6493 Node->getValueType(0),
6494 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6495 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6496 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6498 case Intrinsic::aarch64_sme_famax_x2:
6500 Node->getValueType(0),
6501 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6502 AArch64::FAMAX_2Z2Z_D}))
6503 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6505 case Intrinsic::aarch64_sme_famax_x4:
6507 Node->getValueType(0),
6508 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6509 AArch64::FAMAX_4Z4Z_D}))
6510 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6512 case Intrinsic::aarch64_sme_famin_x2:
6514 Node->getValueType(0),
6515 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6516 AArch64::FAMIN_2Z2Z_D}))
6517 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6519 case Intrinsic::aarch64_sme_famin_x4:
6521 Node->getValueType(0),
6522 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6523 AArch64::FAMIN_4Z4Z_D}))
6524 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6526 case Intrinsic::aarch64_sve_smin_x2:
6528 Node->getValueType(0),
6529 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6530 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6531 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6533 case Intrinsic::aarch64_sve_umin_x2:
6535 Node->getValueType(0),
6536 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6537 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6538 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6540 case Intrinsic::aarch64_sve_fmin_x2:
6542 Node->getValueType(0),
6543 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6544 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6545 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6547 case Intrinsic::aarch64_sve_smin_x4:
6549 Node->getValueType(0),
6550 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6551 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6552 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6554 case Intrinsic::aarch64_sve_umin_x4:
6556 Node->getValueType(0),
6557 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6558 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6559 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6561 case Intrinsic::aarch64_sve_fmin_x4:
6563 Node->getValueType(0),
6564 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6565 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6566 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6568 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6570 Node->getValueType(0),
6571 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6572 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6573 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6575 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6577 Node->getValueType(0),
6578 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6579 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6580 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6582 case Intrinsic::aarch64_sve_fminnm_single_x2:
6584 Node->getValueType(0),
6585 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6586 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6587 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6589 case Intrinsic::aarch64_sve_fminnm_single_x4:
6591 Node->getValueType(0),
6592 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6593 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6594 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6596 case Intrinsic::aarch64_sve_fscale_single_x4:
6597 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6599 case Intrinsic::aarch64_sve_fscale_single_x2:
6600 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6602 case Intrinsic::aarch64_sve_fmul_single_x4:
6604 Node->getValueType(0),
6605 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6606 AArch64::FMUL_4ZZ_D}))
6607 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6609 case Intrinsic::aarch64_sve_fmul_single_x2:
6611 Node->getValueType(0),
6612 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6613 AArch64::FMUL_2ZZ_D}))
6614 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6616 case Intrinsic::aarch64_sve_fmaxnm_x2:
6618 Node->getValueType(0),
6619 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6620 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6621 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6623 case Intrinsic::aarch64_sve_fmaxnm_x4:
6625 Node->getValueType(0),
6626 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6627 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6628 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6630 case Intrinsic::aarch64_sve_fminnm_x2:
6632 Node->getValueType(0),
6633 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6634 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6635 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6637 case Intrinsic::aarch64_sve_fminnm_x4:
6639 Node->getValueType(0),
6640 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6641 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6642 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6644 case Intrinsic::aarch64_sve_aese_lane_x2:
6645 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6647 case Intrinsic::aarch64_sve_aesd_lane_x2:
6648 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6650 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6651 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6653 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6654 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6656 case Intrinsic::aarch64_sve_aese_lane_x4:
6657 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6659 case Intrinsic::aarch64_sve_aesd_lane_x4:
6660 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6662 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6663 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6665 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6666 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6668 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6669 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6671 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6675 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6677 for (
unsigned I = 0;
I < 2;
I++)
6679 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6681 CurDAG->RemoveDeadNode(Node);
6684 case Intrinsic::aarch64_sve_fscale_x4:
6685 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6687 case Intrinsic::aarch64_sve_fscale_x2:
6688 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6690 case Intrinsic::aarch64_sve_fmul_x4:
6692 Node->getValueType(0),
6693 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6694 AArch64::FMUL_4Z4Z_D}))
6695 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6697 case Intrinsic::aarch64_sve_fmul_x2:
6699 Node->getValueType(0),
6700 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6701 AArch64::FMUL_2Z2Z_D}))
6702 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6704 case Intrinsic::aarch64_sve_fcvtzs_x2:
6705 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6707 case Intrinsic::aarch64_sve_scvtf_x2:
6708 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6710 case Intrinsic::aarch64_sve_fcvtzu_x2:
6711 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6713 case Intrinsic::aarch64_sve_ucvtf_x2:
6714 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6716 case Intrinsic::aarch64_sve_fcvtzs_x4:
6717 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6719 case Intrinsic::aarch64_sve_scvtf_x4:
6720 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6722 case Intrinsic::aarch64_sve_fcvtzu_x4:
6723 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6725 case Intrinsic::aarch64_sve_ucvtf_x4:
6726 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6728 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6729 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6731 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6732 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6734 case Intrinsic::aarch64_sve_sclamp_single_x2:
6736 Node->getValueType(0),
6737 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6738 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6739 SelectClamp(Node, 2,
Op);
6741 case Intrinsic::aarch64_sve_uclamp_single_x2:
6743 Node->getValueType(0),
6744 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6745 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6746 SelectClamp(Node, 2,
Op);
6748 case Intrinsic::aarch64_sve_fclamp_single_x2:
6750 Node->getValueType(0),
6751 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6752 AArch64::FCLAMP_VG2_2Z2Z_D}))
6753 SelectClamp(Node, 2,
Op);
6755 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6756 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6758 case Intrinsic::aarch64_sve_sclamp_single_x4:
6760 Node->getValueType(0),
6761 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6762 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6763 SelectClamp(Node, 4,
Op);
6765 case Intrinsic::aarch64_sve_uclamp_single_x4:
6767 Node->getValueType(0),
6768 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6769 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6770 SelectClamp(Node, 4,
Op);
6772 case Intrinsic::aarch64_sve_fclamp_single_x4:
6774 Node->getValueType(0),
6775 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6776 AArch64::FCLAMP_VG4_4Z4Z_D}))
6777 SelectClamp(Node, 4,
Op);
6779 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6780 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6782 case Intrinsic::aarch64_sve_add_single_x2:
6784 Node->getValueType(0),
6785 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6786 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6787 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6789 case Intrinsic::aarch64_sve_add_single_x4:
6791 Node->getValueType(0),
6792 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6793 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6794 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6796 case Intrinsic::aarch64_sve_zip_x2:
6798 Node->getValueType(0),
6799 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6800 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6801 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6803 case Intrinsic::aarch64_sve_zipq_x2:
6804 SelectUnaryMultiIntrinsic(Node, 2,
false,
6805 AArch64::ZIP_VG2_2ZZZ_Q);
6807 case Intrinsic::aarch64_sve_zip_x4:
6809 Node->getValueType(0),
6810 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6811 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6812 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6814 case Intrinsic::aarch64_sve_zipq_x4:
6815 SelectUnaryMultiIntrinsic(Node, 4,
true,
6816 AArch64::ZIP_VG4_4Z4Z_Q);
6818 case Intrinsic::aarch64_sve_uzp_x2:
6820 Node->getValueType(0),
6821 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6822 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6823 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6825 case Intrinsic::aarch64_sve_uzpq_x2:
6826 SelectUnaryMultiIntrinsic(Node, 2,
false,
6827 AArch64::UZP_VG2_2ZZZ_Q);
6829 case Intrinsic::aarch64_sve_uzp_x4:
6831 Node->getValueType(0),
6832 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6833 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6834 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6836 case Intrinsic::aarch64_sve_uzpq_x4:
6837 SelectUnaryMultiIntrinsic(Node, 4,
true,
6838 AArch64::UZP_VG4_4Z4Z_Q);
6840 case Intrinsic::aarch64_sve_sel_x2:
6842 Node->getValueType(0),
6843 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6844 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6845 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6847 case Intrinsic::aarch64_sve_sel_x4:
6849 Node->getValueType(0),
6850 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6851 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6852 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6854 case Intrinsic::aarch64_sve_frinta_x2:
6855 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6857 case Intrinsic::aarch64_sve_frinta_x4:
6858 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6860 case Intrinsic::aarch64_sve_frintm_x2:
6861 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6863 case Intrinsic::aarch64_sve_frintm_x4:
6864 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6866 case Intrinsic::aarch64_sve_frintn_x2:
6867 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6869 case Intrinsic::aarch64_sve_frintn_x4:
6870 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6872 case Intrinsic::aarch64_sve_frintp_x2:
6873 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6875 case Intrinsic::aarch64_sve_frintp_x4:
6876 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6878 case Intrinsic::aarch64_sve_sunpk_x2:
6880 Node->getValueType(0),
6881 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6882 AArch64::SUNPK_VG2_2ZZ_D}))
6883 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6885 case Intrinsic::aarch64_sve_uunpk_x2:
6887 Node->getValueType(0),
6888 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6889 AArch64::UUNPK_VG2_2ZZ_D}))
6890 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6892 case Intrinsic::aarch64_sve_sunpk_x4:
6894 Node->getValueType(0),
6895 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6896 AArch64::SUNPK_VG4_4Z2Z_D}))
6897 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6899 case Intrinsic::aarch64_sve_uunpk_x4:
6901 Node->getValueType(0),
6902 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6903 AArch64::UUNPK_VG4_4Z2Z_D}))
6904 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6906 case Intrinsic::aarch64_sve_pext_x2: {
6908 Node->getValueType(0),
6909 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6910 AArch64::PEXT_2PCI_D}))
6911 SelectPExtPair(Node,
Op);
6918 unsigned IntNo =
Node->getConstantOperandVal(1);
6919 if (
Node->getNumOperands() >= 3)
6920 VT =
Node->getOperand(2)->getValueType(0);
6924 case Intrinsic::aarch64_neon_st1x2: {
6925 if (VT == MVT::v8i8) {
6926 SelectStore(Node, 2, AArch64::ST1Twov8b);
6928 }
else if (VT == MVT::v16i8) {
6929 SelectStore(Node, 2, AArch64::ST1Twov16b);
6931 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6932 VT == MVT::v4bf16) {
6933 SelectStore(Node, 2, AArch64::ST1Twov4h);
6935 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6936 VT == MVT::v8bf16) {
6937 SelectStore(Node, 2, AArch64::ST1Twov8h);
6939 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6940 SelectStore(Node, 2, AArch64::ST1Twov2s);
6942 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6943 SelectStore(Node, 2, AArch64::ST1Twov4s);
6945 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6946 SelectStore(Node, 2, AArch64::ST1Twov2d);
6948 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6949 SelectStore(Node, 2, AArch64::ST1Twov1d);
6954 case Intrinsic::aarch64_neon_st1x3: {
6955 if (VT == MVT::v8i8) {
6956 SelectStore(Node, 3, AArch64::ST1Threev8b);
6958 }
else if (VT == MVT::v16i8) {
6959 SelectStore(Node, 3, AArch64::ST1Threev16b);
6961 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6962 VT == MVT::v4bf16) {
6963 SelectStore(Node, 3, AArch64::ST1Threev4h);
6965 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6966 VT == MVT::v8bf16) {
6967 SelectStore(Node, 3, AArch64::ST1Threev8h);
6969 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6970 SelectStore(Node, 3, AArch64::ST1Threev2s);
6972 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6973 SelectStore(Node, 3, AArch64::ST1Threev4s);
6975 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6976 SelectStore(Node, 3, AArch64::ST1Threev2d);
6978 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6979 SelectStore(Node, 3, AArch64::ST1Threev1d);
6984 case Intrinsic::aarch64_neon_st1x4: {
6985 if (VT == MVT::v8i8) {
6986 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6988 }
else if (VT == MVT::v16i8) {
6989 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6991 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6992 VT == MVT::v4bf16) {
6993 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6995 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6996 VT == MVT::v8bf16) {
6997 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6999 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7000 SelectStore(Node, 4, AArch64::ST1Fourv2s);
7002 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7003 SelectStore(Node, 4, AArch64::ST1Fourv4s);
7005 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7006 SelectStore(Node, 4, AArch64::ST1Fourv2d);
7008 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7009 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7014 case Intrinsic::aarch64_neon_st2: {
7015 if (VT == MVT::v8i8) {
7016 SelectStore(Node, 2, AArch64::ST2Twov8b);
7018 }
else if (VT == MVT::v16i8) {
7019 SelectStore(Node, 2, AArch64::ST2Twov16b);
7021 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7022 VT == MVT::v4bf16) {
7023 SelectStore(Node, 2, AArch64::ST2Twov4h);
7025 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7026 VT == MVT::v8bf16) {
7027 SelectStore(Node, 2, AArch64::ST2Twov8h);
7029 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7030 SelectStore(Node, 2, AArch64::ST2Twov2s);
7032 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7033 SelectStore(Node, 2, AArch64::ST2Twov4s);
7035 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7036 SelectStore(Node, 2, AArch64::ST2Twov2d);
7038 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7039 SelectStore(Node, 2, AArch64::ST1Twov1d);
7044 case Intrinsic::aarch64_neon_st3: {
7045 if (VT == MVT::v8i8) {
7046 SelectStore(Node, 3, AArch64::ST3Threev8b);
7048 }
else if (VT == MVT::v16i8) {
7049 SelectStore(Node, 3, AArch64::ST3Threev16b);
7051 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7052 VT == MVT::v4bf16) {
7053 SelectStore(Node, 3, AArch64::ST3Threev4h);
7055 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7056 VT == MVT::v8bf16) {
7057 SelectStore(Node, 3, AArch64::ST3Threev8h);
7059 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7060 SelectStore(Node, 3, AArch64::ST3Threev2s);
7062 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7063 SelectStore(Node, 3, AArch64::ST3Threev4s);
7065 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7066 SelectStore(Node, 3, AArch64::ST3Threev2d);
7068 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7069 SelectStore(Node, 3, AArch64::ST1Threev1d);
7074 case Intrinsic::aarch64_neon_st4: {
7075 if (VT == MVT::v8i8) {
7076 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7078 }
else if (VT == MVT::v16i8) {
7079 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7081 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7082 VT == MVT::v4bf16) {
7083 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7085 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7086 VT == MVT::v8bf16) {
7087 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7089 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7090 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7092 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7093 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7095 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7096 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7098 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7099 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7104 case Intrinsic::aarch64_neon_st2lane: {
7105 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7106 SelectStoreLane(Node, 2, AArch64::ST2i8);
7108 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7109 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7110 SelectStoreLane(Node, 2, AArch64::ST2i16);
7112 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7114 SelectStoreLane(Node, 2, AArch64::ST2i32);
7116 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7118 SelectStoreLane(Node, 2, AArch64::ST2i64);
7123 case Intrinsic::aarch64_neon_st3lane: {
7124 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7125 SelectStoreLane(Node, 3, AArch64::ST3i8);
7127 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7128 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7129 SelectStoreLane(Node, 3, AArch64::ST3i16);
7131 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7133 SelectStoreLane(Node, 3, AArch64::ST3i32);
7135 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7137 SelectStoreLane(Node, 3, AArch64::ST3i64);
7142 case Intrinsic::aarch64_neon_st4lane: {
7143 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7144 SelectStoreLane(Node, 4, AArch64::ST4i8);
7146 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7147 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7148 SelectStoreLane(Node, 4, AArch64::ST4i16);
7150 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7152 SelectStoreLane(Node, 4, AArch64::ST4i32);
7154 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7156 SelectStoreLane(Node, 4, AArch64::ST4i64);
7161 case Intrinsic::aarch64_sve_st2q: {
7162 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7165 case Intrinsic::aarch64_sve_st3q: {
7166 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7169 case Intrinsic::aarch64_sve_st4q: {
7170 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7173 case Intrinsic::aarch64_sve_st2: {
7174 if (VT == MVT::nxv16i8) {
7175 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7177 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7178 VT == MVT::nxv8bf16) {
7179 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7181 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7182 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7184 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7185 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7190 case Intrinsic::aarch64_sve_st3: {
7191 if (VT == MVT::nxv16i8) {
7192 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7194 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7195 VT == MVT::nxv8bf16) {
7196 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7198 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7199 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7201 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7202 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7207 case Intrinsic::aarch64_sve_st4: {
7208 if (VT == MVT::nxv16i8) {
7209 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7211 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7212 VT == MVT::nxv8bf16) {
7213 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7215 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7216 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7218 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7219 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7227 case AArch64ISD::LD2post: {
7228 if (VT == MVT::v8i8) {
7229 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7231 }
else if (VT == MVT::v16i8) {
7232 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7234 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7235 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7237 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7238 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7240 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7241 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7243 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7244 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7246 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7247 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7249 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7250 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7255 case AArch64ISD::LD3post: {
7256 if (VT == MVT::v8i8) {
7257 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7259 }
else if (VT == MVT::v16i8) {
7260 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7262 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7263 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7265 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7266 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7268 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7269 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7271 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7272 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7274 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7275 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7277 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7278 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7283 case AArch64ISD::LD4post: {
7284 if (VT == MVT::v8i8) {
7285 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7287 }
else if (VT == MVT::v16i8) {
7288 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7290 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7291 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7293 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7294 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7296 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7297 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7299 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7300 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7302 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7303 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7305 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7306 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7311 case AArch64ISD::LD1x2post: {
7312 if (VT == MVT::v8i8) {
7313 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7315 }
else if (VT == MVT::v16i8) {
7316 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7318 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7319 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7321 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7322 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7324 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7325 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7327 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7328 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7330 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7331 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7333 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7334 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7339 case AArch64ISD::LD1x3post: {
7340 if (VT == MVT::v8i8) {
7341 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7343 }
else if (VT == MVT::v16i8) {
7344 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7346 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7347 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7349 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7350 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7352 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7353 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7355 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7356 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7358 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7359 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7361 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7362 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7367 case AArch64ISD::LD1x4post: {
7368 if (VT == MVT::v8i8) {
7369 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7371 }
else if (VT == MVT::v16i8) {
7372 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7374 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7375 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7377 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7378 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7380 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7381 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7383 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7384 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7386 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7387 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7389 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7390 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7395 case AArch64ISD::LD1DUPpost: {
7396 if (VT == MVT::v8i8) {
7397 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7399 }
else if (VT == MVT::v16i8) {
7400 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7402 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7403 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7405 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7406 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7408 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7409 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7411 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7412 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7414 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7415 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7417 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7418 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7423 case AArch64ISD::LD2DUPpost: {
7424 if (VT == MVT::v8i8) {
7425 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7427 }
else if (VT == MVT::v16i8) {
7428 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7430 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7431 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7433 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7434 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7436 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7437 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7439 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7440 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7442 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7443 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7445 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7446 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7451 case AArch64ISD::LD3DUPpost: {
7452 if (VT == MVT::v8i8) {
7453 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7455 }
else if (VT == MVT::v16i8) {
7456 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7458 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7459 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7461 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7462 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7464 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7465 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7467 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7468 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7470 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7471 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7473 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7474 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7479 case AArch64ISD::LD4DUPpost: {
7480 if (VT == MVT::v8i8) {
7481 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7483 }
else if (VT == MVT::v16i8) {
7484 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7486 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7487 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7489 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7490 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7492 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7493 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7495 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7496 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7498 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7499 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7501 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7502 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7507 case AArch64ISD::LD1LANEpost: {
7508 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7509 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7511 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7512 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7513 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7515 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7517 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7519 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7521 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7526 case AArch64ISD::LD2LANEpost: {
7527 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7528 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7530 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7531 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7532 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7534 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7536 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7538 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7540 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7545 case AArch64ISD::LD3LANEpost: {
7546 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7547 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7549 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7550 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7551 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7553 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7555 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7557 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7559 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7564 case AArch64ISD::LD4LANEpost: {
7565 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7566 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7568 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7569 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7570 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7572 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7574 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7576 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7578 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7583 case AArch64ISD::ST2post: {
7584 VT =
Node->getOperand(1).getValueType();
7585 if (VT == MVT::v8i8) {
7586 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7588 }
else if (VT == MVT::v16i8) {
7589 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7591 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7592 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7594 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7595 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7597 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7598 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7600 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7601 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7603 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7604 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7606 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7607 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7612 case AArch64ISD::ST3post: {
7613 VT =
Node->getOperand(1).getValueType();
7614 if (VT == MVT::v8i8) {
7615 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7617 }
else if (VT == MVT::v16i8) {
7618 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7620 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7621 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7623 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7624 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7626 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7627 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7629 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7630 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7632 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7633 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7635 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7636 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7641 case AArch64ISD::ST4post: {
7642 VT =
Node->getOperand(1).getValueType();
7643 if (VT == MVT::v8i8) {
7644 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7646 }
else if (VT == MVT::v16i8) {
7647 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7649 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7650 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7652 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7653 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7655 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7656 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7658 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7659 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7661 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7662 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7664 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7665 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7670 case AArch64ISD::ST1x2post: {
7671 VT =
Node->getOperand(1).getValueType();
7672 if (VT == MVT::v8i8) {
7673 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7675 }
else if (VT == MVT::v16i8) {
7676 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7678 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7679 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7681 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7682 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7684 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7685 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7687 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7688 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7690 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7691 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7693 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7694 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7699 case AArch64ISD::ST1x3post: {
7700 VT =
Node->getOperand(1).getValueType();
7701 if (VT == MVT::v8i8) {
7702 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7704 }
else if (VT == MVT::v16i8) {
7705 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7707 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7708 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7710 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7711 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7713 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7714 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7716 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7717 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7719 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7720 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7722 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7723 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7728 case AArch64ISD::ST1x4post: {
7729 VT =
Node->getOperand(1).getValueType();
7730 if (VT == MVT::v8i8) {
7731 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7733 }
else if (VT == MVT::v16i8) {
7734 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7736 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7737 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7739 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7740 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7742 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7743 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7745 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7746 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7748 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7749 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7751 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7752 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7757 case AArch64ISD::ST2LANEpost: {
7758 VT =
Node->getOperand(1).getValueType();
7759 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7760 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7762 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7763 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7764 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7766 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7768 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7770 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7772 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7777 case AArch64ISD::ST3LANEpost: {
7778 VT =
Node->getOperand(1).getValueType();
7779 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7780 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7782 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7783 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7784 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7786 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7788 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7790 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7792 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7797 case AArch64ISD::ST4LANEpost: {
7798 VT =
Node->getOperand(1).getValueType();
7799 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7800 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7802 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7803 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7804 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7806 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7808 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7810 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7812 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7827 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7839 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7843 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7844 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7866 return MemIntr->getMemoryVT();
7873 DataVT =
Load->getValueType(0);
7875 DataVT =
Load->getValueType(0);
7877 DataVT =
Store->getValue().getValueType();
7879 DataVT =
Store->getValue().getValueType();
7886 const unsigned Opcode = Root->
getOpcode();
7890 case AArch64ISD::LD1_MERGE_ZERO:
7891 case AArch64ISD::LD1S_MERGE_ZERO:
7892 case AArch64ISD::LDNF1_MERGE_ZERO:
7893 case AArch64ISD::LDNF1S_MERGE_ZERO:
7895 case AArch64ISD::ST1_PRED:
7907 case Intrinsic::aarch64_sme_ldr:
7908 case Intrinsic::aarch64_sme_str:
7909 return MVT::nxv16i8;
7910 case Intrinsic::aarch64_sve_prf:
7915 case Intrinsic::aarch64_sve_ld2_sret:
7916 case Intrinsic::aarch64_sve_ld2q_sret:
7919 case Intrinsic::aarch64_sve_st2q:
7922 case Intrinsic::aarch64_sve_ld3_sret:
7923 case Intrinsic::aarch64_sve_ld3q_sret:
7926 case Intrinsic::aarch64_sve_st3q:
7929 case Intrinsic::aarch64_sve_ld4_sret:
7930 case Intrinsic::aarch64_sve_ld4q_sret:
7933 case Intrinsic::aarch64_sve_st4q:
7936 case Intrinsic::aarch64_sve_ld1_pn_x2:
7937 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7940 case Intrinsic::aarch64_sve_ld1_pn_x4:
7941 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7944 case Intrinsic::aarch64_sve_st1_pn_x2:
7945 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7948 case Intrinsic::aarch64_sve_st1_pn_x4:
7949 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7952 case Intrinsic::aarch64_sve_ld1udq:
7953 case Intrinsic::aarch64_sve_st1dq:
7954 return EVT(MVT::nxv1i64);
7955 case Intrinsic::aarch64_sve_ld1uwq:
7956 case Intrinsic::aarch64_sve_st1wq:
7957 return EVT(MVT::nxv1i32);
7964template <
int64_t Min,
int64_t Max>
7965bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7969 const DataLayout &
DL = CurDAG->getDataLayout();
7970 const MachineFrameInfo &MFI = MF->getFrameInfo();
7978 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7992 int64_t MulImm = std::numeric_limits<int64_t>::max();
7996 int64_t ByteOffset =
C->getSExtValue();
7997 const auto KnownVScale =
8000 if (!KnownVScale || ByteOffset % KnownVScale != 0)
8003 MulImm = ByteOffset / KnownVScale;
8010 if ((MulImm % MemWidthBytes) != 0)
8013 int64_t
Offset = MulImm / MemWidthBytes;
8017 Base =
N.getOperand(0);
8026 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8032bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
8051 int64_t ImmOff =
C->getSExtValue();
8052 unsigned Size = 1 << Scale;
8061 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8063 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8074 if (
C->getZExtValue() == Scale) {
8083bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
8084 const AArch64TargetLowering *TLI =
8085 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8090bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
8091 return N.getValueType().isScalableVectorOf(MVT::i1);
8094bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
8099 int64_t ImmOff =
C->getSExtValue();
8100 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8101 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8106 if (
SDValue C = MatchConstantOffset(
N)) {
8113 if (CurDAG->isBaseWithConstantOffset(
N)) {
8114 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
8115 Base =
N.getOperand(0);
8123 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8127bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
8165 if (CN->getAPIntValue().uge(LowerBound) &&
8166 CN->getAPIntValue().ult(UpperBound)) {
8168 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8176template <
bool MatchCBB>
8183 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8185 Reg =
N.getOperand(0);
8187 SDLoc(
N), MVT::i32);
8195 Reg =
N.getOperand(0);
8215bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *
N) {
8216 EVT VT =
N->getValueType(0);
8227 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8236 unsigned CondCode = CC->getZExtValue();
8239 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8241 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8242 else if (VT == MVT::f32)
8243 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8244 else if (VT == MVT::f64)
8245 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8253 if (TVal == CmpLHS && FVal == CmpRHS)
8258 if (TVal == CmpLHS && FVal == CmpRHS)
8267 unsigned Opc = getOpc(VT, isMax);
8273 if (!CFP || CFP->getValueAPF().isNaN())
8278 if (CFP->isZero() && !
N->getFlags().hasNoSignedZeros())
8284 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8287 CurDAG->SelectNodeTo(
N,
Opc, VT, CmpLHS, CmpRHS);
8291void AArch64DAGToDAGISel::PreprocessISelDAG() {
8292 bool MadeChange =
false;
8298 switch (
N.getOpcode()) {
8300 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8301 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8302 ScalarTy ==
N.getOperand(0).getValueType())
8307 case AArch64ISD::VSHL: {
8310 EVT VT =
N.getValueType(0);
8317 if (
B.getOpcode() ==
A.getOpcode())
8330 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8336 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(&
N, 0), Result);
8342 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.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value 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.