24#include "llvm/IR/IntrinsicsAArch64.h"
33#define DEBUG_TYPE "aarch64-isel"
34#define PASS_NAME "AArch64 Instruction Selection"
37#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
38#pragma inline_depth(0)
54 AArch64DAGToDAGISel() =
delete;
66 void PreprocessISelDAG()
override;
70 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
72 std::vector<SDValue> &OutOps)
override;
74 template <
signed Low,
signed High,
signed Scale>
77 template <
signed Low,
signed High>
85 return SelectShiftedRegister(
N,
false,
Reg, Shift);
88 return SelectShiftedRegister(
N,
true,
Reg, Shift);
91 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
94 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
97 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
100 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
103 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
106 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
109 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
112 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
115 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
118 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
121 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
124 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
127 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
130 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
133 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
136 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
139 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
141 template <
unsigned Size,
unsigned Max>
145 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
148 int64_t
C = CI->getSExtValue();
156 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
163 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
169 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
174 N =
N->getOperand(0);
178 EVT VT =
N->getValueType(0);
179 EVT LVT =
N->getOperand(0).getValueType();
180 unsigned Index =
N->getConstantOperandVal(1);
184 Res =
N->getOperand(0);
189 if (
N.getOpcode() != AArch64ISD::VLSHR)
192 EVT VT =
Op.getValueType();
193 unsigned ShtAmt =
N->getConstantOperandVal(1);
198 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
200 Op.getOperand(1).getConstantOperandVal(0)
201 <<
Op.getOperand(1).getConstantOperandVal(1));
202 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
205 Op.getOperand(1).getConstantOperandVal(0));
209 if (Imm != 1ULL << (ShtAmt - 1))
212 Res1 =
Op.getOperand(0);
213 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
217 bool SelectDupZeroOrUndef(
SDValue N) {
218 switch(
N->getOpcode()) {
222 case AArch64ISD::DUP:
224 auto Opnd0 =
N->getOperand(0);
238 bool SelectAny(
SDValue) {
return true; }
241 switch(
N->getOpcode()) {
242 case AArch64ISD::DUP:
244 auto Opnd0 =
N->getOperand(0);
256 template <MVT::SimpleValueType VT,
bool Negate>
258 return SelectSVEAddSubImm(
N, VT, Imm, Shift, Negate);
261 template <MVT::SimpleValueType VT,
bool Negate>
263 return SelectSVEAddSubSSatImm(
N, VT, Imm, Shift, Negate);
266 template <MVT::SimpleValueType VT>
268 return SelectSVECpyDupImm(
N, VT, Imm, Shift);
271 template <MVT::SimpleValueType VT,
bool Invert = false>
273 return SelectSVELogicalImm(
N, VT, Imm, Invert);
276 template <MVT::SimpleValueType VT>
278 return SelectSVEArithImm(
N, VT, Imm);
281 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
283 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation, Imm);
290 EVT EltVT =
N->getValueType(0).getVectorElementType();
291 return SelectSVEShiftImm(
N->getOperand(0), 1,
297 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
304 MulImm = 1LL << MulImm;
306 if ((MulImm % std::abs(Scale)) != 0)
310 if ((MulImm >= Min) && (MulImm <= Max)) {
311 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
318 template <
signed Max,
signed Scale>
325 if (MulImm >= 0 && MulImm <= Max) {
327 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
334 template <
unsigned BaseReg,
unsigned Max>
342 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
365 const unsigned SubRegs[]);
367 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
369 bool tryIndexedLoad(
SDNode *
N);
371 void SelectPtrauthAuth(
SDNode *
N);
372 void SelectPtrauthResign(
SDNode *
N);
373 void SelectPtrauthResignWithPC(
SDNode *
N);
375 bool trySelectStackSlotTagP(
SDNode *
N);
378 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
380 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
382 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
383 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
384 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
385 unsigned Opc_rr,
unsigned Opc_ri,
386 bool IsIntr =
false);
387 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
388 unsigned Scale,
unsigned Opc_ri,
390 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
391 bool IsZmMulti,
unsigned Opcode,
392 bool HasPred =
false);
394 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
395 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
396 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
397 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
398 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
399 bool IsTupleInput,
unsigned Opc);
400 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
402 template <
unsigned MaxIdx,
unsigned Scale>
403 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
405 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
406 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
407 unsigned BaseReg = 0);
409 template <
int64_t Min,
int64_t Max>
413 template <
unsigned Scale>
415 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
418 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
420 void SelectMultiVectorLuti6LaneX4(
SDNode *
Node,
unsigned NumIndexVecs);
422 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc,
425 template <
unsigned MaxIdx,
unsigned Scale>
430 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
431 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
432 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
433 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
434 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
435 unsigned Opc_rr,
unsigned Opc_ri);
436 std::tuple<unsigned, SDValue, SDValue>
437 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
441 bool tryBitfieldExtractOp(
SDNode *
N);
442 bool tryBitfieldExtractOpFromSExt(
SDNode *
N);
443 bool tryBitfieldInsertOp(
SDNode *
N);
444 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
445 bool tryShiftAmountMod(
SDNode *
N);
447 bool tryReadRegister(
SDNode *
N);
448 bool tryWriteRegister(
SDNode *
N);
450 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
451 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
458#include "AArch64GenDAGISel.inc"
466 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
468 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
481 bool isWorthNegatingImm(
SDValue V)
const;
482 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
483 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
484 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
487 template<
unsigned RegW
idth>
489 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
491 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
493 template <
unsigned RegW
idth>
495 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
497 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
499 template<
unsigned RegW
idth>
501 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
507 template <
unsigned FloatW
idth>
509 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
515 bool SelectCMP_SWAP(
SDNode *
N);
536 bool AllowSaturation,
SDValue &Imm);
544 bool SelectAllActivePredicate(
SDValue N);
549 template <
bool MatchCBB>
559 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
563char AArch64DAGToDAGISelLegacy::ID = 0;
569 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
575 auto getFloatVT = [&](
EVT VT) {
577 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
578 return VT.changeElementType(*(DAG.
getContext()),
579 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
584 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
585 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
589 EVT OrigVT =
N.getValueType(0);
598 Imm =
C->getZExtValue();
615 return N->getOpcode() ==
Opc &&
626 return Imm == ImmExpected;
631 assert(RegWidth == 32 || RegWidth == 64);
633 return APInt(RegWidth,
640 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
641 if (
N->getOpcode() == AArch64ISD::NVCAST)
642 N =
N->getOperand(0);
643 unsigned SplatWidth =
N.getScalarValueSizeInBits();
644 if (
N.getOpcode() == AArch64ISD::FMOV)
646 if (
N->getOpcode() == AArch64ISD::MOVI)
647 return APInt(SplatWidth,
N.getConstantOperandVal(0));
648 if (
N->getOpcode() == AArch64ISD::MOVIshift)
649 return APInt(SplatWidth,
N.getConstantOperandVal(0)
650 <<
N.getConstantOperandVal(1));
651 if (
N->getOpcode() == AArch64ISD::MVNIshift)
652 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
653 <<
N.getConstantOperandVal(1));
654 if (
N->getOpcode() == AArch64ISD::MOVIedit)
656 N.getConstantOperandVal(0)));
657 if (
N->getOpcode() == AArch64ISD::DUP)
659 return Const->getAPIntValue().trunc(SplatWidth);
662 return SplatVal.
trunc(SplatWidth);
671 unsigned SplatWidth =
N.getScalarValueSizeInBits();
673 if (SplatVal->getBitWidth() <= SplatWidth)
675 if (SplatVal->isSplat(SplatWidth))
676 return SplatVal->trunc(SplatWidth);
681bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
688 ImmVal->getZExtValue(), Encoding))
691 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
695bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(
SDValue N,
SDValue &Imm,
698 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
699 N.getValueType().getScalarType().getSimpleVT(),
705bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(
SDValue N,
708 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal, Imm);
712bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(
SDValue N,
SDValue &Imm) {
717 int64_t ImmVal = ImmAPIntVal->getSExtValue();
718 if (ImmVal < -128 || ImmVal > 127)
721 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
725bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(
SDValue N,
SDValue &Imm) {
730 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
734 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
738bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
740 std::vector<SDValue> &OutOps) {
741 switch(ConstraintID) {
744 case InlineAsm::ConstraintCode::m:
745 case InlineAsm::ConstraintCode::o:
746 case InlineAsm::ConstraintCode::Q:
752 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
754 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
755 dl,
Op.getValueType(),
757 OutOps.push_back(NewOp);
776 uint64_t Immed =
N.getNode()->getAsZExtVal();
786 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
787 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
804 uint64_t Immed =
N.getNode()->getAsZExtVal();
812 if (
N.getValueType() == MVT::i32)
813 Immed = ~((uint32_t)Immed) + 1;
815 Immed = ~Immed + 1ULL;
816 if (Immed & 0xFFFFFFFFFF000000ULL)
819 Immed &= 0xFFFFFFULL;
820 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
827 switch (
N.getOpcode()) {
853 unsigned ShiftVal = CSD->getZExtValue();
871bool AArch64DAGToDAGISel::isWorthFoldingAddr(
SDValue V,
unsigned Size)
const {
874 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
879 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
903 EVT VT =
N.getValueType();
904 if (VT != MVT::i32 && VT != MVT::i64)
907 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
913 unsigned LHSOpcode =
LHS->getOpcode();
927 unsigned LowZBits, MaskLen;
931 unsigned BitWidth =
N.getValueSizeInBits();
938 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
941 NewShiftC = LowZBits - ShiftAmtC;
942 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
948 NewShiftC = LowZBits + ShiftAmtC;
961 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
963 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
967 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
969 Reg =
SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
970 NewShiftAmt, BitWidthMinus1),
973 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
987 SrcVT =
N.getOperand(0).getValueType();
989 if (!IsLoadStore && SrcVT == MVT::i8)
991 else if (!IsLoadStore && SrcVT == MVT::i16)
993 else if (SrcVT == MVT::i32)
995 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1000 EVT SrcVT =
N.getOperand(0).getValueType();
1001 if (!IsLoadStore && SrcVT == MVT::i8)
1003 else if (!IsLoadStore && SrcVT == MVT::i16)
1005 else if (SrcVT == MVT::i32)
1007 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1032bool AArch64DAGToDAGISel::isWorthNegatingImm(
SDValue V)
const {
1035 EVT VT =
V.getValueType();
1036 assert((VT == MVT::i32 || VT == MVT::i64) &&
"invalid type");
1047 return NewCost.
size() < OrigCost.
size();
1054bool AArch64DAGToDAGISel::isWorthFoldingALU(
SDValue V,
bool LSL)
const {
1057 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1062 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1063 V.getConstantOperandVal(1) <= 4 &&
1076bool AArch64DAGToDAGISel::SelectShiftedRegister(
SDValue N,
bool AllowROR,
1078 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1088 unsigned BitSize =
N.getValueSizeInBits();
1089 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1092 Reg =
N.getOperand(0);
1093 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1094 return isWorthFoldingALU(
N,
true);
1105 if (
N.getValueType() == MVT::i32)
1113template<
signed Low,
signed High,
signed Scale>
1119 if ((MulImm % std::abs(Scale)) == 0) {
1120 int64_t RDVLImm = MulImm / Scale;
1121 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1122 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1131template <
signed Low,
signed High>
1132bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(
SDValue N,
SDValue &Imm) {
1137 if (MulImm >=
Low && MulImm <=
High) {
1138 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1149 unsigned ShiftVal = 0;
1164 Reg =
N.getOperand(0).getOperand(0);
1176 Op =
Op->getOperand(0);
1178 Op.getOperand(0).getValueType().isFixedLengthVector())
1182 Reg =
N.getOperand(0);
1187 unsigned Opc =
N.getOpcode();
1205 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1207 return isWorthFoldingALU(
N);
1214 unsigned ShiftVal = 0;
1228 Reg =
N.getOperand(0);
1229 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1231 return isWorthFoldingALU(
N);
1240 for (
auto *
User :
N->users()) {
1267bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
1268 unsigned BW,
unsigned Size,
1272 const DataLayout &
DL = CurDAG->getDataLayout();
1273 const TargetLowering *TLI = getTargetLowering();
1277 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1283 if (CurDAG->isBaseWithConstantOffset(
N)) {
1286 int64_t RHSC =
RHS->getSExtValue();
1288 int64_t
Range = 0x1LL << (BW - 1);
1290 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1291 RHSC < (
Range << Scale)) {
1292 Base =
N.getOperand(0);
1297 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1302 uint64_t RHSC =
RHS->getZExtValue();
1304 uint64_t
Range = 0x1ULL << BW;
1306 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1307 Base =
N.getOperand(0);
1312 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1323 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1330bool AArch64DAGToDAGISel::SelectAddrModeIndexed(
SDValue N,
unsigned Size,
1333 const DataLayout &
DL = CurDAG->getDataLayout();
1334 const TargetLowering *TLI = getTargetLowering();
1338 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1343 GlobalAddressSDNode *GAN =
1345 Base =
N.getOperand(0);
1355 if (CurDAG->isBaseWithConstantOffset(
N)) {
1357 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1360 Base =
N.getOperand(0);
1365 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1373 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1381 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1390bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(
SDValue N,
unsigned Size,
1393 if (!CurDAG->isBaseWithConstantOffset(
N))
1396 int64_t RHSC =
RHS->getSExtValue();
1397 if (RHSC >= -256 && RHSC < 256) {
1398 Base =
N.getOperand(0);
1401 const TargetLowering *TLI = getTargetLowering();
1402 Base = CurDAG->getTargetFrameIndex(
1405 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1415 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1422bool AArch64DAGToDAGISel::SelectExtendedSHL(
SDValue N,
unsigned Size,
1442 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1448 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1451 return isWorthFoldingAddr(
N,
Size);
1454bool AArch64DAGToDAGISel::SelectAddrModeWRO(
SDValue N,
unsigned Size,
1472 const SDNode *
Node =
N.getNode();
1473 for (SDNode *UI :
Node->users()) {
1479 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1482 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1485 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1490 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1493 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1498 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1502 if (IsExtendedRegisterWorthFolding &&
1509 if (isWorthFoldingAddr(
LHS,
Size))
1514 if (IsExtendedRegisterWorthFolding &&
1521 if (isWorthFoldingAddr(
RHS,
Size))
1533 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1536 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1538 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1539 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1543bool AArch64DAGToDAGISel::SelectAddrModeXRO(
SDValue N,
unsigned Size,
1556 const SDNode *
Node =
N.getNode();
1557 for (SDNode *UI :
Node->users()) {
1574 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1584 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1591 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1594 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1597 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1602 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1605 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1612 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1613 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1619 static const unsigned RegClassIDs[] = {
1620 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1621 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1622 AArch64::dsub2, AArch64::dsub3};
1628 static const unsigned RegClassIDs[] = {
1629 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1630 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1631 AArch64::qsub2, AArch64::qsub3};
1637 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1638 AArch64::ZPR3RegClassID,
1639 AArch64::ZPR4RegClassID};
1640 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1641 AArch64::zsub2, AArch64::zsub3};
1651 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1652 AArch64::ZPR4Mul4RegClassID};
1653 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1654 AArch64::zsub2, AArch64::zsub3};
1659 const unsigned RegClassIDs[],
1660 const unsigned SubRegs[]) {
1663 if (Regs.
size() == 1)
1674 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1677 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1678 Ops.push_back(Regs[i]);
1679 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1683 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1687void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1690 EVT VT =
N->getValueType(0);
1692 unsigned ExtOff = isExt;
1695 unsigned Vec0Off = ExtOff + 1;
1701 Ops.push_back(
N->getOperand(1));
1702 Ops.push_back(RegSeq);
1703 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1704 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1707static std::tuple<SDValue, SDValue>
1728 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1733 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1735 return std::make_tuple(
1740void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1745 SDValue AUTDisc =
N->getOperand(3);
1748 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1750 SDValue AUTAddrDisc, AUTConstDisc;
1751 std::tie(AUTConstDisc, AUTAddrDisc) =
1755 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1757 if (
N->getNumOperands() > 4)
1758 Ops.push_back(
N->getOperand(4));
1761 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1762 ReplaceNode(
N, AUT);
1764 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1765 AArch64::X16, Val,
SDValue());
1768 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1769 ReplaceNode(
N, AUT);
1773void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1783 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1788 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1789 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1791 SDValue AUTAddrDisc, AUTConstDisc;
1792 std::tie(AUTConstDisc, AUTAddrDisc) =
1795 SDValue PACAddrDisc, PACConstDisc;
1796 std::tie(PACConstDisc, PACAddrDisc) =
1799 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1800 AArch64::X16, Val,
SDValue());
1803 SDValue Addend =
N->getOperand(OffsetBase + 6);
1804 SDValue IncomingChain =
N->getOperand(0);
1805 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1806 PACKey, PACConstDisc, PACAddrDisc,
1807 Addend, IncomingChain, X16Copy.
getValue(1)};
1809 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1810 MVT::i64, MVT::Other,
Ops);
1811 ReplaceNode(
N, AUTRELLOADPAC);
1813 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1814 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1816 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1817 ReplaceNode(
N, AUTPAC);
1821void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *
N) {
1833 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1834 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1836 SDValue PACAddrDisc, PACConstDisc;
1837 std::tie(PACConstDisc, PACAddrDisc) =
1840 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1841 AArch64::X17, Val,
SDValue());
1842 SDValue X16Copy = CurDAG->getCopyToReg(
1843 CurDAG->getEntryNode(),
DL, AArch64::X16, AUTDisc, X17Copy.
getValue(1));
1844 SDValue X15Copy = CurDAG->getCopyToReg(
1845 CurDAG->getEntryNode(),
DL, AArch64::X15, AUTPC, X16Copy.
getValue(1));
1847 SDValue Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1850 CurDAG->getMachineNode(AArch64::AUTPCPAC,
DL, MVT::i64,
Ops);
1851 ReplaceNode(
N, AUTPCPAC);
1854bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1856 if (
LD->isUnindexed())
1858 EVT VT =
LD->getMemoryVT();
1859 EVT DstVT =
N->getValueType(0);
1863 int OffsetVal = (int)
OffsetOp->getZExtValue();
1868 unsigned Opcode = 0;
1871 bool InsertTo64 =
false;
1873 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1874 else if (VT == MVT::i32) {
1876 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1878 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1880 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1886 }
else if (VT == MVT::i16) {
1888 if (DstVT == MVT::i64)
1889 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1891 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1893 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1894 InsertTo64 = DstVT == MVT::i64;
1899 }
else if (VT == MVT::i8) {
1901 if (DstVT == MVT::i64)
1902 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1904 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1906 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1907 InsertTo64 = DstVT == MVT::i64;
1912 }
else if (VT == MVT::f16) {
1913 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1914 }
else if (VT == MVT::bf16) {
1915 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1916 }
else if (VT == MVT::f32) {
1917 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1918 }
else if (VT == MVT::f64 ||
1920 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1922 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1924 if (IsPre || OffsetVal != 8)
1928 Opcode = AArch64::LD1Onev8b_POST;
1931 Opcode = AArch64::LD1Onev4h_POST;
1934 Opcode = AArch64::LD1Onev2s_POST;
1937 Opcode = AArch64::LD1Onev1d_POST;
1943 if (IsPre || OffsetVal != 16)
1947 Opcode = AArch64::LD1Onev16b_POST;
1950 Opcode = AArch64::LD1Onev8h_POST;
1953 Opcode = AArch64::LD1Onev4s_POST;
1956 Opcode = AArch64::LD1Onev2d_POST;
1968 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
1969 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
1971 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
1981 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
1982 LoadedVal =
SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
1983 MVT::i64, LoadedVal, SubReg),
1987 ReplaceUses(
SDValue(
N, 0), LoadedVal);
1990 CurDAG->RemoveDeadNode(
N);
1994void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1995 unsigned SubRegIdx) {
1997 EVT VT =
N->getValueType(0);
2003 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2005 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2007 for (
unsigned i = 0; i < NumVecs; ++i)
2009 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2016 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2020 CurDAG->RemoveDeadNode(
N);
2023void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2024 unsigned Opc,
unsigned SubRegIdx) {
2026 EVT VT =
N->getValueType(0);
2033 const EVT ResTys[] = {MVT::i64,
2034 MVT::Untyped, MVT::Other};
2036 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2044 ReplaceUses(
SDValue(
N, 0), SuperReg);
2046 for (
unsigned i = 0; i < NumVecs; ++i)
2048 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2056 CurDAG->RemoveDeadNode(
N);
2062std::tuple<unsigned, SDValue, SDValue>
2063AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2069 SDValue NewOffset = OldOffset;
2071 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2072 N, OldBase, NewBase, NewOffset);
2076 const bool IsRegReg =
2077 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2080 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2093template <SelectTypeKind Kind>
2105 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2110 if (EltVT != MVT::i1)
2114 if (EltVT == MVT::bf16)
2116 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2146void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2149 if (
Imm->getZExtValue() > 1)
2153 EVT VT =
N->getValueType(0);
2155 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2158 for (
unsigned I = 0;
I < 2; ++
I)
2159 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2160 AArch64::psub0 +
I,
DL, VT, SuperReg));
2162 CurDAG->RemoveDeadNode(
N);
2165void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2167 EVT VT =
N->getValueType(0);
2171 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2174 for (
unsigned I = 0;
I < 2; ++
I)
2175 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2176 AArch64::psub0 +
I,
DL, VT, SuperReg));
2178 CurDAG->RemoveDeadNode(
N);
2181void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2183 EVT VT =
N->getValueType(0);
2187 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2189 for (
unsigned i = 0; i < NumVecs; ++i)
2190 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2191 AArch64::zsub0 + i,
DL, VT, SuperReg));
2193 CurDAG->RemoveDeadNode(
N);
2196void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2199 EVT VT =
N->getValueType(0);
2201 Ops.push_back(
N->getOperand(0));
2204 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2207 for (
unsigned i = 0; i < NumVecs; ++i)
2208 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2209 AArch64::zsub0 + i,
DL, VT, SuperReg));
2212 unsigned ChainIdx = NumVecs;
2214 CurDAG->RemoveDeadNode(
N);
2217void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2222 assert(Opcode != 0 &&
"Unexpected opcode");
2225 EVT VT =
N->getValueType(0);
2226 SDUse *OpsIter =
N->op_begin() + 1;
2229 auto GetMultiVecOperand = [&]() {
2232 return createZMulTuple(Regs);
2236 Ops.push_back(*OpsIter++);
2238 Ops.push_back(GetMultiVecOperand());
2240 Ops.push_back(GetMultiVecOperand());
2242 Ops.push_back(*OpsIter++);
2245 Ops.append(OpsIter,
N->op_end());
2247 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2249 for (
unsigned i = 0; i < NumVecs; ++i)
2250 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2251 AArch64::zsub0 + i,
DL, VT, SuperReg));
2253 CurDAG->RemoveDeadNode(
N);
2256void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2257 unsigned Scale,
unsigned Opc_ri,
2258 unsigned Opc_rr,
bool IsIntr) {
2259 assert(Scale < 5 &&
"Invalid scaling value.");
2261 EVT VT =
N->getValueType(0);
2268 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2269 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2275 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2277 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2279 for (
unsigned i = 0; i < NumVecs; ++i)
2280 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2281 AArch64::zsub0 + i,
DL, VT, SuperReg));
2284 unsigned ChainIdx = NumVecs;
2286 CurDAG->RemoveDeadNode(
N);
2289void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2294 assert(Scale < 4 &&
"Invalid scaling value.");
2296 EVT VT =
N->getValueType(0);
2304 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2310 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2312 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2314 for (
unsigned i = 0; i < NumVecs; ++i)
2315 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2316 AArch64::zsub0 + i,
DL, VT, SuperReg));
2319 unsigned ChainIdx = NumVecs;
2321 CurDAG->RemoveDeadNode(
N);
2324void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2326 if (
N->getValueType(0) != MVT::nxv4f32)
2328 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2331void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2332 unsigned NumOutVecs,
2336 if (
Imm->getZExtValue() > MaxImm)
2340 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2346 EVT VT =
Node->getValueType(0);
2349 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2352 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2353 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2354 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2357 unsigned ChainIdx = NumOutVecs;
2359 CurDAG->RemoveDeadNode(Node);
2362void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2363 unsigned NumIndexVecs) {
2364 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2365 "unexpected number of index vectors");
2367 constexpr unsigned FirstIndexOp = 3;
2368 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2370 if (!Imm ||
Imm->getZExtValue() > 1)
2376 unsigned Lane =
Imm->getZExtValue();
2377 unsigned IndexOp = FirstIndexOp;
2378 if (NumIndexVecs == 3)
2381 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2383 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2384 SDValue Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2387 EVT VT =
Node->getValueType(0);
2389 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2392 for (
unsigned I = 0;
I < 4; ++
I)
2393 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2394 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2396 CurDAG->RemoveDeadNode(Node);
2399void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2400 unsigned NumOutVecs,
2402 unsigned NumInVecs) {
2403 assert((NumInVecs == 2 || NumInVecs == 3) &&
2404 "unexpected number of input vectors");
2407 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2411 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2415 EVT VT =
Node->getValueType(0);
2418 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2421 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2422 ReplaceUses(
SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2423 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2426 CurDAG->RemoveDeadNode(Node);
2429void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2432 EVT VT =
N->getValueType(0);
2435 SDValue Zd = createZMulTuple(Regs);
2436 SDValue Zn =
N->getOperand(1 + NumVecs);
2437 SDValue Zm =
N->getOperand(2 + NumVecs);
2443 for (
unsigned i = 0; i < NumVecs; ++i)
2444 ReplaceUses(
SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2445 AArch64::zsub0 + i,
DL, VT, SuperReg));
2447 CurDAG->RemoveDeadNode(
N);
2477template <
unsigned MaxIdx,
unsigned Scale>
2478void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2479 unsigned BaseReg,
unsigned Op) {
2480 unsigned TileNum = 0;
2481 if (BaseReg != AArch64::ZA)
2482 TileNum =
N->getConstantOperandVal(2);
2488 if (BaseReg == AArch64::ZA)
2493 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2497 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2499 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2501 EVT VT =
N->getValueType(0);
2502 for (
unsigned I = 0;
I < NumVecs; ++
I)
2504 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2507 unsigned ChainIdx = NumVecs;
2509 CurDAG->RemoveDeadNode(
N);
2512void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2513 unsigned Op,
unsigned MaxIdx,
2514 unsigned Scale,
unsigned BaseReg) {
2519 if (BaseReg != AArch64::ZA)
2523 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2530 if (BaseReg != AArch64::ZA )
2531 Ops.push_back(
N->getOperand(2));
2534 Ops.push_back(
N->getOperand(0));
2535 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2537 EVT VT =
N->getValueType(0);
2538 for (
unsigned I = 0;
I < NumVecs; ++
I)
2540 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2544 unsigned ChainIdx = NumVecs;
2546 CurDAG->RemoveDeadNode(
N);
2549void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2550 unsigned NumOutVecs,
2554 EVT VT =
N->getValueType(0);
2555 unsigned NumInVecs =
N->getNumOperands() - 1;
2559 assert((NumInVecs == 2 || NumInVecs == 4) &&
2560 "Don't know how to handle multi-register input!");
2562 Ops.push_back(createZMulTuple(Regs));
2565 for (
unsigned I = 0;
I < NumInVecs;
I++)
2566 Ops.push_back(
N->getOperand(1 +
I));
2569 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2572 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2573 ReplaceUses(
SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2574 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2575 CurDAG->RemoveDeadNode(
N);
2578void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2581 EVT VT =
N->getOperand(2)->getValueType(0);
2589 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2598void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2599 unsigned Scale,
unsigned Opc_rr,
2605 SDValue RegSeq = createZTuple(Regs);
2611 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2612 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2618 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2627void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2630 EVT VT =
N->getOperand(2)->getValueType(0);
2631 const EVT ResTys[] = {MVT::i64,
2643 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2687void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2690 EVT VT =
N->getValueType(0);
2702 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2704 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2706 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2708 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2712 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2713 AArch64::qsub2, AArch64::qsub3 };
2714 for (
unsigned i = 0; i < NumVecs; ++i) {
2715 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2722 CurDAG->RemoveDeadNode(
N);
2725void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2728 EVT VT =
N->getValueType(0);
2740 const EVT ResTys[] = {MVT::i64,
2743 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2746 CurDAG->getTargetConstant(LaneNo, dl,
2751 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2763 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2764 AArch64::qsub2, AArch64::qsub3 };
2765 for (
unsigned i = 0; i < NumVecs; ++i) {
2766 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2776 CurDAG->RemoveDeadNode(
N);
2779void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2782 EVT VT =
N->getOperand(2)->getValueType(0);
2794 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2796 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2798 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2807void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2810 EVT VT =
N->getOperand(2)->getValueType(0);
2822 const EVT ResTys[] = {MVT::i64,
2825 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2827 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2831 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2842 unsigned &LSB,
unsigned &MSB,
2843 unsigned NumberOfIgnoredLowBits,
2844 bool BiggerPattern) {
2846 "N must be a AND operation to call this function");
2848 EVT VT =
N->getValueType(0);
2853 assert((VT == MVT::i32 || VT == MVT::i64) &&
2854 "Type checking must have been done before calling this function");
2868 const SDNode *Op0 =
N->getOperand(0).getNode();
2875 if (AndImm & (AndImm + 1))
2878 bool ClampMSB =
false;
2898 ClampMSB = (VT == MVT::i32);
2899 }
else if (BiggerPattern) {
2905 Opd0 =
N->getOperand(0);
2911 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2914 <<
": Found large shift immediate, this should not happen\n"));
2928 MSB = MSB > 31 ? 31 : MSB;
2930 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2935 SDValue &Opd0,
unsigned &Immr,
2939 EVT VT =
N->getValueType(0);
2941 assert((VT == MVT::i32 || VT == MVT::i64) &&
2942 "Type checking must have been done before calling this function");
2946 Op =
Op->getOperand(0);
2947 VT =
Op->getValueType(0);
2956 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2960 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
2961 Opd0 =
Op.getOperand(0);
2963 Imms = ShiftImm + Width - 1;
2991 Opd0 =
N->getOperand(0).getOperand(0);
3001 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3008 unsigned &Immr,
unsigned &Imms,
3009 bool BiggerPattern) {
3011 "N must be a SHR/SRA operation to call this function");
3013 EVT VT =
N->getValueType(0);
3018 assert((VT == MVT::i32 || VT == MVT::i64) &&
3019 "Type checking must have been done before calling this function");
3029 Opd0 =
N->getOperand(0).getOperand(0);
3030 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3036 Opd0 =
N->getOperand(0).getOperand(0);
3039 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3040 }
else if (BiggerPattern) {
3044 Opd0 =
N->getOperand(0);
3053 <<
": Found large shift immediate, this should not happen\n"));
3062 "bad amount in shift node!");
3063 int immr = SrlImm - ShlImm;
3068 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3070 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3074bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
3077 EVT VT =
N->getValueType(0);
3078 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
3079 if (VT != MVT::i64 || NarrowVT != MVT::i32)
3090 unsigned Immr = ShiftImm;
3092 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3093 CurDAG->getTargetConstant(Imms, dl, VT)};
3094 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
3099 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3100 unsigned NumberOfIgnoredLowBits = 0,
3101 bool BiggerPattern =
false) {
3102 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3105 switch (
N->getOpcode()) {
3107 if (!
N->isMachineOpcode())
3112 NumberOfIgnoredLowBits, BiggerPattern);
3121 unsigned NOpc =
N->getMachineOpcode();
3125 case AArch64::SBFMWri:
3126 case AArch64::UBFMWri:
3127 case AArch64::SBFMXri:
3128 case AArch64::UBFMXri:
3130 Opd0 =
N->getOperand(0);
3131 Immr =
N->getConstantOperandVal(1);
3132 Imms =
N->getConstantOperandVal(2);
3139bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3140 unsigned Opc, Immr, Imms;
3145 EVT VT =
N->getValueType(0);
3150 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3151 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3152 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3154 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3155 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3161 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3162 CurDAG->getTargetConstant(Imms, dl, VT)};
3163 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3172 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3173 assert((VT == MVT::i32 || VT == MVT::i64) &&
3174 "i32 or i64 mask type expected!");
3178 APInt SignificantDstMask =
3182 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3183 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3216 APInt OpUsefulBits(UsefulBits);
3220 OpUsefulBits <<= MSB - Imm + 1;
3225 OpUsefulBits <<= Imm;
3227 OpUsefulBits <<= MSB + 1;
3230 OpUsefulBits <<= OpUsefulBits.
getBitWidth() - Imm;
3236 UsefulBits &= OpUsefulBits;
3253 APInt Mask(UsefulBits);
3254 Mask.clearAllBits();
3262 Mask.lshrInPlace(ShiftAmt);
3268 Mask.lshrInPlace(ShiftAmt);
3284 APInt OpUsefulBits(UsefulBits);
3298 OpUsefulBits <<= Width;
3301 if (
Op.getOperand(1) == Orig) {
3303 Mask = ResultUsefulBits & OpUsefulBits;
3307 if (
Op.getOperand(0) == Orig)
3309 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3315 OpUsefulBits <<= Width;
3317 OpUsefulBits <<= LSB;
3319 if (
Op.getOperand(1) == Orig) {
3321 Mask = ResultUsefulBits & OpUsefulBits;
3322 Mask.lshrInPlace(LSB);
3325 if (
Op.getOperand(0) == Orig)
3326 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3343 case AArch64::ANDSWri:
3344 case AArch64::ANDSXri:
3345 case AArch64::ANDWri:
3346 case AArch64::ANDXri:
3350 case AArch64::UBFMWri:
3351 case AArch64::UBFMXri:
3354 case AArch64::ORRWrs:
3355 case AArch64::ORRXrs:
3360 case AArch64::BFMWri:
3361 case AArch64::BFMXri:
3364 case AArch64::STRBBui:
3365 case AArch64::STURBBi:
3371 case AArch64::STRHHui:
3372 case AArch64::STURHHi:
3385 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3387 UsefulBits =
APInt(Bitwidth, 0);
3396 UsersUsefulBits |= UsefulBitsForUse;
3401 UsefulBits &= UsersUsefulBits;
3411 EVT VT =
Op.getValueType();
3414 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3417 if (ShlAmount > 0) {
3420 UBFMOpc, dl, VT,
Op,
3425 assert(ShlAmount < 0 &&
"expected right shift");
3426 int ShrAmount = -ShlAmount;
3438 const uint64_t NonZeroBits,
3445 const uint64_t NonZeroBits,
3452 bool BiggerPattern,
SDValue &Src,
3453 int &DstLSB,
int &Width) {
3454 EVT VT =
Op.getValueType();
3467 switch (
Op.getOpcode()) {
3472 NonZeroBits, Src, DstLSB, Width);
3475 NonZeroBits, Src, DstLSB, Width);
3488 EVT VT =
Op.getValueType();
3489 assert((VT == MVT::i32 || VT == MVT::i64) &&
3490 "Caller guarantees VT is one of i32 or i64");
3503 assert((~AndImm & NonZeroBits) == 0 &&
3504 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3533 if (!BiggerPattern && !AndOp0.
hasOneUse())
3552 <<
"Found large Width in bit-field-positioning -- this indicates no "
3553 "proper combining / constant folding was performed\n");
3562 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3577 "Op.getNode() should be a SHL node to call this function");
3579 "Op.getNode() should shift ShlImm to call this function");
3586 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3610 EVT VT =
Op.getValueType();
3611 assert((VT == MVT::i32 || VT == MVT::i64) &&
3612 "Caller guarantees that type is i32 or i64");
3619 if (!BiggerPattern && !
Op.hasOneUse())
3628 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3636 assert(VT == MVT::i32 || VT == MVT::i64);
3647 EVT VT =
N->getValueType(0);
3648 if (VT != MVT::i32 && VT != MVT::i64)
3666 if (!
And.hasOneUse() ||
3683 if ((OrImm & NotKnownZero) != 0) {
3695 unsigned ImmS = Width - 1;
3701 bool IsBFI = LSB != 0;
3706 unsigned OrChunks = 0, BFIChunks = 0;
3707 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3708 if (((OrImm >> Shift) & 0xFFFF) != 0)
3710 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3713 if (BFIChunks > OrChunks)
3719 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3727 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3736 if (!Dst.hasOneUse())
3739 EVT VT = Dst.getValueType();
3740 assert((VT == MVT::i32 || VT == MVT::i64) &&
3741 "Caller should guarantee that VT is one of i32 or i64");
3769 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3770 unsigned MaskWidth =
3773 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3779 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3780 ShiftedOperand =
SDValue(UBFMNode, 0);
3809 const bool BiggerPattern) {
3810 EVT VT =
N->getValueType(0);
3811 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3812 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3813 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3814 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3815 assert((VT == MVT::i32 || VT == MVT::i64) &&
3816 "Expect result type to be i32 or i64 since N is combinable to BFM");
3823 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3826 if (BiggerPattern) {
3849 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3911 EVT VT =
N->getValueType(0);
3912 if (VT != MVT::i32 && VT != MVT::i64)
3920 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3921 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3941 for (
int I = 0;
I < 4; ++
I) {
3944 unsigned ImmR, ImmS;
3945 bool BiggerPattern =
I / 2;
3946 SDValue OrOpd0Val =
N->getOperand(
I % 2);
3948 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
3954 NumberOfIgnoredLowBits, BiggerPattern)) {
3957 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
3958 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
3963 Width = ImmS - ImmR + 1;
3974 Src, DstLSB, Width)) {
3982 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
3992 APInt BitsToBeInserted =
3995 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4019 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4052 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4054 if (Src->hasOneUse() &&
4057 Src = Src->getOperand(0);
4067 unsigned ImmS = Width - 1;
4073 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4081bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4090 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4103bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4107 EVT VT =
N->getValueType(0);
4108 if (VT != MVT::i32 && VT != MVT::i64)
4114 Op0, DstLSB, Width))
4120 unsigned ImmS = Width - 1;
4123 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4124 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4125 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4126 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4132bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4133 EVT VT =
N->getValueType(0);
4136 switch (
N->getOpcode()) {
4138 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4141 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4144 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4147 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4155 if (VT == MVT::i32) {
4158 }
else if (VT == MVT::i64) {
4164 SDValue ShiftAmt =
N->getOperand(1);
4184 (Add0Imm %
Size == 0)) {
4190 if (SubVT == MVT::i32) {
4191 NegOpc = AArch64::SUBWrr;
4192 ZeroReg = AArch64::WZR;
4194 assert(SubVT == MVT::i64);
4195 NegOpc = AArch64::SUBXrr;
4196 ZeroReg = AArch64::XZR;
4199 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4200 MachineSDNode *Neg =
4201 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4202 NewShiftAmt =
SDValue(Neg, 0);
4210 if (SubVT == MVT::i32) {
4211 NotOpc = AArch64::ORNWrr;
4212 ZeroReg = AArch64::WZR;
4214 assert(SubVT == MVT::i64);
4215 NotOpc = AArch64::ORNXrr;
4216 ZeroReg = AArch64::XZR;
4219 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4220 MachineSDNode *
Not =
4221 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4222 NewShiftAmt =
SDValue(Not, 0);
4243 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4244 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4245 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4246 NewShiftAmt, SubReg);
4247 NewShiftAmt =
SDValue(Ext, 0);
4251 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4258 bool isReciprocal) {
4261 FVal = CN->getValueAPF();
4264 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4274 if (
unsigned FBits =
4287 bool isReciprocal) {
4288 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4289 N.getValueType().getScalarSizeInBits() ==
4290 N.getOperand(0).getValueType().getScalarSizeInBits())
4291 N =
N.getOperand(0);
4293 auto ImmToFloat = [RegWidth](
APInt Imm) {
4307 switch (
N->getOpcode()) {
4308 case AArch64ISD::MOVIshift:
4309 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4310 <<
N.getConstantOperandVal(1)));
4312 case AArch64ISD::FMOV:
4313 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4315 case AArch64ISD::DUP:
4317 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4325 if (
unsigned FBits =
4334bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
4335 unsigned RegWidth) {
4340bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
4341 unsigned RegWidth) {
4343 CurDAG,
N, FixedPos, RegWidth,
false);
4346bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(
SDValue N,
4348 unsigned RegWidth) {
4350 CurDAG,
N, FixedPos, RegWidth,
true);
4353bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(
SDValue N,
4355 unsigned RegWidth) {
4365 RegString.
split(Fields,
':');
4367 if (Fields.
size() == 1)
4371 &&
"Invalid number of fields in read register string");
4374 bool AllIntFields =
true;
4378 AllIntFields &= !
Field.getAsInteger(10, IntField);
4379 Ops.push_back(IntField);
4383 "Unexpected non-integer value in special register string.");
4388 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4396bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4398 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4401 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4403 unsigned Opcode64Bit = AArch64::MRS;
4408 const auto *TheReg =
4409 AArch64SysReg::lookupSysRegByName(RegString->getString());
4410 if (TheReg && TheReg->Readable &&
4411 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4412 Imm = TheReg->Encoding;
4418 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4419 Opcode64Bit = AArch64::ADR;
4428 RegString->getString());
4429 unsigned PseudoOp = 0;
4430 if (AArch64::GPR64RegClass.
contains(PReg))
4431 PseudoOp = AArch64::READ_REGISTER_GPR64;
4432 else if (AArch64::FPR64RegClass.
contains(PReg))
4433 PseudoOp = AArch64::READ_REGISTER_FPR64;
4434 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4435 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4436 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4445 SDValue InChain =
N->getOperand(0);
4446 SDValue SysRegImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
4447 if (!ReadIs128Bit) {
4448 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4449 {SysRegImm, InChain});
4451 SDNode *MRRS = CurDAG->getMachineNode(
4453 {MVT::Untyped , MVT::Other },
4454 {SysRegImm, InChain});
4458 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4460 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4466 ReplaceUses(
SDValue(
N, 2), OutChain);
4475bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4477 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4480 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4482 if (!WriteIs128Bit) {
4488 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4491 "Expected a constant integer expression.");
4492 unsigned Reg = PMapper->Encoding;
4493 uint64_t Immed =
N->getConstantOperandVal(2);
4494 CurDAG->SelectNodeTo(
4495 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4496 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4502 if (trySelectPState(
4503 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4504 AArch64::MSRpstateImm4))
4506 if (trySelectPState(
4507 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4508 AArch64::MSRpstateImm1))
4517 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4518 if (TheReg && TheReg->Writeable &&
4519 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4520 Imm = TheReg->Encoding;
4530 RegString->getString());
4531 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4532 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4533 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4534 N->getOperand(2).getValueType() == MVT::i64) {
4536 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4537 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4538 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4539 MVT::Other, {RegOp,
Copy});
4541 CurDAG->RemoveDeadNode(
N);
4549 if (!WriteIs128Bit) {
4550 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4551 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4552 N->getOperand(2), InChain);
4556 SDNode *Pair = CurDAG->getMachineNode(
4557 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4558 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4561 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4563 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4565 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4566 CurDAG->getTargetConstant(Imm,
DL, MVT::i32),
4574bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4579 if (Subtarget->hasLSE())
return false;
4581 if (MemTy == MVT::i8)
4582 Opcode = AArch64::CMP_SWAP_8;
4583 else if (MemTy == MVT::i16)
4584 Opcode = AArch64::CMP_SWAP_16;
4585 else if (MemTy == MVT::i32)
4586 Opcode = AArch64::CMP_SWAP_32;
4587 else if (MemTy == MVT::i64)
4588 Opcode = AArch64::CMP_SWAP_64;
4592 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4593 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4595 SDNode *CmpSwap = CurDAG->getMachineNode(
4597 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4604 CurDAG->RemoveDeadNode(
N);
4609bool AArch64DAGToDAGISel::SelectSVEAddSubImm(
SDValue N, MVT VT,
SDValue &Imm,
4610 SDValue &Shift,
bool Negate) {
4617 return SelectSVEAddSubImm(SDLoc(
N), Val, VT, Imm, Shift, Negate);
4620bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4629 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4636 if ((Val & ~0xff) == 0) {
4637 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4642 if ((Val & ~0xff00) == 0) {
4643 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4655bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(
SDValue N, MVT VT,
4679 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4680 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4687 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4688 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4692 if (Val <= 65280 && Val % 256 == 0) {
4693 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4694 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4705bool AArch64DAGToDAGISel::SelectSVECpyDupImm(
SDValue N, MVT VT,
SDValue &Imm,
4715 int32_t ImmVal, ShiftVal;
4720 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4721 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4725bool AArch64DAGToDAGISel::SelectSVESignedArithImm(
SDValue N,
SDValue &Imm) {
4727 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(), Imm);
4731bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4734 if (ImmVal >= -128 && ImmVal < 128) {
4735 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4741bool AArch64DAGToDAGISel::SelectSVEArithImm(
SDValue N, MVT VT,
SDValue &Imm) {
4743 uint64_t ImmVal = CNode->getZExtValue();
4753 ImmVal &= 0xFFFFFFFF;
4762 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4769bool AArch64DAGToDAGISel::SelectSVELogicalImm(
SDValue N, MVT VT,
SDValue &Imm,
4773 ImmVal = CI->getZExtValue();
4775 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4786 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4795bool AArch64DAGToDAGISel::SelectSVEShiftImm(
SDValue N, uint64_t
Low,
4796 uint64_t
High,
bool AllowSaturation,
4799 uint64_t ImmVal = CN->getZExtValue();
4806 if (ImmVal >
High) {
4807 if (!AllowSaturation)
4812 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4819bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4833 const TargetLowering *TLI = getTargetLowering();
4836 SDValue FiOp = CurDAG->getTargetFrameIndex(
4838 int TagOffset =
N->getConstantOperandVal(3);
4840 SDNode *Out = CurDAG->getMachineNode(
4841 AArch64::TAGPstack,
DL, MVT::i64,
4842 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4843 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4844 ReplaceNode(
N, Out);
4848void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4850 "llvm.aarch64.tagp third argument must be an immediate");
4851 if (trySelectStackSlotTagP(
N))
4858 int TagOffset =
N->getConstantOperandVal(3);
4859 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4860 {
N->getOperand(1),
N->getOperand(2)});
4861 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4862 {
SDValue(N1, 0),
N->getOperand(2)});
4863 SDNode *N3 = CurDAG->getMachineNode(
4864 AArch64::ADDG,
DL, MVT::i64,
4865 {
SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4866 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4870bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4874 if (
N->getConstantOperandVal(2) != 0)
4876 if (!
N->getOperand(0).isUndef())
4880 EVT VT =
N->getValueType(0);
4881 EVT InVT =
N->getOperand(1).getValueType();
4892 "Expected to insert into a packed scalable vector!");
4895 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4896 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4897 N->getOperand(1), RC));
4901bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4905 if (
N->getConstantOperandVal(1) != 0)
4909 EVT VT =
N->getValueType(0);
4910 EVT InVT =
N->getOperand(0).getValueType();
4921 "Expected to extract from a packed scalable vector!");
4924 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4925 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4926 N->getOperand(0), RC));
4930bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4936 EVT VT =
N->getValueType(0);
4949 (Subtarget->hasSVE2() ||
4950 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4951 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4954 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4958 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4959 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4960 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4967 bool IsXOROperand =
true;
4969 IsXOROperand =
false;
4975 APInt ShlAmt, ShrAmt;
4983 if (!IsXOROperand) {
4985 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4988 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4989 SDNode *SubRegToReg =
4990 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
5001 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5002 AArch64::XAR_ZZZI_D})) {
5003 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5028 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5038 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5046 bool IsXOROperand =
true;
5048 IsXOROperand =
false;
5051 R1 =
XOR.getOperand(0);
5052 R2 =
XOR.getOperand(1);
5062 if (ShAmt + HsAmt != VTSizeInBits)
5065 if (!IsXOROperand) {
5068 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5077 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5083 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5084 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5086 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5089 if (
R2.getValueType() == VT)
5090 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5095 SDValue SubReg = CurDAG->getTargetConstant(
5098 R1 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5103 R2 =
SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5109 SDNode *XAR =
nullptr;
5113 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5114 AArch64::XAR_ZZZI_D}))
5115 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5117 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5120 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5126 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5127 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5130 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5131 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5134 SDValue SubReg = CurDAG->getTargetConstant(
5137 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5141 ReplaceNode(
N, XAR);
5148 assert(VT == MVT::i32 || VT == MVT::i64);
5150 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5153void AArch64DAGToDAGISel::Select(SDNode *Node) {
5155 if (
Node->isMachineOpcode()) {
5157 Node->setNodeId(-1);
5162 EVT VT =
Node->getValueType(0);
5164 switch (
Node->getOpcode()) {
5169 if (SelectCMP_SWAP(Node))
5174 case AArch64ISD::MRRS:
5175 if (tryReadRegister(Node))
5180 case AArch64ISD::MSRR:
5181 if (tryWriteRegister(Node))
5188 if (tryIndexedLoad(Node))
5197 if (tryBitfieldExtractOp(Node))
5199 if (tryBitfieldInsertInZeroOp(Node))
5204 if (tryShiftAmountMod(Node))
5209 if (tryBitfieldExtractOpFromSExt(Node))
5214 if (tryBitfieldInsertOp(Node))
5216 if (trySelectXAR(Node))
5221 if (trySelectCastScalableToFixedLengthVector(Node))
5227 if (trySelectCastFixedLengthToScalableVector(Node))
5236 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5247 const TargetLowering *TLI = getTargetLowering();
5248 SDValue TFI = CurDAG->getTargetFrameIndex(
5251 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5252 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5253 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5257 unsigned IntNo =
Node->getConstantOperandVal(1);
5261 case Intrinsic::aarch64_gcsss: {
5265 SDValue Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5267 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5268 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5269 MVT::Other, Zero,
SDValue(SS1, 0));
5270 ReplaceNode(Node, SS2);
5273 case Intrinsic::aarch64_ldaxp:
5274 case Intrinsic::aarch64_ldxp: {
5276 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5281 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5282 MVT::Other, MemAddr, Chain);
5285 MachineMemOperand *MemOp =
5288 ReplaceNode(Node, Ld);
5291 case Intrinsic::aarch64_stlxp:
5292 case Intrinsic::aarch64_stxp: {
5294 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5302 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5304 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5306 MachineMemOperand *MemOp =
5310 ReplaceNode(Node, St);
5313 case Intrinsic::aarch64_neon_ld1x2:
5314 if (VT == MVT::v8i8) {
5315 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5317 }
else if (VT == MVT::v16i8) {
5318 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5320 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5321 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5323 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5324 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5326 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5327 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5329 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5330 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5332 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5333 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5335 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5336 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5340 case Intrinsic::aarch64_neon_ld1x3:
5341 if (VT == MVT::v8i8) {
5342 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5344 }
else if (VT == MVT::v16i8) {
5345 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5347 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5348 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5350 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5351 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5353 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5354 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5356 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5357 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5359 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5360 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5362 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5363 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5367 case Intrinsic::aarch64_neon_ld1x4:
5368 if (VT == MVT::v8i8) {
5369 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5371 }
else if (VT == MVT::v16i8) {
5372 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5374 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5375 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5377 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5378 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5380 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5381 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5383 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5384 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5386 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5387 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5389 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5390 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5394 case Intrinsic::aarch64_neon_ld2:
5395 if (VT == MVT::v8i8) {
5396 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5398 }
else if (VT == MVT::v16i8) {
5399 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5401 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5402 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5404 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5405 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5407 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5408 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5410 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5411 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5413 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5414 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5416 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5417 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5421 case Intrinsic::aarch64_neon_ld3:
5422 if (VT == MVT::v8i8) {
5423 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5425 }
else if (VT == MVT::v16i8) {
5426 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5428 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5429 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5431 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5432 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5434 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5435 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5437 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5438 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5440 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5441 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5443 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5444 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5448 case Intrinsic::aarch64_neon_ld4:
5449 if (VT == MVT::v8i8) {
5450 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5452 }
else if (VT == MVT::v16i8) {
5453 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5455 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5456 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5458 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5459 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5461 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5462 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5464 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5465 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5467 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5468 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5470 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5471 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5475 case Intrinsic::aarch64_neon_ld2r:
5476 if (VT == MVT::v8i8) {
5477 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5479 }
else if (VT == MVT::v16i8) {
5480 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5482 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5483 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5485 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5486 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5488 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5489 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5491 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5492 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5494 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5495 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5497 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5498 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5502 case Intrinsic::aarch64_neon_ld3r:
5503 if (VT == MVT::v8i8) {
5504 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5506 }
else if (VT == MVT::v16i8) {
5507 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5509 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5510 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5512 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5513 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5515 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5516 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5518 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5519 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5521 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5522 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5524 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5525 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5529 case Intrinsic::aarch64_neon_ld4r:
5530 if (VT == MVT::v8i8) {
5531 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5533 }
else if (VT == MVT::v16i8) {
5534 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5536 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5537 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5539 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5540 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5542 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5543 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5545 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5546 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5548 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5549 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5551 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5552 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5556 case Intrinsic::aarch64_neon_ld2lane:
5557 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5558 SelectLoadLane(Node, 2, AArch64::LD2i8);
5560 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5561 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5562 SelectLoadLane(Node, 2, AArch64::LD2i16);
5564 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5566 SelectLoadLane(Node, 2, AArch64::LD2i32);
5568 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5570 SelectLoadLane(Node, 2, AArch64::LD2i64);
5574 case Intrinsic::aarch64_neon_ld3lane:
5575 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5576 SelectLoadLane(Node, 3, AArch64::LD3i8);
5578 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5579 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5580 SelectLoadLane(Node, 3, AArch64::LD3i16);
5582 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5584 SelectLoadLane(Node, 3, AArch64::LD3i32);
5586 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5588 SelectLoadLane(Node, 3, AArch64::LD3i64);
5592 case Intrinsic::aarch64_neon_ld4lane:
5593 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5594 SelectLoadLane(Node, 4, AArch64::LD4i8);
5596 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5597 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5598 SelectLoadLane(Node, 4, AArch64::LD4i16);
5600 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5602 SelectLoadLane(Node, 4, AArch64::LD4i32);
5604 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5606 SelectLoadLane(Node, 4, AArch64::LD4i64);
5610 case Intrinsic::aarch64_ld64b:
5611 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5613 case Intrinsic::aarch64_sve_ld2q_sret: {
5614 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5617 case Intrinsic::aarch64_sve_ld3q_sret: {
5618 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5621 case Intrinsic::aarch64_sve_ld4q_sret: {
5622 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5625 case Intrinsic::aarch64_sve_ld2_sret: {
5626 if (VT == MVT::nxv16i8) {
5627 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5630 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5631 VT == MVT::nxv8bf16) {
5632 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5635 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5636 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5639 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5640 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5646 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5647 if (VT == MVT::nxv16i8) {
5648 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5649 SelectContiguousMultiVectorLoad(
5650 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5651 else if (Subtarget->hasSVE2p1())
5652 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5657 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5658 VT == MVT::nxv8bf16) {
5659 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5660 SelectContiguousMultiVectorLoad(
5661 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5662 else if (Subtarget->hasSVE2p1())
5663 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5668 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5669 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5670 SelectContiguousMultiVectorLoad(
5671 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5672 else if (Subtarget->hasSVE2p1())
5673 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5678 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5679 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5680 SelectContiguousMultiVectorLoad(
5681 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5682 else if (Subtarget->hasSVE2p1())
5683 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5691 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5692 if (VT == MVT::nxv16i8) {
5693 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5694 SelectContiguousMultiVectorLoad(
5695 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5696 else if (Subtarget->hasSVE2p1())
5697 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5702 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5703 VT == MVT::nxv8bf16) {
5704 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5705 SelectContiguousMultiVectorLoad(
5706 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5707 else if (Subtarget->hasSVE2p1())
5708 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5713 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5714 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5715 SelectContiguousMultiVectorLoad(
5716 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5717 else if (Subtarget->hasSVE2p1())
5718 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5723 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5724 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5725 SelectContiguousMultiVectorLoad(
5726 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5727 else if (Subtarget->hasSVE2p1())
5728 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5736 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5737 if (VT == MVT::nxv16i8) {
5738 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5739 SelectContiguousMultiVectorLoad(Node, 2, 0,
5740 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5741 AArch64::LDNT1B_2Z_PSEUDO);
5742 else if (Subtarget->hasSVE2p1())
5743 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5744 AArch64::LDNT1B_2Z);
5748 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5749 VT == MVT::nxv8bf16) {
5750 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5751 SelectContiguousMultiVectorLoad(Node, 2, 1,
5752 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5753 AArch64::LDNT1H_2Z_PSEUDO);
5754 else if (Subtarget->hasSVE2p1())
5755 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5756 AArch64::LDNT1H_2Z);
5760 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5761 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5762 SelectContiguousMultiVectorLoad(Node, 2, 2,
5763 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5764 AArch64::LDNT1W_2Z_PSEUDO);
5765 else if (Subtarget->hasSVE2p1())
5766 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5767 AArch64::LDNT1W_2Z);
5771 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5772 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5773 SelectContiguousMultiVectorLoad(Node, 2, 3,
5774 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5775 AArch64::LDNT1D_2Z_PSEUDO);
5776 else if (Subtarget->hasSVE2p1())
5777 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5778 AArch64::LDNT1D_2Z);
5785 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5786 if (VT == MVT::nxv16i8) {
5787 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5788 SelectContiguousMultiVectorLoad(Node, 4, 0,
5789 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5790 AArch64::LDNT1B_4Z_PSEUDO);
5791 else if (Subtarget->hasSVE2p1())
5792 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5793 AArch64::LDNT1B_4Z);
5797 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5798 VT == MVT::nxv8bf16) {
5799 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5800 SelectContiguousMultiVectorLoad(Node, 4, 1,
5801 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5802 AArch64::LDNT1H_4Z_PSEUDO);
5803 else if (Subtarget->hasSVE2p1())
5804 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5805 AArch64::LDNT1H_4Z);
5809 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5810 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5811 SelectContiguousMultiVectorLoad(Node, 4, 2,
5812 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5813 AArch64::LDNT1W_4Z_PSEUDO);
5814 else if (Subtarget->hasSVE2p1())
5815 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5816 AArch64::LDNT1W_4Z);
5820 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5821 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5822 SelectContiguousMultiVectorLoad(Node, 4, 3,
5823 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5824 AArch64::LDNT1D_4Z_PSEUDO);
5825 else if (Subtarget->hasSVE2p1())
5826 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5827 AArch64::LDNT1D_4Z);
5834 case Intrinsic::aarch64_sve_ld3_sret: {
5835 if (VT == MVT::nxv16i8) {
5836 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5839 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5840 VT == MVT::nxv8bf16) {
5841 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5844 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5845 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5848 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5849 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5855 case Intrinsic::aarch64_sve_ld4_sret: {
5856 if (VT == MVT::nxv16i8) {
5857 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5860 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5861 VT == MVT::nxv8bf16) {
5862 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5865 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5866 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5869 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5870 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5876 case Intrinsic::aarch64_sme_read_hor_vg2: {
5877 if (VT == MVT::nxv16i8) {
5878 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5879 AArch64::MOVA_2ZMXI_H_B);
5881 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5882 VT == MVT::nxv8bf16) {
5883 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5884 AArch64::MOVA_2ZMXI_H_H);
5886 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5887 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5888 AArch64::MOVA_2ZMXI_H_S);
5890 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5891 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5892 AArch64::MOVA_2ZMXI_H_D);
5897 case Intrinsic::aarch64_sme_read_ver_vg2: {
5898 if (VT == MVT::nxv16i8) {
5899 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5900 AArch64::MOVA_2ZMXI_V_B);
5902 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5903 VT == MVT::nxv8bf16) {
5904 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5905 AArch64::MOVA_2ZMXI_V_H);
5907 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5908 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5909 AArch64::MOVA_2ZMXI_V_S);
5911 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5912 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5913 AArch64::MOVA_2ZMXI_V_D);
5918 case Intrinsic::aarch64_sme_read_hor_vg4: {
5919 if (VT == MVT::nxv16i8) {
5920 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5921 AArch64::MOVA_4ZMXI_H_B);
5923 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5924 VT == MVT::nxv8bf16) {
5925 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5926 AArch64::MOVA_4ZMXI_H_H);
5928 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5929 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5930 AArch64::MOVA_4ZMXI_H_S);
5932 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5933 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5934 AArch64::MOVA_4ZMXI_H_D);
5939 case Intrinsic::aarch64_sme_read_ver_vg4: {
5940 if (VT == MVT::nxv16i8) {
5941 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5942 AArch64::MOVA_4ZMXI_V_B);
5944 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5945 VT == MVT::nxv8bf16) {
5946 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5947 AArch64::MOVA_4ZMXI_V_H);
5949 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5950 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5951 AArch64::MOVA_4ZMXI_V_S);
5953 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5954 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5955 AArch64::MOVA_4ZMXI_V_D);
5960 case Intrinsic::aarch64_sme_read_vg1x2: {
5961 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5962 AArch64::MOVA_VG2_2ZMXI);
5965 case Intrinsic::aarch64_sme_read_vg1x4: {
5966 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5967 AArch64::MOVA_VG4_4ZMXI);
5970 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5971 if (VT == MVT::nxv16i8) {
5972 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5974 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5975 VT == MVT::nxv8bf16) {
5976 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5978 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5979 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5981 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5982 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5987 case Intrinsic::aarch64_sme_readz_vert_x2: {
5988 if (VT == MVT::nxv16i8) {
5989 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5991 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5992 VT == MVT::nxv8bf16) {
5993 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5995 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5996 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5998 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5999 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
6004 case Intrinsic::aarch64_sme_readz_horiz_x4: {
6005 if (VT == MVT::nxv16i8) {
6006 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
6008 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6009 VT == MVT::nxv8bf16) {
6010 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6012 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6013 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6015 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6016 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6021 case Intrinsic::aarch64_sme_readz_vert_x4: {
6022 if (VT == MVT::nxv16i8) {
6023 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6025 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6026 VT == MVT::nxv8bf16) {
6027 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6029 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6030 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6032 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6033 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6038 case Intrinsic::aarch64_sme_readz_x2: {
6039 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6043 case Intrinsic::aarch64_sme_readz_x4: {
6044 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6048 case Intrinsic::swift_async_context_addr: {
6051 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6053 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6054 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6055 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6057 ReplaceUses(
SDValue(Node, 0), Res);
6059 CurDAG->RemoveDeadNode(Node);
6061 auto &MF = CurDAG->getMachineFunction();
6062 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6063 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6066 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6068 Node->getValueType(0),
6069 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6070 AArch64::LUTI2_4ZTZI_S}))
6072 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6075 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6077 Node->getValueType(0),
6078 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6080 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6083 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6085 Node->getValueType(0),
6086 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6087 AArch64::LUTI2_2ZTZI_S}))
6089 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6092 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6094 Node->getValueType(0),
6095 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6096 AArch64::LUTI4_2ZTZI_S}))
6098 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6101 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6102 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6105 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6106 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6109 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6111 Node->getValueType(0),
6112 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6113 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6115 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6117 Node->getValueType(0),
6118 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6119 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6121 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6123 Node->getValueType(0),
6124 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6125 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6127 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6129 Node->getValueType(0),
6130 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6131 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6133 case Intrinsic::ptrauth_resign_load_relative:
6134 SelectPtrauthResign(Node);
6139 unsigned IntNo =
Node->getConstantOperandVal(0);
6143 case Intrinsic::aarch64_tagp:
6147 case Intrinsic::ptrauth_auth:
6148 SelectPtrauthAuth(Node);
6151 case Intrinsic::ptrauth_resign:
6152 SelectPtrauthResign(Node);
6155 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6156 SelectPtrauthResignWithPC(Node);
6159 case Intrinsic::aarch64_neon_tbl2:
6160 SelectTable(Node, 2,
6161 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6164 case Intrinsic::aarch64_neon_tbl3:
6165 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6166 : AArch64::TBLv16i8Three,
6169 case Intrinsic::aarch64_neon_tbl4:
6170 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6171 : AArch64::TBLv16i8Four,
6174 case Intrinsic::aarch64_neon_tbx2:
6175 SelectTable(Node, 2,
6176 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6179 case Intrinsic::aarch64_neon_tbx3:
6180 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6181 : AArch64::TBXv16i8Three,
6184 case Intrinsic::aarch64_neon_tbx4:
6185 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6186 : AArch64::TBXv16i8Four,
6189 case Intrinsic::aarch64_sve_srshl_single_x2:
6191 Node->getValueType(0),
6192 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6193 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6194 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6196 case Intrinsic::aarch64_sve_srshl_single_x4:
6198 Node->getValueType(0),
6199 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6200 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6201 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6203 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6204 SelectMultiVectorLuti6LaneX4(Node, 2);
6206 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6207 SelectMultiVectorLuti6LaneX4(Node, 3);
6209 case Intrinsic::aarch64_sve_urshl_single_x2:
6211 Node->getValueType(0),
6212 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6213 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6214 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6216 case Intrinsic::aarch64_sve_urshl_single_x4:
6218 Node->getValueType(0),
6219 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6220 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6221 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6223 case Intrinsic::aarch64_sve_srshl_x2:
6225 Node->getValueType(0),
6226 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6227 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6228 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6230 case Intrinsic::aarch64_sve_srshl_x4:
6232 Node->getValueType(0),
6233 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6234 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6235 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6237 case Intrinsic::aarch64_sve_urshl_x2:
6239 Node->getValueType(0),
6240 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6241 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6242 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6244 case Intrinsic::aarch64_sve_urshl_x4:
6246 Node->getValueType(0),
6247 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6248 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6249 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6251 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6253 Node->getValueType(0),
6254 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6255 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6256 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6258 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6260 Node->getValueType(0),
6261 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6262 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6263 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6265 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6267 Node->getValueType(0),
6268 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6269 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6270 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6272 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6274 Node->getValueType(0),
6275 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6276 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6277 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6279 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6281 Node->getValueType(0),
6282 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6283 AArch64::FSCALE_2ZZ_D}))
6284 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6286 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6288 Node->getValueType(0),
6289 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6290 AArch64::FSCALE_4ZZ_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6293 case Intrinsic::aarch64_sme_fp8_scale_x2:
6295 Node->getValueType(0),
6296 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6297 AArch64::FSCALE_2Z2Z_D}))
6298 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6300 case Intrinsic::aarch64_sme_fp8_scale_x4:
6302 Node->getValueType(0),
6303 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6304 AArch64::FSCALE_4Z4Z_D}))
6305 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6307 case Intrinsic::aarch64_sve_whilege_x2:
6309 Node->getValueType(0),
6310 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6311 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6312 SelectWhilePair(Node,
Op);
6314 case Intrinsic::aarch64_sve_whilegt_x2:
6316 Node->getValueType(0),
6317 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6318 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6319 SelectWhilePair(Node,
Op);
6321 case Intrinsic::aarch64_sve_whilehi_x2:
6323 Node->getValueType(0),
6324 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6325 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6326 SelectWhilePair(Node,
Op);
6328 case Intrinsic::aarch64_sve_whilehs_x2:
6330 Node->getValueType(0),
6331 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6332 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6333 SelectWhilePair(Node,
Op);
6335 case Intrinsic::aarch64_sve_whilele_x2:
6337 Node->getValueType(0),
6338 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6339 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6340 SelectWhilePair(Node,
Op);
6342 case Intrinsic::aarch64_sve_whilelo_x2:
6344 Node->getValueType(0),
6345 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6346 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6347 SelectWhilePair(Node,
Op);
6349 case Intrinsic::aarch64_sve_whilels_x2:
6351 Node->getValueType(0),
6352 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6353 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6354 SelectWhilePair(Node,
Op);
6356 case Intrinsic::aarch64_sve_whilelt_x2:
6358 Node->getValueType(0),
6359 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6360 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6361 SelectWhilePair(Node,
Op);
6363 case Intrinsic::aarch64_sve_smax_single_x2:
6365 Node->getValueType(0),
6366 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6367 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6368 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6370 case Intrinsic::aarch64_sve_umax_single_x2:
6372 Node->getValueType(0),
6373 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6374 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6375 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6377 case Intrinsic::aarch64_sve_fmax_single_x2:
6379 Node->getValueType(0),
6380 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6381 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6382 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6384 case Intrinsic::aarch64_sve_smax_single_x4:
6386 Node->getValueType(0),
6387 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6388 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6389 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6391 case Intrinsic::aarch64_sve_umax_single_x4:
6393 Node->getValueType(0),
6394 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6395 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6396 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6398 case Intrinsic::aarch64_sve_fmax_single_x4:
6400 Node->getValueType(0),
6401 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6402 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6403 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6405 case Intrinsic::aarch64_sve_smin_single_x2:
6407 Node->getValueType(0),
6408 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6409 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6410 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6412 case Intrinsic::aarch64_sve_umin_single_x2:
6414 Node->getValueType(0),
6415 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6416 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6417 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6419 case Intrinsic::aarch64_sve_fmin_single_x2:
6421 Node->getValueType(0),
6422 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6423 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6424 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6426 case Intrinsic::aarch64_sve_smin_single_x4:
6428 Node->getValueType(0),
6429 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6430 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6431 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6433 case Intrinsic::aarch64_sve_umin_single_x4:
6435 Node->getValueType(0),
6436 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6437 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6438 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6440 case Intrinsic::aarch64_sve_fmin_single_x4:
6442 Node->getValueType(0),
6443 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6444 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6445 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6447 case Intrinsic::aarch64_sve_smax_x2:
6449 Node->getValueType(0),
6450 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6451 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6452 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6454 case Intrinsic::aarch64_sve_umax_x2:
6456 Node->getValueType(0),
6457 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6458 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6459 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6461 case Intrinsic::aarch64_sve_fmax_x2:
6463 Node->getValueType(0),
6464 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6465 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6466 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6468 case Intrinsic::aarch64_sve_smax_x4:
6470 Node->getValueType(0),
6471 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6472 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6473 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6475 case Intrinsic::aarch64_sve_umax_x4:
6477 Node->getValueType(0),
6478 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6479 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6480 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6482 case Intrinsic::aarch64_sve_fmax_x4:
6484 Node->getValueType(0),
6485 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6486 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6487 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6489 case Intrinsic::aarch64_sme_famax_x2:
6491 Node->getValueType(0),
6492 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6493 AArch64::FAMAX_2Z2Z_D}))
6494 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6496 case Intrinsic::aarch64_sme_famax_x4:
6498 Node->getValueType(0),
6499 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6500 AArch64::FAMAX_4Z4Z_D}))
6501 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6503 case Intrinsic::aarch64_sme_famin_x2:
6505 Node->getValueType(0),
6506 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6507 AArch64::FAMIN_2Z2Z_D}))
6508 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6510 case Intrinsic::aarch64_sme_famin_x4:
6512 Node->getValueType(0),
6513 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6514 AArch64::FAMIN_4Z4Z_D}))
6515 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6517 case Intrinsic::aarch64_sve_smin_x2:
6519 Node->getValueType(0),
6520 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6521 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6522 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6524 case Intrinsic::aarch64_sve_umin_x2:
6526 Node->getValueType(0),
6527 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6528 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6529 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6531 case Intrinsic::aarch64_sve_fmin_x2:
6533 Node->getValueType(0),
6534 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6535 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6536 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6538 case Intrinsic::aarch64_sve_smin_x4:
6540 Node->getValueType(0),
6541 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6542 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6543 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6545 case Intrinsic::aarch64_sve_umin_x4:
6547 Node->getValueType(0),
6548 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6549 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6550 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6552 case Intrinsic::aarch64_sve_fmin_x4:
6554 Node->getValueType(0),
6555 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6556 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6557 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6559 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6561 Node->getValueType(0),
6562 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6563 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6564 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6566 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6568 Node->getValueType(0),
6569 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6570 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6571 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6573 case Intrinsic::aarch64_sve_fminnm_single_x2:
6575 Node->getValueType(0),
6576 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6577 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6578 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6580 case Intrinsic::aarch64_sve_fminnm_single_x4:
6582 Node->getValueType(0),
6583 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6584 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6585 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6587 case Intrinsic::aarch64_sve_fscale_single_x4:
6588 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6590 case Intrinsic::aarch64_sve_fscale_single_x2:
6591 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6593 case Intrinsic::aarch64_sve_fmul_single_x4:
6595 Node->getValueType(0),
6596 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6597 AArch64::FMUL_4ZZ_D}))
6598 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6600 case Intrinsic::aarch64_sve_fmul_single_x2:
6602 Node->getValueType(0),
6603 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6604 AArch64::FMUL_2ZZ_D}))
6605 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6607 case Intrinsic::aarch64_sve_fmaxnm_x2:
6609 Node->getValueType(0),
6610 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6611 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6612 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6614 case Intrinsic::aarch64_sve_fmaxnm_x4:
6616 Node->getValueType(0),
6617 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6618 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6619 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6621 case Intrinsic::aarch64_sve_fminnm_x2:
6623 Node->getValueType(0),
6624 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6625 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6626 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6628 case Intrinsic::aarch64_sve_fminnm_x4:
6630 Node->getValueType(0),
6631 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6632 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6633 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6635 case Intrinsic::aarch64_sve_aese_lane_x2:
6636 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6638 case Intrinsic::aarch64_sve_aesd_lane_x2:
6639 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6641 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6642 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6644 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6645 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6647 case Intrinsic::aarch64_sve_aese_lane_x4:
6648 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6650 case Intrinsic::aarch64_sve_aesd_lane_x4:
6651 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6653 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6654 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6656 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6657 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6659 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6660 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6662 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6666 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6668 for (
unsigned I = 0;
I < 2;
I++)
6670 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6672 CurDAG->RemoveDeadNode(Node);
6675 case Intrinsic::aarch64_sve_fscale_x4:
6676 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6678 case Intrinsic::aarch64_sve_fscale_x2:
6679 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6681 case Intrinsic::aarch64_sve_fmul_x4:
6683 Node->getValueType(0),
6684 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6685 AArch64::FMUL_4Z4Z_D}))
6686 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6688 case Intrinsic::aarch64_sve_fmul_x2:
6690 Node->getValueType(0),
6691 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6692 AArch64::FMUL_2Z2Z_D}))
6693 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6695 case Intrinsic::aarch64_sve_fcvtzs_x2:
6696 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6698 case Intrinsic::aarch64_sve_scvtf_x2:
6699 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6701 case Intrinsic::aarch64_sve_fcvtzu_x2:
6702 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6704 case Intrinsic::aarch64_sve_ucvtf_x2:
6705 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6707 case Intrinsic::aarch64_sve_fcvtzs_x4:
6708 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6710 case Intrinsic::aarch64_sve_scvtf_x4:
6711 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6713 case Intrinsic::aarch64_sve_fcvtzu_x4:
6714 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6716 case Intrinsic::aarch64_sve_ucvtf_x4:
6717 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6719 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6720 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6722 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6723 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6725 case Intrinsic::aarch64_sve_sclamp_single_x2:
6727 Node->getValueType(0),
6728 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6729 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6730 SelectClamp(Node, 2,
Op);
6732 case Intrinsic::aarch64_sve_uclamp_single_x2:
6734 Node->getValueType(0),
6735 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6736 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6737 SelectClamp(Node, 2,
Op);
6739 case Intrinsic::aarch64_sve_fclamp_single_x2:
6741 Node->getValueType(0),
6742 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6743 AArch64::FCLAMP_VG2_2Z2Z_D}))
6744 SelectClamp(Node, 2,
Op);
6746 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6747 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6749 case Intrinsic::aarch64_sve_sclamp_single_x4:
6751 Node->getValueType(0),
6752 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6753 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6754 SelectClamp(Node, 4,
Op);
6756 case Intrinsic::aarch64_sve_uclamp_single_x4:
6758 Node->getValueType(0),
6759 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6760 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6761 SelectClamp(Node, 4,
Op);
6763 case Intrinsic::aarch64_sve_fclamp_single_x4:
6765 Node->getValueType(0),
6766 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6767 AArch64::FCLAMP_VG4_4Z4Z_D}))
6768 SelectClamp(Node, 4,
Op);
6770 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6771 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6773 case Intrinsic::aarch64_sve_add_single_x2:
6775 Node->getValueType(0),
6776 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6777 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6778 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6780 case Intrinsic::aarch64_sve_add_single_x4:
6782 Node->getValueType(0),
6783 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6784 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6785 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6787 case Intrinsic::aarch64_sve_zip_x2:
6789 Node->getValueType(0),
6790 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6791 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6792 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6794 case Intrinsic::aarch64_sve_zipq_x2:
6795 SelectUnaryMultiIntrinsic(Node, 2,
false,
6796 AArch64::ZIP_VG2_2ZZZ_Q);
6798 case Intrinsic::aarch64_sve_zip_x4:
6800 Node->getValueType(0),
6801 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6802 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6803 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6805 case Intrinsic::aarch64_sve_zipq_x4:
6806 SelectUnaryMultiIntrinsic(Node, 4,
true,
6807 AArch64::ZIP_VG4_4Z4Z_Q);
6809 case Intrinsic::aarch64_sve_uzp_x2:
6811 Node->getValueType(0),
6812 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6813 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6814 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6816 case Intrinsic::aarch64_sve_uzpq_x2:
6817 SelectUnaryMultiIntrinsic(Node, 2,
false,
6818 AArch64::UZP_VG2_2ZZZ_Q);
6820 case Intrinsic::aarch64_sve_uzp_x4:
6822 Node->getValueType(0),
6823 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6824 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6825 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6827 case Intrinsic::aarch64_sve_uzpq_x4:
6828 SelectUnaryMultiIntrinsic(Node, 4,
true,
6829 AArch64::UZP_VG4_4Z4Z_Q);
6831 case Intrinsic::aarch64_sve_sel_x2:
6833 Node->getValueType(0),
6834 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6835 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6836 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6838 case Intrinsic::aarch64_sve_sel_x4:
6840 Node->getValueType(0),
6841 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6842 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6843 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6845 case Intrinsic::aarch64_sve_frinta_x2:
6846 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6848 case Intrinsic::aarch64_sve_frinta_x4:
6849 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6851 case Intrinsic::aarch64_sve_frintm_x2:
6852 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6854 case Intrinsic::aarch64_sve_frintm_x4:
6855 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6857 case Intrinsic::aarch64_sve_frintn_x2:
6858 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6860 case Intrinsic::aarch64_sve_frintn_x4:
6861 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6863 case Intrinsic::aarch64_sve_frintp_x2:
6864 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6866 case Intrinsic::aarch64_sve_frintp_x4:
6867 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6869 case Intrinsic::aarch64_sve_sunpk_x2:
6871 Node->getValueType(0),
6872 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6873 AArch64::SUNPK_VG2_2ZZ_D}))
6874 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6876 case Intrinsic::aarch64_sve_uunpk_x2:
6878 Node->getValueType(0),
6879 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6880 AArch64::UUNPK_VG2_2ZZ_D}))
6881 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6883 case Intrinsic::aarch64_sve_sunpk_x4:
6885 Node->getValueType(0),
6886 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6887 AArch64::SUNPK_VG4_4Z2Z_D}))
6888 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6890 case Intrinsic::aarch64_sve_uunpk_x4:
6892 Node->getValueType(0),
6893 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6894 AArch64::UUNPK_VG4_4Z2Z_D}))
6895 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6897 case Intrinsic::aarch64_sve_pext_x2: {
6899 Node->getValueType(0),
6900 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6901 AArch64::PEXT_2PCI_D}))
6902 SelectPExtPair(Node,
Op);
6909 unsigned IntNo =
Node->getConstantOperandVal(1);
6910 if (
Node->getNumOperands() >= 3)
6911 VT =
Node->getOperand(2)->getValueType(0);
6915 case Intrinsic::aarch64_neon_st1x2: {
6916 if (VT == MVT::v8i8) {
6917 SelectStore(Node, 2, AArch64::ST1Twov8b);
6919 }
else if (VT == MVT::v16i8) {
6920 SelectStore(Node, 2, AArch64::ST1Twov16b);
6922 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6923 VT == MVT::v4bf16) {
6924 SelectStore(Node, 2, AArch64::ST1Twov4h);
6926 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6927 VT == MVT::v8bf16) {
6928 SelectStore(Node, 2, AArch64::ST1Twov8h);
6930 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6931 SelectStore(Node, 2, AArch64::ST1Twov2s);
6933 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6934 SelectStore(Node, 2, AArch64::ST1Twov4s);
6936 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6937 SelectStore(Node, 2, AArch64::ST1Twov2d);
6939 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6940 SelectStore(Node, 2, AArch64::ST1Twov1d);
6945 case Intrinsic::aarch64_neon_st1x3: {
6946 if (VT == MVT::v8i8) {
6947 SelectStore(Node, 3, AArch64::ST1Threev8b);
6949 }
else if (VT == MVT::v16i8) {
6950 SelectStore(Node, 3, AArch64::ST1Threev16b);
6952 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6953 VT == MVT::v4bf16) {
6954 SelectStore(Node, 3, AArch64::ST1Threev4h);
6956 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6957 VT == MVT::v8bf16) {
6958 SelectStore(Node, 3, AArch64::ST1Threev8h);
6960 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6961 SelectStore(Node, 3, AArch64::ST1Threev2s);
6963 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6964 SelectStore(Node, 3, AArch64::ST1Threev4s);
6966 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6967 SelectStore(Node, 3, AArch64::ST1Threev2d);
6969 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6970 SelectStore(Node, 3, AArch64::ST1Threev1d);
6975 case Intrinsic::aarch64_neon_st1x4: {
6976 if (VT == MVT::v8i8) {
6977 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6979 }
else if (VT == MVT::v16i8) {
6980 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6982 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6983 VT == MVT::v4bf16) {
6984 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6986 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6987 VT == MVT::v8bf16) {
6988 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6990 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6991 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6993 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6994 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6996 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6997 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6999 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7000 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7005 case Intrinsic::aarch64_neon_st2: {
7006 if (VT == MVT::v8i8) {
7007 SelectStore(Node, 2, AArch64::ST2Twov8b);
7009 }
else if (VT == MVT::v16i8) {
7010 SelectStore(Node, 2, AArch64::ST2Twov16b);
7012 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7013 VT == MVT::v4bf16) {
7014 SelectStore(Node, 2, AArch64::ST2Twov4h);
7016 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7017 VT == MVT::v8bf16) {
7018 SelectStore(Node, 2, AArch64::ST2Twov8h);
7020 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7021 SelectStore(Node, 2, AArch64::ST2Twov2s);
7023 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7024 SelectStore(Node, 2, AArch64::ST2Twov4s);
7026 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7027 SelectStore(Node, 2, AArch64::ST2Twov2d);
7029 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7030 SelectStore(Node, 2, AArch64::ST1Twov1d);
7035 case Intrinsic::aarch64_neon_st3: {
7036 if (VT == MVT::v8i8) {
7037 SelectStore(Node, 3, AArch64::ST3Threev8b);
7039 }
else if (VT == MVT::v16i8) {
7040 SelectStore(Node, 3, AArch64::ST3Threev16b);
7042 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7043 VT == MVT::v4bf16) {
7044 SelectStore(Node, 3, AArch64::ST3Threev4h);
7046 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7047 VT == MVT::v8bf16) {
7048 SelectStore(Node, 3, AArch64::ST3Threev8h);
7050 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7051 SelectStore(Node, 3, AArch64::ST3Threev2s);
7053 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7054 SelectStore(Node, 3, AArch64::ST3Threev4s);
7056 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7057 SelectStore(Node, 3, AArch64::ST3Threev2d);
7059 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7060 SelectStore(Node, 3, AArch64::ST1Threev1d);
7065 case Intrinsic::aarch64_neon_st4: {
7066 if (VT == MVT::v8i8) {
7067 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7069 }
else if (VT == MVT::v16i8) {
7070 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7072 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7073 VT == MVT::v4bf16) {
7074 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7076 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7077 VT == MVT::v8bf16) {
7078 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7080 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7081 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7083 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7084 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7086 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7087 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7089 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7090 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7095 case Intrinsic::aarch64_neon_st2lane: {
7096 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7097 SelectStoreLane(Node, 2, AArch64::ST2i8);
7099 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7100 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7101 SelectStoreLane(Node, 2, AArch64::ST2i16);
7103 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7105 SelectStoreLane(Node, 2, AArch64::ST2i32);
7107 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7109 SelectStoreLane(Node, 2, AArch64::ST2i64);
7114 case Intrinsic::aarch64_neon_st3lane: {
7115 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7116 SelectStoreLane(Node, 3, AArch64::ST3i8);
7118 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7119 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7120 SelectStoreLane(Node, 3, AArch64::ST3i16);
7122 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7124 SelectStoreLane(Node, 3, AArch64::ST3i32);
7126 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7128 SelectStoreLane(Node, 3, AArch64::ST3i64);
7133 case Intrinsic::aarch64_neon_st4lane: {
7134 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7135 SelectStoreLane(Node, 4, AArch64::ST4i8);
7137 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7138 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7139 SelectStoreLane(Node, 4, AArch64::ST4i16);
7141 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7143 SelectStoreLane(Node, 4, AArch64::ST4i32);
7145 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7147 SelectStoreLane(Node, 4, AArch64::ST4i64);
7152 case Intrinsic::aarch64_sve_st2q: {
7153 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7156 case Intrinsic::aarch64_sve_st3q: {
7157 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7160 case Intrinsic::aarch64_sve_st4q: {
7161 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7164 case Intrinsic::aarch64_sve_st2: {
7165 if (VT == MVT::nxv16i8) {
7166 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7168 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7169 VT == MVT::nxv8bf16) {
7170 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7172 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7173 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7175 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7176 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7181 case Intrinsic::aarch64_sve_st3: {
7182 if (VT == MVT::nxv16i8) {
7183 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7185 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7186 VT == MVT::nxv8bf16) {
7187 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7189 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7190 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7192 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7193 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7198 case Intrinsic::aarch64_sve_st4: {
7199 if (VT == MVT::nxv16i8) {
7200 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7202 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7203 VT == MVT::nxv8bf16) {
7204 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7206 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7207 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7209 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7210 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7218 case AArch64ISD::LD2post: {
7219 if (VT == MVT::v8i8) {
7220 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7222 }
else if (VT == MVT::v16i8) {
7223 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7225 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7226 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7228 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7229 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7231 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7232 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7234 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7235 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7237 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7238 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7240 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7241 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7246 case AArch64ISD::LD3post: {
7247 if (VT == MVT::v8i8) {
7248 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7250 }
else if (VT == MVT::v16i8) {
7251 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7253 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7254 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7256 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7257 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7259 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7260 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7262 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7263 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7265 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7266 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7268 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7269 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7274 case AArch64ISD::LD4post: {
7275 if (VT == MVT::v8i8) {
7276 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7278 }
else if (VT == MVT::v16i8) {
7279 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7281 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7282 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7284 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7285 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7287 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7288 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7290 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7291 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7293 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7294 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7296 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7297 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7302 case AArch64ISD::LD1x2post: {
7303 if (VT == MVT::v8i8) {
7304 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7306 }
else if (VT == MVT::v16i8) {
7307 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7309 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7310 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7312 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7313 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7315 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7316 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7318 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7319 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7321 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7322 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7324 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7325 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7330 case AArch64ISD::LD1x3post: {
7331 if (VT == MVT::v8i8) {
7332 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7334 }
else if (VT == MVT::v16i8) {
7335 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7337 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7338 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7340 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7341 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7343 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7344 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7346 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7347 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7349 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7350 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7352 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7353 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7358 case AArch64ISD::LD1x4post: {
7359 if (VT == MVT::v8i8) {
7360 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7362 }
else if (VT == MVT::v16i8) {
7363 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7365 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7366 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7368 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7369 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7371 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7372 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7374 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7375 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7377 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7378 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7380 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7381 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7386 case AArch64ISD::LD1DUPpost: {
7387 if (VT == MVT::v8i8) {
7388 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7390 }
else if (VT == MVT::v16i8) {
7391 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7393 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7394 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7396 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7397 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7399 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7400 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7402 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7403 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7405 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7406 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7408 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7409 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7414 case AArch64ISD::LD2DUPpost: {
7415 if (VT == MVT::v8i8) {
7416 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7418 }
else if (VT == MVT::v16i8) {
7419 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7421 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7422 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7424 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7425 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7427 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7428 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7430 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7431 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7433 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7434 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7436 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7437 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7442 case AArch64ISD::LD3DUPpost: {
7443 if (VT == MVT::v8i8) {
7444 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7446 }
else if (VT == MVT::v16i8) {
7447 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7449 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7450 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7452 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7453 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7455 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7456 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7458 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7459 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7461 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7462 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7464 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7465 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7470 case AArch64ISD::LD4DUPpost: {
7471 if (VT == MVT::v8i8) {
7472 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7474 }
else if (VT == MVT::v16i8) {
7475 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7477 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7478 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7480 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7481 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7483 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7484 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7486 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7487 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7489 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7490 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7492 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7493 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7498 case AArch64ISD::LD1LANEpost: {
7499 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7500 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7502 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7503 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7504 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7506 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7508 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7510 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7512 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7517 case AArch64ISD::LD2LANEpost: {
7518 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7519 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7521 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7522 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7523 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7525 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7527 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7529 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7531 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7536 case AArch64ISD::LD3LANEpost: {
7537 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7538 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7540 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7541 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7542 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7544 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7546 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7548 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7550 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7555 case AArch64ISD::LD4LANEpost: {
7556 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7557 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7559 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7560 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7561 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7563 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7565 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7567 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7569 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7574 case AArch64ISD::ST2post: {
7575 VT =
Node->getOperand(1).getValueType();
7576 if (VT == MVT::v8i8) {
7577 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7579 }
else if (VT == MVT::v16i8) {
7580 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7582 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7583 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7585 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7586 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7588 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7589 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7591 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7592 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7594 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7595 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7597 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7598 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7603 case AArch64ISD::ST3post: {
7604 VT =
Node->getOperand(1).getValueType();
7605 if (VT == MVT::v8i8) {
7606 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7608 }
else if (VT == MVT::v16i8) {
7609 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7611 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7612 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7614 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7615 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7617 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7618 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7620 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7621 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7623 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7624 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7626 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7627 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7632 case AArch64ISD::ST4post: {
7633 VT =
Node->getOperand(1).getValueType();
7634 if (VT == MVT::v8i8) {
7635 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7637 }
else if (VT == MVT::v16i8) {
7638 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7640 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7641 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7643 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7644 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7646 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7647 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7649 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7650 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7652 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7653 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7655 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7656 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7661 case AArch64ISD::ST1x2post: {
7662 VT =
Node->getOperand(1).getValueType();
7663 if (VT == MVT::v8i8) {
7664 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7666 }
else if (VT == MVT::v16i8) {
7667 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7669 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7670 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7672 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7673 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7675 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7676 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7678 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7679 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7681 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7682 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7684 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7685 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7690 case AArch64ISD::ST1x3post: {
7691 VT =
Node->getOperand(1).getValueType();
7692 if (VT == MVT::v8i8) {
7693 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7695 }
else if (VT == MVT::v16i8) {
7696 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7698 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7699 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7701 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7702 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7704 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7705 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7707 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7708 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7710 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7711 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7713 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7714 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7719 case AArch64ISD::ST1x4post: {
7720 VT =
Node->getOperand(1).getValueType();
7721 if (VT == MVT::v8i8) {
7722 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7724 }
else if (VT == MVT::v16i8) {
7725 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7727 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7728 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7730 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7731 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7733 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7734 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7736 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7737 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7739 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7740 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7742 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7743 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7748 case AArch64ISD::ST2LANEpost: {
7749 VT =
Node->getOperand(1).getValueType();
7750 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7751 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7753 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7754 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7755 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7757 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7759 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7761 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7763 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7768 case AArch64ISD::ST3LANEpost: {
7769 VT =
Node->getOperand(1).getValueType();
7770 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7771 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7773 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7774 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7775 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7777 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7779 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7781 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7783 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7788 case AArch64ISD::ST4LANEpost: {
7789 VT =
Node->getOperand(1).getValueType();
7790 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7791 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7793 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7794 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7795 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7797 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7799 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7801 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7803 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7818 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7830 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7834 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7835 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7857 return MemIntr->getMemoryVT();
7864 DataVT =
Load->getValueType(0);
7866 DataVT =
Load->getValueType(0);
7868 DataVT =
Store->getValue().getValueType();
7870 DataVT =
Store->getValue().getValueType();
7877 const unsigned Opcode = Root->
getOpcode();
7881 case AArch64ISD::LD1_MERGE_ZERO:
7882 case AArch64ISD::LD1S_MERGE_ZERO:
7883 case AArch64ISD::LDNF1_MERGE_ZERO:
7884 case AArch64ISD::LDNF1S_MERGE_ZERO:
7886 case AArch64ISD::ST1_PRED:
7898 case Intrinsic::aarch64_sme_ldr:
7899 case Intrinsic::aarch64_sme_str:
7900 return MVT::nxv16i8;
7901 case Intrinsic::aarch64_sve_prf:
7906 case Intrinsic::aarch64_sve_ld2_sret:
7907 case Intrinsic::aarch64_sve_ld2q_sret:
7910 case Intrinsic::aarch64_sve_st2q:
7913 case Intrinsic::aarch64_sve_ld3_sret:
7914 case Intrinsic::aarch64_sve_ld3q_sret:
7917 case Intrinsic::aarch64_sve_st3q:
7920 case Intrinsic::aarch64_sve_ld4_sret:
7921 case Intrinsic::aarch64_sve_ld4q_sret:
7924 case Intrinsic::aarch64_sve_st4q:
7927 case Intrinsic::aarch64_sve_ld1_pn_x2:
7928 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7931 case Intrinsic::aarch64_sve_ld1_pn_x4:
7932 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7935 case Intrinsic::aarch64_sve_st1_pn_x2:
7936 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7939 case Intrinsic::aarch64_sve_st1_pn_x4:
7940 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7943 case Intrinsic::aarch64_sve_ld1udq:
7944 case Intrinsic::aarch64_sve_st1dq:
7945 return EVT(MVT::nxv1i64);
7946 case Intrinsic::aarch64_sve_ld1uwq:
7947 case Intrinsic::aarch64_sve_st1wq:
7948 return EVT(MVT::nxv1i32);
7955template <
int64_t Min,
int64_t Max>
7956bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root,
SDValue N,
7960 const DataLayout &
DL = CurDAG->getDataLayout();
7961 const MachineFrameInfo &MFI = MF->getFrameInfo();
7969 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7983 int64_t MulImm = std::numeric_limits<int64_t>::max();
7987 int64_t ByteOffset =
C->getSExtValue();
7988 const auto KnownVScale =
7991 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7994 MulImm = ByteOffset / KnownVScale;
8001 if ((MulImm % MemWidthBytes) != 0)
8004 int64_t
Offset = MulImm / MemWidthBytes;
8008 Base =
N.getOperand(0);
8017 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8023bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(
SDValue N,
unsigned Scale,
8042 int64_t ImmOff =
C->getSExtValue();
8043 unsigned Size = 1 << Scale;
8052 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8054 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8065 if (
C->getZExtValue() == Scale) {
8074bool AArch64DAGToDAGISel::SelectAllActivePredicate(
SDValue N) {
8075 const AArch64TargetLowering *TLI =
8076 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8081bool AArch64DAGToDAGISel::SelectAnyPredicate(
SDValue N) {
8082 return N.getValueType().isScalableVectorOf(MVT::i1);
8085bool AArch64DAGToDAGISel::SelectSMETileSlice(
SDValue N,
unsigned MaxSize,
8090 int64_t ImmOff =
C->getSExtValue();
8091 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8092 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8097 if (
SDValue C = MatchConstantOffset(
N)) {
8104 if (CurDAG->isBaseWithConstantOffset(
N)) {
8105 if (
SDValue C = MatchConstantOffset(
N.getOperand(1))) {
8106 Base =
N.getOperand(0);
8114 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8118bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P,
SDValue N,
8138 uint64_t LowerBound = 0, UpperBound = 64;
8156 if (CN->getAPIntValue().uge(LowerBound) &&
8157 CN->getAPIntValue().ult(UpperBound)) {
8159 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8167template <
bool MatchCBB>
8174 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8176 Reg =
N.getOperand(0);
8178 SDLoc(
N), MVT::i32);
8186 Reg =
N.getOperand(0);
8206SDValue AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode &
N) {
8207 EVT VT =
N.getValueType(0);
8218 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8227 unsigned CondCode = CC->getZExtValue();
8230 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8232 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8233 else if (VT == MVT::f32)
8234 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8235 else if (VT == MVT::f64)
8236 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8244 if (TVal == CmpLHS && FVal == CmpRHS)
8249 if (TVal == CmpLHS && FVal == CmpRHS)
8258 unsigned Opc = getOpc(VT, isMax);
8264 if (!CFP || CFP->getValueAPF().isNaN())
8269 if (CFP->isZero() && !
N.getFlags().hasNoSignedZeros())
8275 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8281 return SDValue(CurDAG->getMachineNode(
Opc,
DL, VT, CmpLHS, CmpRHS), 0);
8284void AArch64DAGToDAGISel::PreprocessISelDAG() {
8285 bool MadeChange =
false;
8291 switch (
N.getOpcode()) {
8293 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8294 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8295 ScalarTy ==
N.getOperand(0).getValueType())
8300 case AArch64ISD::CSEL:
8301 Result = tryFoldCselToFMaxMin(
N);
8308 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8314 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(&
N, 0), Result);
8320 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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64RegisterInfo * getRegisterInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N) const
Register matchRegisterName(StringRef RegName) const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static const fltSemantics & IEEEhalf()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
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).
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.