25#include "llvm/IR/IntrinsicsAArch64.h"
36#define DEBUG_TYPE "aarch64-isel"
37#define PASS_NAME "AArch64 Instruction Selection"
40#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
41#pragma inline_depth(0)
57 AArch64DAGToDAGISel() =
delete;
69 void PreprocessISelDAG()
override;
73 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
75 std::vector<SDValue> &OutOps)
override;
77 template <
signed Low,
signed High,
signed Scale>
80 template <
signed Low,
signed High>
88 return SelectShiftedRegister(
N,
false,
Reg, Shift);
91 return SelectShiftedRegister(
N,
true,
Reg, Shift);
93 template <
unsigned ShiftW
idth>
97 return SelectAddrModeIndexed7S(
N, 1,
Base, OffImm);
100 return SelectAddrModeIndexed7S(
N, 2,
Base, OffImm);
103 return SelectAddrModeIndexed7S(
N, 4,
Base, OffImm);
106 return SelectAddrModeIndexed7S(
N, 8,
Base, OffImm);
109 return SelectAddrModeIndexed7S(
N, 16,
Base, OffImm);
112 return SelectAddrModeIndexedBitWidth(
N,
true, 9, 16,
Base, OffImm);
115 return SelectAddrModeIndexedBitWidth(
N,
false, 6, 16,
Base, OffImm);
118 return SelectAddrModeIndexed(
N, 1,
Base, OffImm);
121 return SelectAddrModeIndexed(
N, 2,
Base, OffImm);
124 return SelectAddrModeIndexed(
N, 4,
Base, OffImm);
127 return SelectAddrModeIndexed(
N, 8,
Base, OffImm);
130 return SelectAddrModeIndexed(
N, 16,
Base, OffImm);
133 return SelectAddrModeUnscaled(
N, 1,
Base, OffImm);
136 return SelectAddrModeUnscaled(
N, 2,
Base, OffImm);
139 return SelectAddrModeUnscaled(
N, 4,
Base, OffImm);
142 return SelectAddrModeUnscaled(
N, 8,
Base, OffImm);
145 return SelectAddrModeUnscaled(
N, 16,
Base, OffImm);
147 template <
unsigned Size,
unsigned Max>
151 bool Found = SelectAddrModeIndexed(
N,
Size,
Base, OffImm);
154 int64_t
C = CI->getSExtValue();
162 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i64);
169 return SelectAddrModeWRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
175 return SelectAddrModeXRO(
N, Width / 8,
Base,
Offset, SignExtend, DoShift);
180 N =
N->getOperand(0);
184 EVT VT =
N->getValueType(0);
185 EVT LVT =
N->getOperand(0).getValueType();
186 unsigned Index =
N->getConstantOperandVal(1);
190 Res =
N->getOperand(0);
195 if (
N.getOpcode() != AArch64ISD::VLSHR)
198 EVT VT =
Op.getValueType();
199 unsigned ShtAmt =
N->getConstantOperandVal(1);
204 if (
Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
206 Op.getOperand(1).getConstantOperandVal(0)
207 <<
Op.getOperand(1).getConstantOperandVal(1));
208 else if (
Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
211 Op.getOperand(1).getConstantOperandVal(0));
215 if (
Imm != 1ULL << (ShtAmt - 1))
218 Res1 =
Op.getOperand(0);
219 Res2 = CurDAG->getTargetConstant(ShtAmt,
SDLoc(
N), MVT::i32);
223 bool SelectDupZeroOrUndef(
SDValue N) {
224 switch(
N->getOpcode()) {
228 case AArch64ISD::DUP:
230 auto Opnd0 =
N->getOperand(0);
244 bool SelectAny(
SDValue) {
return true; }
247 switch(
N->getOpcode()) {
248 case AArch64ISD::DUP:
250 auto Opnd0 =
N->getOperand(0);
262 template <MVT::SimpleValueType VT,
bool Negate>
264 return SelectSVEAddSubImm(
N, VT,
Imm, Shift, Negate);
267 template <MVT::SimpleValueType VT,
bool Negate>
269 return SelectSVEAddSubSSatImm(
N, VT,
Imm, Shift, Negate);
272 template <MVT::SimpleValueType VT>
274 return SelectSVECpyDupImm(
N, VT,
Imm, Shift);
277 template <MVT::SimpleValueType VT,
bool Invert = false>
279 return SelectSVELogicalImm(
N, VT,
Imm, Invert);
282 template <MVT::SimpleValueType VT>
284 return SelectSVEArithImm(
N, VT,
Imm);
287 template <
unsigned Low,
unsigned High,
bool AllowSaturation = false>
289 return SelectSVEShiftImm(
N,
Low,
High, AllowSaturation,
Imm);
296 EVT EltVT =
N->getValueType(0).getVectorElementType();
297 return SelectSVEShiftImm(
N->getOperand(0), 1,
303 template<
signed Min,
signed Max,
signed Scale,
bool Shift>
310 MulImm = 1LL << MulImm;
312 if ((MulImm % std::abs(Scale)) != 0)
316 if ((MulImm >= Min) && (MulImm <= Max)) {
317 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
324 template <
signed Max,
signed Scale>
331 if (MulImm >= 0 && MulImm <= Max) {
333 Imm = CurDAG->getTargetConstant(MulImm,
SDLoc(
N), MVT::i32);
340 template <
unsigned BaseReg,
unsigned Max>
348 Imm = CurDAG->getRegister(BaseReg +
C, MVT::Other);
371 const unsigned SubRegs[]);
373 void SelectTable(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
bool isExt);
375 bool tryIndexedLoad(
SDNode *
N);
377 void SelectPtrauthAuth(
SDNode *
N);
378 void SelectPtrauthResign(
SDNode *
N);
379 void SelectPtrauthResignWithPC(
SDNode *
N);
381 bool trySelectStackSlotTagP(
SDNode *
N);
384 void SelectLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
386 void SelectPostLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Opc,
388 void SelectLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
389 void SelectPostLoadLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
390 void SelectPredicatedLoad(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
391 unsigned Opc_rr,
unsigned Opc_ri,
392 bool IsIntr =
false);
393 void SelectContiguousMultiVectorLoad(
SDNode *
N,
unsigned NumVecs,
394 unsigned Scale,
unsigned Opc_ri,
396 void SelectDestructiveMultiIntrinsic(
SDNode *
N,
unsigned NumVecs,
397 bool IsZmMulti,
unsigned Opcode,
398 bool HasPred =
false);
400 void SelectWhilePair(
SDNode *
N,
unsigned Opc);
401 void SelectCVTIntrinsic(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
402 void SelectCVTIntrinsicFP8(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
403 void SelectClamp(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
404 void SelectUnaryMultiIntrinsic(
SDNode *
N,
unsigned NumOutVecs,
405 bool IsTupleInput,
unsigned Opc);
406 void SelectFrintFromVT(
SDNode *
N,
unsigned NumVecs,
unsigned Opcode);
408 template <
unsigned MaxIdx,
unsigned Scale>
409 void SelectMultiVectorMove(
SDNode *
N,
unsigned NumVecs,
unsigned BaseReg,
411 void SelectMultiVectorMoveZ(
SDNode *
N,
unsigned NumVecs,
412 unsigned Op,
unsigned MaxIdx,
unsigned Scale,
413 unsigned BaseReg = 0);
415 template <
int64_t Min,
int64_t Max>
419 template <
unsigned Scale>
421 return SelectSVERegRegAddrMode(
N, Scale,
Base,
Offset);
424 void SelectMultiVectorLutiLane(
SDNode *
Node,
unsigned NumOutVecs,
426 void SelectMultiVectorLuti6LaneX4(
SDNode *
Node,
unsigned NumIndexVecs);
428 void SelectMultiVectorLuti(
SDNode *
Node,
unsigned NumOutVecs,
unsigned Opc,
431 template <
unsigned MaxIdx,
unsigned Scale>
436 void SelectStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
437 void SelectPostStore(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
438 void SelectStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
439 void SelectPostStoreLane(
SDNode *
N,
unsigned NumVecs,
unsigned Opc);
440 void SelectPredicatedStore(
SDNode *
N,
unsigned NumVecs,
unsigned Scale,
441 unsigned Opc_rr,
unsigned Opc_ri);
442 std::tuple<unsigned, SDValue, SDValue>
443 findAddrModeSVELoadStore(
SDNode *
N,
unsigned Opc_rr,
unsigned Opc_ri,
447 bool tryBitfieldExtractOp(
SDNode *
N);
448 bool tryBitfieldInsertOp(
SDNode *
N);
449 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
450 bool tryShiftAmountMod(
SDNode *
N);
452 bool tryReadRegister(
SDNode *
N);
453 bool tryWriteRegister(
SDNode *
N);
455 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
456 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
460 bool tryFoldCselToFMaxMin(
SDNode *
N);
463#include "AArch64GenDAGISel.inc"
471 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
473 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
486 bool isWorthNegatingImm(
SDValue V)
const;
487 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
488 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
489 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
492 template<
unsigned RegW
idth>
494 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
496 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
498 template <
unsigned RegW
idth>
500 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
502 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
504 template<
unsigned RegW
idth>
506 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
512 template <
unsigned FloatW
idth>
514 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
520 bool SelectCMP_SWAP(
SDNode *
N);
552 bool SelectAllActivePredicate(
SDValue N);
557 template <
bool MatchCBB>
567 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
571char AArch64DAGToDAGISelLegacy::ID = 0;
577 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
583 auto getFloatVT = [&](
EVT VT) {
585 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
586 return VT.changeElementType(*(DAG.
getContext()),
587 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
592 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
593 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
597 EVT OrigVT =
N.getValueType(0);
606 Imm =
C->getZExtValue();
623 return N->getOpcode() ==
Opc &&
634 return Imm == ImmExpected;
639 assert(RegWidth == 32 || RegWidth == 64);
641 return APInt(RegWidth,
649 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
650 if (
N->getOpcode() == AArch64ISD::NVCAST ||
652 N =
N->getOperand(0);
653 unsigned SplatWidth =
N.getScalarValueSizeInBits();
654 if (
N.getOpcode() == AArch64ISD::FMOV)
656 if (
N->getOpcode() == AArch64ISD::MOVI)
657 return APInt(SplatWidth,
N.getConstantOperandVal(0));
658 if (
N->getOpcode() == AArch64ISD::MOVIshift)
659 return APInt(SplatWidth,
N.getConstantOperandVal(0)
660 <<
N.getConstantOperandVal(1));
661 if (
N->getOpcode() == AArch64ISD::MVNIshift)
662 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
663 <<
N.getConstantOperandVal(1));
664 if (
N->getOpcode() == AArch64ISD::MOVIedit)
666 N.getConstantOperandVal(0)));
667 if (
N->getOpcode() == AArch64ISD::DUP)
669 return Const->getAPIntValue().trunc(SplatWidth);
672 return SplatVal.
trunc(SplatWidth);
680static std::optional<APInt>
682 unsigned SplatWidth =
N.getScalarValueSizeInBits();
684 if (SplatVal->getBitWidth() <= SplatWidth)
686 if (SplatVal->isSplat(SplatWidth))
687 return SplatVal->trunc(SplatWidth);
692bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
699 ImmVal->getZExtValue(), Encoding))
702 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
706bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(SDValue
N, SDValue &
Imm,
709 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
710 N.getValueType().getScalarType().getSimpleVT(),
716bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(SDValue
N,
719 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal,
Imm);
723bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(SDValue
N, SDValue &
Imm) {
728 int64_t ImmVal = ImmAPIntVal->getSExtValue();
729 if (ImmVal < -128 || ImmVal > 127)
732 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
736bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(SDValue
N, SDValue &
Imm) {
741 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
745 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
749bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
751 std::vector<SDValue> &OutOps) {
752 switch(ConstraintID) {
755 case InlineAsm::ConstraintCode::m:
756 case InlineAsm::ConstraintCode::o:
757 case InlineAsm::ConstraintCode::Q:
764 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
766 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
767 dl,
Op.getValueType(),
769 OutOps.push_back(NewOp);
775template <
unsigned ShiftW
idth>
776bool AArch64DAGToDAGISel::SelectShiftMask(SDValue
N, SDValue &ShAmt) {
782 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
794 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
797 (
Imm % ShiftWidth == 0)) {
805 if (
N.getOpcode() ==
ISD::SUB &&
N.hasOneUse() &&
806 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
809 (
Imm % ShiftWidth == 0)) {
811 EVT VT =
N.getValueType();
812 unsigned NegOpc = (ShiftWidth == 32) ? AArch64::SUBWrr : AArch64::SUBXrr;
813 unsigned ZeroReg = (ShiftWidth == 32) ? AArch64::WZR : AArch64::XZR;
815 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, VT);
817 CurDAG->getMachineNode(NegOpc,
DL, VT, Zero,
N.getOperand(1));
818 ShAmt = SDValue(Neg, 0);
825 if (
N.getOpcode() ==
ISD::SUB &&
N.hasOneUse() &&
826 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
829 (
Imm % ShiftWidth == ShiftWidth - 1)) {
831 EVT VT =
N.getValueType();
832 unsigned NotOpc = (ShiftWidth == 32) ? AArch64::ORNWrr : AArch64::ORNXrr;
833 unsigned ZeroReg = (ShiftWidth == 32) ? AArch64::WZR : AArch64::XZR;
835 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, VT);
837 CurDAG->getMachineNode(NotOpc,
DL, VT, Zero,
N.getOperand(1));
838 ShAmt = SDValue(
Not, 0);
849bool AArch64DAGToDAGISel::SelectArithImmed(SDValue
N, SDValue &Val,
859 uint64_t Immed =
N.getNode()->getAsZExtVal();
869 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
870 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
876bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue
N, SDValue &Val,
887 uint64_t Immed =
N.getNode()->getAsZExtVal();
895 if (
N.getValueType() == MVT::i32)
896 Immed = ~((uint32_t)Immed) + 1;
898 Immed = ~Immed + 1ULL;
899 if (Immed & 0xFFFFFFFFFF000000ULL)
902 Immed &= 0xFFFFFFULL;
903 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
910 switch (
N.getOpcode()) {
936 unsigned ShiftVal = CSD->getZExtValue();
954bool AArch64DAGToDAGISel::isWorthFoldingAddr(SDValue V,
unsigned Size)
const {
957 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
962 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
970 const SDValue
LHS =
V.getOperand(0);
971 const SDValue
RHS =
V.getOperand(1);
984bool AArch64DAGToDAGISel::SelectShiftedRegisterFromAnd(SDValue
N, SDValue &
Reg,
986 EVT VT =
N.getValueType();
987 if (VT != MVT::i32 && VT != MVT::i64)
990 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
992 SDValue
LHS =
N.getOperand(0);
996 unsigned LHSOpcode =
LHS->getOpcode();
1010 unsigned LowZBits, MaskLen;
1014 unsigned BitWidth =
N.getValueSizeInBits();
1017 unsigned NewShiftOp;
1021 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
1024 NewShiftC = LowZBits - ShiftAmtC;
1025 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1031 NewShiftC = LowZBits + ShiftAmtC;
1044 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1046 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
1050 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
1051 SDValue BitWidthMinus1 = CurDAG->getTargetConstant(
BitWidth - 1,
DL, VT);
1052 Reg = SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
1053 NewShiftAmt, BitWidthMinus1),
1056 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
1070 SrcVT =
N.getOperand(0).getValueType();
1072 if (!IsLoadStore && SrcVT == MVT::i8)
1074 else if (!IsLoadStore && SrcVT == MVT::i16)
1076 else if (SrcVT == MVT::i32)
1078 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1083 EVT SrcVT =
N.getOperand(0).getValueType();
1084 if (!IsLoadStore && SrcVT == MVT::i8)
1086 else if (!IsLoadStore && SrcVT == MVT::i16)
1088 else if (SrcVT == MVT::i32)
1090 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1115bool AArch64DAGToDAGISel::isWorthNegatingImm(SDValue V)
const {
1118 EVT VT =
V.getValueType();
1119 assert((VT == MVT::i32 || VT == MVT::i64) &&
"invalid type");
1130 return NewCost.
size() < OrigCost.
size();
1137bool AArch64DAGToDAGISel::isWorthFoldingALU(SDValue V,
bool LSL)
const {
1140 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1145 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1146 V.getConstantOperandVal(1) <= 4 &&
1159bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue
N,
bool AllowROR,
1160 SDValue &
Reg, SDValue &Shift) {
1161 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1171 unsigned BitSize =
N.getValueSizeInBits();
1172 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1175 Reg =
N.getOperand(0);
1176 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1177 return isWorthFoldingALU(
N,
true);
1188 if (
N.getValueType() == MVT::i32)
1196template<
signed Low,
signed High,
signed Scale>
1197bool AArch64DAGToDAGISel::SelectRDVLImm(SDValue
N, SDValue &
Imm) {
1202 if ((MulImm % std::abs(Scale)) == 0) {
1203 int64_t RDVLImm = MulImm / Scale;
1204 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1205 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1214template <
signed Low,
signed High>
1215bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue
N, SDValue &
Imm) {
1220 if (MulImm >=
Low && MulImm <=
High) {
1221 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1230bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue
N, SDValue &
Reg,
1232 unsigned ShiftVal = 0;
1247 Reg =
N.getOperand(0).getOperand(0);
1257 SDValue
Op =
N.getOperand(0);
1259 Op =
Op->getOperand(0);
1261 Op.getOperand(0).getValueType().isFixedLengthVector())
1265 Reg =
N.getOperand(0);
1269 auto isDef32 = [](SDValue
N) {
1270 unsigned Opc =
N.getOpcode();
1283 Reg.getValueType() == MVT::i32 &&
1294 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1296 return isWorthFoldingALU(
N);
1301bool AArch64DAGToDAGISel::SelectArithUXTXRegister(SDValue
N, SDValue &
Reg,
1303 unsigned ShiftVal = 0;
1317 Reg =
N.getOperand(0);
1318 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1320 return isWorthFoldingALU(
N);
1329 for (
auto *
User :
N->users()) {
1356bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue
N,
bool IsSignedImm,
1357 unsigned BW,
unsigned Size,
1361 const DataLayout &
DL = CurDAG->getDataLayout();
1362 const TargetLowering *TLI = getTargetLowering();
1366 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1372 if (CurDAG->isBaseWithConstantOffset(
N)) {
1375 int64_t RHSC =
RHS->getSExtValue();
1377 int64_t
Range = 0x1LL << (BW - 1);
1379 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1380 RHSC < (
Range << Scale)) {
1381 Base =
N.getOperand(0);
1386 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1395 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1396 Base =
N.getOperand(0);
1401 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1412 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1419bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue
N,
unsigned Size,
1420 SDValue &
Base, SDValue &OffImm) {
1422 const DataLayout &
DL = CurDAG->getDataLayout();
1423 const TargetLowering *TLI = getTargetLowering();
1427 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1432 GlobalAddressSDNode *GAN =
1434 Base =
N.getOperand(0);
1444 if (CurDAG->isBaseWithConstantOffset(
N)) {
1446 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1449 Base =
N.getOperand(0);
1454 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1462 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1470 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1479bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue
N,
unsigned Size,
1482 if (!CurDAG->isBaseWithConstantOffset(
N))
1485 int64_t RHSC =
RHS->getSExtValue();
1486 if (RHSC >= -256 && RHSC < 256) {
1487 Base =
N.getOperand(0);
1490 const TargetLowering *TLI = getTargetLowering();
1491 Base = CurDAG->getTargetFrameIndex(
1494 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1504 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1511bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue
N,
unsigned Size,
1512 bool WantExtend, SDValue &
Offset,
1513 SDValue &SignExtend) {
1531 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1537 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1540 return isWorthFoldingAddr(
N,
Size);
1543bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue
N,
unsigned Size,
1545 SDValue &SignExtend,
1549 SDValue
LHS =
N.getOperand(0);
1550 SDValue
RHS =
N.getOperand(1);
1561 const SDNode *
Node =
N.getNode();
1562 for (SDNode *UI :
Node->users()) {
1568 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1571 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1574 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1579 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1582 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1587 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1591 if (IsExtendedRegisterWorthFolding &&
1598 if (isWorthFoldingAddr(
LHS,
Size))
1603 if (IsExtendedRegisterWorthFolding &&
1610 if (isWorthFoldingAddr(
RHS,
Size))
1622 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1625 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1627 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1628 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1632bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue
N,
unsigned Size,
1634 SDValue &SignExtend,
1638 SDValue
LHS =
N.getOperand(0);
1639 SDValue
RHS =
N.getOperand(1);
1645 const SDNode *
Node =
N.getNode();
1646 for (SDNode *UI :
Node->users()) {
1663 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1673 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1674 SDValue MOVIV = SDValue(MOVI, 0);
1680 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1683 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1686 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1691 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1694 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1701 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1702 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1708 static const unsigned RegClassIDs[] = {
1709 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1710 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1711 AArch64::dsub2, AArch64::dsub3};
1717 static const unsigned RegClassIDs[] = {
1718 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1719 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1720 AArch64::qsub2, AArch64::qsub3};
1726 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1727 AArch64::ZPR3RegClassID,
1728 AArch64::ZPR4RegClassID};
1729 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1730 AArch64::zsub2, AArch64::zsub3};
1740 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1741 AArch64::ZPR4Mul4RegClassID};
1742 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1743 AArch64::zsub2, AArch64::zsub3};
1748 const unsigned RegClassIDs[],
1749 const unsigned SubRegs[]) {
1752 if (Regs.
size() == 1)
1763 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1766 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1767 Ops.push_back(Regs[i]);
1768 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1772 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1773 return SDValue(
N, 0);
1776void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1779 EVT VT =
N->getValueType(0);
1781 unsigned ExtOff = isExt;
1784 unsigned Vec0Off = ExtOff + 1;
1790 Ops.push_back(
N->getOperand(1));
1791 Ops.push_back(RegSeq);
1792 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1793 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1796static std::tuple<SDValue, SDValue>
1817 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1822 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1824 return std::make_tuple(
1829void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1832 SDValue Val =
N->getOperand(1);
1833 SDValue AUTKey =
N->getOperand(2);
1834 SDValue AUTDisc =
N->getOperand(3);
1837 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1839 SDValue AUTAddrDisc, AUTConstDisc;
1840 std::tie(AUTConstDisc, AUTAddrDisc) =
1844 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1846 if (
N->getNumOperands() > 4)
1847 Ops.push_back(
N->getOperand(4));
1850 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1851 ReplaceNode(
N, AUT);
1853 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1854 AArch64::X16, Val, SDValue());
1855 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.
getValue(1)};
1857 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1858 ReplaceNode(
N, AUT);
1862void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1872 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1877 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1878 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1880 SDValue AUTAddrDisc, AUTConstDisc;
1881 std::tie(AUTConstDisc, AUTAddrDisc) =
1884 SDValue PACAddrDisc, PACConstDisc;
1885 std::tie(PACConstDisc, PACAddrDisc) =
1888 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1889 AArch64::X16, Val, SDValue());
1892 SDValue Addend =
N->getOperand(OffsetBase + 6);
1893 SDValue IncomingChain =
N->getOperand(0);
1894 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1895 PACKey, PACConstDisc, PACAddrDisc,
1896 Addend, IncomingChain, X16Copy.
getValue(1)};
1898 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1899 MVT::i64, MVT::Other,
Ops);
1900 ReplaceNode(
N, AUTRELLOADPAC);
1902 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1903 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1905 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1906 ReplaceNode(
N, AUTPAC);
1910void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *
N) {
1922 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1923 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1925 SDValue PACAddrDisc, PACConstDisc;
1926 std::tie(PACConstDisc, PACAddrDisc) =
1929 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1930 AArch64::X17, Val, SDValue());
1931 SDValue X16Copy = CurDAG->getCopyToReg(
1932 CurDAG->getEntryNode(),
DL, AArch64::X16, AUTDisc, X17Copy.
getValue(1));
1933 SDValue X15Copy = CurDAG->getCopyToReg(
1934 CurDAG->getEntryNode(),
DL, AArch64::X15, AUTPC, X16Copy.
getValue(1));
1936 SDValue
Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1939 CurDAG->getMachineNode(AArch64::AUTPCPAC,
DL, MVT::i64,
Ops);
1940 ReplaceNode(
N, AUTPCPAC);
1943bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1945 if (
LD->isUnindexed())
1947 EVT VT =
LD->getMemoryVT();
1948 EVT DstVT =
N->getValueType(0);
1952 int OffsetVal = (int)
OffsetOp->getZExtValue();
1957 unsigned Opcode = 0;
1960 bool InsertTo64 =
false;
1963 (!Subtarget->
isLittleEndian() || (Subtarget->requiresStrictAlign() &&
1966 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1967 else if (VT == MVT::i32) {
1969 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1971 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1973 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1979 }
else if (VT == MVT::i16) {
1981 if (DstVT == MVT::i64)
1982 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1984 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1986 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1987 InsertTo64 = DstVT == MVT::i64;
1992 }
else if (VT == MVT::i8) {
1994 if (DstVT == MVT::i64)
1995 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1997 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1999 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
2000 InsertTo64 = DstVT == MVT::i64;
2005 }
else if (VT == MVT::f16) {
2006 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2007 }
else if (VT == MVT::bf16) {
2008 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2009 }
else if (VT == MVT::f32) {
2010 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
2011 }
else if (VT == MVT::f64 || (VT.
is64BitVector() && !UseLd1)) {
2012 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
2014 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
2016 if (IsPre || OffsetVal != 8)
2020 Opcode = AArch64::LD1Onev8b_POST;
2023 Opcode = AArch64::LD1Onev4h_POST;
2026 Opcode = AArch64::LD1Onev2s_POST;
2029 Opcode = AArch64::LD1Onev1d_POST;
2035 if (IsPre || OffsetVal != 16)
2039 Opcode = AArch64::LD1Onev16b_POST;
2042 Opcode = AArch64::LD1Onev8h_POST;
2045 Opcode = AArch64::LD1Onev4s_POST;
2048 Opcode = AArch64::LD1Onev2d_POST;
2055 SDValue Chain =
LD->getChain();
2056 SDValue
Base =
LD->getBasePtr();
2059 SDValue
Offset = UseLd1 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
2060 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
2062 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
2070 SDValue LoadedVal = SDValue(Res, 1);
2072 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
2073 LoadedVal = SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
2074 MVT::i64, LoadedVal, SubReg),
2078 ReplaceUses(SDValue(
N, 0), LoadedVal);
2079 ReplaceUses(SDValue(
N, 1), SDValue(Res, 0));
2080 ReplaceUses(SDValue(
N, 2), SDValue(Res, 2));
2081 CurDAG->RemoveDeadNode(
N);
2085void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
2086 unsigned SubRegIdx) {
2088 EVT VT =
N->getValueType(0);
2091 SDValue
Ops[] = {
N->getOperand(2),
2094 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2096 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2097 SDValue SuperReg = SDValue(Ld, 0);
2098 for (
unsigned i = 0; i < NumVecs; ++i)
2099 ReplaceUses(SDValue(
N, i),
2100 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2102 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2107 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2111 CurDAG->RemoveDeadNode(
N);
2114void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2115 unsigned Opc,
unsigned SubRegIdx) {
2117 EVT VT =
N->getValueType(0);
2120 SDValue
Ops[] = {
N->getOperand(1),
2124 const EVT ResTys[] = {MVT::i64,
2125 MVT::Untyped, MVT::Other};
2127 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2130 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2133 SDValue SuperReg = SDValue(Ld, 1);
2135 ReplaceUses(SDValue(
N, 0), SuperReg);
2137 for (
unsigned i = 0; i < NumVecs; ++i)
2138 ReplaceUses(SDValue(
N, i),
2139 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2146 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2147 CurDAG->RemoveDeadNode(
N);
2153std::tuple<unsigned, SDValue, SDValue>
2154AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2156 const SDValue &OldBase,
2157 const SDValue &OldOffset,
2159 SDValue NewBase = OldBase;
2160 SDValue NewOffset = OldOffset;
2162 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2163 N, OldBase, NewBase, NewOffset);
2167 const bool IsRegReg =
2168 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2171 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2184template <SelectTypeKind Kind>
2196 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2201 if (EltVT != MVT::i1)
2205 if (EltVT == MVT::bf16)
2207 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2237void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2240 if (
Imm->getZExtValue() > 1)
2244 EVT VT =
N->getValueType(0);
2245 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2246 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2247 SDValue SuperReg = SDValue(WhilePair, 0);
2249 for (
unsigned I = 0;
I < 2; ++
I)
2250 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2251 AArch64::psub0 +
I,
DL, VT, SuperReg));
2253 CurDAG->RemoveDeadNode(
N);
2256void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2258 EVT VT =
N->getValueType(0);
2260 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2262 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2263 SDValue SuperReg = SDValue(WhilePair, 0);
2265 for (
unsigned I = 0;
I < 2; ++
I)
2266 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2267 AArch64::psub0 +
I,
DL, VT, SuperReg));
2269 CurDAG->RemoveDeadNode(
N);
2272void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2274 EVT VT =
N->getValueType(0);
2276 SDValue
Ops = createZTuple(Regs);
2278 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2279 SDValue SuperReg = SDValue(Intrinsic, 0);
2280 for (
unsigned i = 0; i < NumVecs; ++i)
2281 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2282 AArch64::zsub0 + i,
DL, VT, SuperReg));
2284 CurDAG->RemoveDeadNode(
N);
2287void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2290 EVT VT =
N->getValueType(0);
2292 Ops.push_back(
N->getOperand(0));
2295 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2296 SDValue SuperReg = SDValue(Instruction, 0);
2298 for (
unsigned i = 0; i < NumVecs; ++i)
2299 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2300 AArch64::zsub0 + i,
DL, VT, SuperReg));
2303 unsigned ChainIdx = NumVecs;
2304 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Instruction, 1));
2305 CurDAG->RemoveDeadNode(
N);
2308void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2313 assert(Opcode != 0 &&
"Unexpected opcode");
2316 EVT VT =
N->getValueType(0);
2317 SDUse *OpsIter =
N->op_begin() + 1;
2320 auto GetMultiVecOperand = [&]() {
2323 return createZMulTuple(Regs);
2327 Ops.push_back(*OpsIter++);
2329 Ops.push_back(GetMultiVecOperand());
2331 Ops.push_back(GetMultiVecOperand());
2333 Ops.push_back(*OpsIter++);
2336 Ops.append(OpsIter,
N->op_end());
2338 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2339 SDValue SuperReg = SDValue(Intrinsic, 0);
2340 for (
unsigned i = 0; i < NumVecs; ++i)
2341 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2342 AArch64::zsub0 + i,
DL, VT, SuperReg));
2344 CurDAG->RemoveDeadNode(
N);
2347void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2348 unsigned Scale,
unsigned Opc_ri,
2349 unsigned Opc_rr,
bool IsIntr) {
2350 assert(Scale < 5 &&
"Invalid scaling value.");
2352 EVT VT =
N->getValueType(0);
2359 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2360 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2362 SDValue
Ops[] = {
N->getOperand(IsIntr ? 2 : 1),
2366 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2368 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2369 SDValue SuperReg = SDValue(
Load, 0);
2370 for (
unsigned i = 0; i < NumVecs; ++i)
2371 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2372 AArch64::zsub0 + i,
DL, VT, SuperReg));
2375 unsigned ChainIdx = NumVecs;
2376 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2377 CurDAG->RemoveDeadNode(
N);
2380void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2385 assert(Scale < 4 &&
"Invalid scaling value.");
2387 EVT VT =
N->getValueType(0);
2392 SDValue
Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
2395 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2397 SDValue
Ops[] = {PNg,
2401 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2403 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2404 SDValue SuperReg = SDValue(
Load, 0);
2405 for (
unsigned i = 0; i < NumVecs; ++i)
2406 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2407 AArch64::zsub0 + i,
DL, VT, SuperReg));
2410 unsigned ChainIdx = NumVecs;
2411 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2412 CurDAG->RemoveDeadNode(
N);
2415void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2417 if (
N->getValueType(0) != MVT::nxv4f32)
2419 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2422void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2423 unsigned NumOutVecs,
2427 if (
Imm->getZExtValue() > MaxImm)
2431 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2434 SDValue Chain =
Node->getOperand(0);
2435 SDValue
Ops[] = {ZtValue,
Node->getOperand(3),
Node->getOperand(4), Chain};
2437 EVT VT =
Node->getValueType(0);
2440 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2441 SDValue SuperReg = SDValue(Instruction, 0);
2443 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2444 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2445 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2448 unsigned ChainIdx = NumOutVecs;
2449 ReplaceUses(SDValue(Node, ChainIdx), SDValue(Instruction, 1));
2450 CurDAG->RemoveDeadNode(Node);
2453void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2454 unsigned NumIndexVecs) {
2455 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2456 "unexpected number of index vectors");
2458 constexpr unsigned FirstIndexOp = 3;
2459 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2461 if (!
Imm ||
Imm->getZExtValue() > 1)
2467 unsigned Lane =
Imm->getZExtValue();
2468 unsigned IndexOp = FirstIndexOp;
2469 if (NumIndexVecs == 3)
2472 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2473 SDValue IndexTuple =
2474 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2475 SDValue
Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2478 EVT VT =
Node->getValueType(0);
2480 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2481 SDValue SuperReg = SDValue(Instruction, 0);
2483 for (
unsigned I = 0;
I < 4; ++
I)
2484 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2485 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2487 CurDAG->RemoveDeadNode(Node);
2490void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2491 unsigned NumOutVecs,
2493 unsigned NumInVecs) {
2494 assert((NumInVecs == 2 || NumInVecs == 3) &&
2495 "unexpected number of input vectors");
2498 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2502 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2503 SDValue
Ops[] = {ZtValue, ZTuple,
Node->getOperand(0)};
2506 EVT VT =
Node->getValueType(0);
2509 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2510 SDValue SuperReg = SDValue(Instruction, 0);
2512 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2513 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2514 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2516 ReplaceUses(SDValue(Node, NumOutVecs), SDValue(Instruction, 1));
2517 CurDAG->RemoveDeadNode(Node);
2520void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2523 EVT VT =
N->getValueType(0);
2526 SDValue Zd = createZMulTuple(Regs);
2527 SDValue Zn =
N->getOperand(1 + NumVecs);
2528 SDValue Zm =
N->getOperand(2 + NumVecs);
2530 SDValue
Ops[] = {Zd, Zn, Zm};
2533 SDValue SuperReg = SDValue(Intrinsic, 0);
2534 for (
unsigned i = 0; i < NumVecs; ++i)
2535 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2536 AArch64::zsub0 + i,
DL, VT, SuperReg));
2538 CurDAG->RemoveDeadNode(
N);
2568template <
unsigned MaxIdx,
unsigned Scale>
2569void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2570 unsigned BaseReg,
unsigned Op) {
2571 unsigned TileNum = 0;
2572 if (BaseReg != AArch64::ZA)
2573 TileNum =
N->getConstantOperandVal(2);
2579 if (BaseReg == AArch64::ZA)
2584 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2588 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2590 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2592 EVT VT =
N->getValueType(0);
2593 for (
unsigned I = 0;
I < NumVecs; ++
I)
2594 ReplaceUses(SDValue(
N,
I),
2595 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2598 unsigned ChainIdx = NumVecs;
2599 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2600 CurDAG->RemoveDeadNode(
N);
2603void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2604 unsigned Op,
unsigned MaxIdx,
2605 unsigned Scale,
unsigned BaseReg) {
2610 if (BaseReg != AArch64::ZA)
2614 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2621 if (BaseReg != AArch64::ZA )
2622 Ops.push_back(
N->getOperand(2));
2625 Ops.push_back(
N->getOperand(0));
2626 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2628 EVT VT =
N->getValueType(0);
2629 for (
unsigned I = 0;
I < NumVecs; ++
I)
2630 ReplaceUses(SDValue(
N,
I),
2631 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2635 unsigned ChainIdx = NumVecs;
2636 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2637 CurDAG->RemoveDeadNode(
N);
2640void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2641 unsigned NumOutVecs,
2645 EVT VT =
N->getValueType(0);
2646 unsigned NumInVecs =
N->getNumOperands() - 1;
2650 assert((NumInVecs == 2 || NumInVecs == 4) &&
2651 "Don't know how to handle multi-register input!");
2653 Ops.push_back(createZMulTuple(Regs));
2656 for (
unsigned I = 0;
I < NumInVecs;
I++)
2657 Ops.push_back(
N->getOperand(1 +
I));
2660 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2661 SDValue SuperReg = SDValue(Res, 0);
2663 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2664 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2665 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2666 CurDAG->RemoveDeadNode(
N);
2669void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2672 EVT VT =
N->getOperand(2)->getValueType(0);
2680 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2689void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2690 unsigned Scale,
unsigned Opc_rr,
2696 SDValue RegSeq = createZTuple(Regs);
2702 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2703 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2709 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2718void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2721 EVT VT =
N->getOperand(2)->getValueType(0);
2722 const EVT ResTys[] = {MVT::i64,
2730 SDValue
Ops[] = {RegSeq,
2734 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2752 SDValue operator()(SDValue V64Reg) {
2778void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2781 EVT VT =
N->getValueType(0);
2793 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2795 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2797 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2799 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2800 SDValue SuperReg = SDValue(Ld, 0);
2803 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2804 AArch64::qsub2, AArch64::qsub3 };
2805 for (
unsigned i = 0; i < NumVecs; ++i) {
2806 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2809 ReplaceUses(SDValue(
N, i), NV);
2812 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2813 CurDAG->RemoveDeadNode(
N);
2816void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2819 EVT VT =
N->getValueType(0);
2831 const EVT ResTys[] = {MVT::i64,
2834 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2836 SDValue
Ops[] = {RegSeq,
2837 CurDAG->getTargetConstant(LaneNo, dl,
2842 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2845 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2848 SDValue SuperReg = SDValue(Ld, 1);
2850 ReplaceUses(SDValue(
N, 0),
2854 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2855 AArch64::qsub2, AArch64::qsub3 };
2856 for (
unsigned i = 0; i < NumVecs; ++i) {
2857 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2861 ReplaceUses(SDValue(
N, i), NV);
2866 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2867 CurDAG->RemoveDeadNode(
N);
2870void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2873 EVT VT =
N->getOperand(2)->getValueType(0);
2885 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2887 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2889 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2898void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2901 EVT VT =
N->getOperand(2)->getValueType(0);
2913 const EVT ResTys[] = {MVT::i64,
2916 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2918 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2922 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2933 unsigned &LSB,
unsigned &MSB,
2934 unsigned NumberOfIgnoredLowBits,
2935 bool BiggerPattern) {
2937 "N must be a AND operation to call this function");
2939 EVT VT =
N->getValueType(0);
2944 assert((VT == MVT::i32 || VT == MVT::i64) &&
2945 "Type checking must have been done before calling this function");
2959 const SDNode *Op0 =
N->getOperand(0).getNode();
2966 if (AndImm & (AndImm + 1))
2969 bool ClampMSB =
false;
2989 ClampMSB = (VT == MVT::i32);
2990 }
else if (BiggerPattern) {
2996 Opd0 =
N->getOperand(0);
3002 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
3005 <<
": Found large shift immediate, this should not happen\n"));
3019 MSB = MSB > 31 ? 31 : MSB;
3021 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3026 SDValue &Opd0,
unsigned &Immr,
3030 EVT VT =
N->getValueType(0);
3032 assert((VT == MVT::i32 || VT == MVT::i64) &&
3033 "Type checking must have been done before calling this function");
3037 Op =
Op->getOperand(0);
3038 VT =
Op->getValueType(0);
3047 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3051 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
3052 Opd0 =
Op.getOperand(0);
3054 Imms = ShiftImm + Width - 1;
3082 Opd0 =
N->getOperand(0).getOperand(0);
3092 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3099 unsigned &Immr,
unsigned &Imms,
3100 bool BiggerPattern) {
3102 "N must be a SHR/SRA operation to call this function");
3104 EVT VT =
N->getValueType(0);
3109 assert((VT == MVT::i32 || VT == MVT::i64) &&
3110 "Type checking must have been done before calling this function");
3120 Opd0 =
N->getOperand(0).getOperand(0);
3121 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3127 Opd0 =
N->getOperand(0).getOperand(0);
3130 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3131 }
else if (BiggerPattern) {
3135 Opd0 =
N->getOperand(0);
3144 <<
": Found large shift immediate, this should not happen\n"));
3153 "bad amount in shift node!");
3154 int immr = SrlImm - ShlImm;
3159 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3161 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3166 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3167 unsigned NumberOfIgnoredLowBits = 0,
3168 bool BiggerPattern =
false) {
3169 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3172 switch (
N->getOpcode()) {
3174 if (!
N->isMachineOpcode())
3179 NumberOfIgnoredLowBits, BiggerPattern);
3188 unsigned NOpc =
N->getMachineOpcode();
3192 case AArch64::SBFMWri:
3193 case AArch64::UBFMWri:
3194 case AArch64::SBFMXri:
3195 case AArch64::UBFMXri:
3197 Opd0 =
N->getOperand(0);
3198 Immr =
N->getConstantOperandVal(1);
3199 Imms =
N->getConstantOperandVal(2);
3206bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3207 unsigned Opc, Immr, Imms;
3212 EVT VT =
N->getValueType(0);
3217 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3218 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3219 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3221 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3222 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3223 MVT::i32, SDValue(BFM, 0));
3228 SDValue
Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3229 CurDAG->getTargetConstant(Imms, dl, VT)};
3230 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3239 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3240 assert((VT == MVT::i32 || VT == MVT::i64) &&
3241 "i32 or i64 mask type expected!");
3245 APInt SignificantDstMask =
3249 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3250 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3283 APInt OpUsefulBits(UsefulBits);
3287 OpUsefulBits <<= MSB -
Imm + 1;
3292 OpUsefulBits <<=
Imm;
3294 OpUsefulBits <<= MSB + 1;
3303 UsefulBits &= OpUsefulBits;
3320 APInt Mask(UsefulBits);
3321 Mask.clearAllBits();
3329 Mask.lshrInPlace(ShiftAmt);
3335 Mask.lshrInPlace(ShiftAmt);
3351 APInt OpUsefulBits(UsefulBits);
3365 OpUsefulBits <<= Width;
3368 if (
Op.getOperand(1) == Orig) {
3370 Mask = ResultUsefulBits & OpUsefulBits;
3374 if (
Op.getOperand(0) == Orig)
3376 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3382 OpUsefulBits <<= Width;
3384 OpUsefulBits <<= LSB;
3386 if (
Op.getOperand(1) == Orig) {
3388 Mask = ResultUsefulBits & OpUsefulBits;
3389 Mask.lshrInPlace(LSB);
3392 if (
Op.getOperand(0) == Orig)
3393 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3410 case AArch64::ANDSWri:
3411 case AArch64::ANDSXri:
3412 case AArch64::ANDWri:
3413 case AArch64::ANDXri:
3417 case AArch64::UBFMWri:
3418 case AArch64::UBFMXri:
3421 case AArch64::ORRWrs:
3422 case AArch64::ORRXrs:
3427 case AArch64::BFMWri:
3428 case AArch64::BFMXri:
3431 case AArch64::STRBBui:
3432 case AArch64::STURBBi:
3438 case AArch64::STRHHui:
3439 case AArch64::STURHHi:
3452 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3454 UsefulBits =
APInt(Bitwidth, 0);
3463 UsersUsefulBits |= UsefulBitsForUse;
3468 UsefulBits &= UsersUsefulBits;
3478 EVT VT =
Op.getValueType();
3481 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3484 if (ShlAmount > 0) {
3487 UBFMOpc, dl, VT,
Op,
3492 assert(ShlAmount < 0 &&
"expected right shift");
3493 int ShrAmount = -ShlAmount;
3506 SDValue &Src,
int &DstLSB,
3513 SDValue &Src,
int &DstLSB,
3519 bool BiggerPattern,
SDValue &Src,
3520 int &DstLSB,
int &Width) {
3521 EVT VT =
Op.getValueType();
3534 switch (
Op.getOpcode()) {
3539 NonZeroBits, Src, DstLSB, Width);
3542 NonZeroBits, Src, DstLSB, Width);
3555 EVT VT =
Op.getValueType();
3556 assert((VT == MVT::i32 || VT == MVT::i64) &&
3557 "Caller guarantees VT is one of i32 or i64");
3570 assert((~AndImm & NonZeroBits) == 0 &&
3571 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3600 if (!BiggerPattern && !AndOp0.
hasOneUse())
3619 <<
"Found large Width in bit-field-positioning -- this indicates no "
3620 "proper combining / constant folding was performed\n");
3629 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3644 "Op.getNode() should be a SHL node to call this function");
3646 "Op.getNode() should shift ShlImm to call this function");
3653 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3677 EVT VT =
Op.getValueType();
3678 assert((VT == MVT::i32 || VT == MVT::i64) &&
3679 "Caller guarantees that type is i32 or i64");
3686 if (!BiggerPattern && !
Op.hasOneUse())
3695 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3703 assert(VT == MVT::i32 || VT == MVT::i64);
3714 EVT VT =
N->getValueType(0);
3715 if (VT != MVT::i32 && VT != MVT::i64)
3733 if (!
And.hasOneUse() ||
3750 if ((OrImm & NotKnownZero) != 0) {
3762 unsigned ImmS = Width - 1;
3768 bool IsBFI = LSB != 0;
3773 unsigned OrChunks = 0, BFIChunks = 0;
3774 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3775 if (((OrImm >> Shift) & 0xFFFF) != 0)
3777 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3780 if (BFIChunks > OrChunks)
3786 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3794 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3803 if (!Dst.hasOneUse())
3806 EVT VT = Dst.getValueType();
3807 assert((VT == MVT::i32 || VT == MVT::i64) &&
3808 "Caller should guarantee that VT is one of i32 or i64");
3836 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3837 unsigned MaskWidth =
3840 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3846 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3847 ShiftedOperand =
SDValue(UBFMNode, 0);
3876 const bool BiggerPattern) {
3877 EVT VT =
N->getValueType(0);
3878 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3879 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3880 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3881 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3882 assert((VT == MVT::i32 || VT == MVT::i64) &&
3883 "Expect result type to be i32 or i64 since N is combinable to BFM");
3890 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3893 if (BiggerPattern) {
3916 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3978 EVT VT =
N->getValueType(0);
3979 if (VT != MVT::i32 && VT != MVT::i64)
3987 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3988 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
4008 for (
int I = 0;
I < 4; ++
I) {
4011 unsigned ImmR, ImmS;
4012 bool BiggerPattern =
I / 2;
4013 SDValue OrOpd0Val =
N->getOperand(
I % 2);
4015 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
4021 NumberOfIgnoredLowBits, BiggerPattern)) {
4024 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
4025 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
4030 Width = ImmS - ImmR + 1;
4041 Src, DstLSB, Width)) {
4049 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
4059 APInt BitsToBeInserted =
4062 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4086 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4119 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4121 if (Src->hasOneUse() &&
4124 Src = Src->getOperand(0);
4134 unsigned ImmS = Width - 1;
4140 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4148bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4157 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4170bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4174 EVT VT =
N->getValueType(0);
4175 if (VT != MVT::i32 && VT != MVT::i64)
4181 Op0, DstLSB, Width))
4187 unsigned ImmS = Width - 1;
4190 SDValue
Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4191 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4192 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4193 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4199bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4200 EVT VT =
N->getValueType(0);
4203 switch (
N->getOpcode()) {
4205 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4208 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4211 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4214 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4222 if (VT == MVT::i32) {
4225 }
else if (VT == MVT::i64) {
4231 SDValue ShiftAmt =
N->getOperand(1);
4233 SDValue NewShiftAmt;
4251 (Add0Imm %
Size == 0)) {
4257 if (SubVT == MVT::i32) {
4258 NegOpc = AArch64::SUBWrr;
4259 ZeroReg = AArch64::WZR;
4261 assert(SubVT == MVT::i64);
4262 NegOpc = AArch64::SUBXrr;
4263 ZeroReg = AArch64::XZR;
4266 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4267 MachineSDNode *Neg =
4268 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4269 NewShiftAmt = SDValue(Neg, 0);
4277 if (SubVT == MVT::i32) {
4278 NotOpc = AArch64::ORNWrr;
4279 ZeroReg = AArch64::WZR;
4281 assert(SubVT == MVT::i64);
4282 NotOpc = AArch64::ORNXrr;
4283 ZeroReg = AArch64::XZR;
4286 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4287 MachineSDNode *
Not =
4288 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4289 NewShiftAmt = SDValue(
Not, 0);
4310 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4311 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4312 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4313 NewShiftAmt, SubReg);
4314 NewShiftAmt = SDValue(Ext, 0);
4317 SDValue
Ops[] = {
N->getOperand(0), NewShiftAmt};
4318 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4325 bool isReciprocal) {
4328 FVal = CN->getValueAPF();
4331 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4341 if (
unsigned FBits =
4354 bool isReciprocal) {
4355 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4356 N.getValueType().getScalarSizeInBits() ==
4357 N.getOperand(0).getValueType().getScalarSizeInBits())
4358 N =
N.getOperand(0);
4360 auto ImmToFloat = [RegWidth](
APInt Imm) {
4374 switch (
N->getOpcode()) {
4375 case AArch64ISD::MOVIshift:
4376 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4377 <<
N.getConstantOperandVal(1)));
4379 case AArch64ISD::FMOV:
4380 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4382 case AArch64ISD::DUP:
4384 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4392 if (
unsigned FBits =
4401bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue
N, SDValue &FixedPos,
4402 unsigned RegWidth) {
4407bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(SDValue
N, SDValue &FixedPos,
4408 unsigned RegWidth) {
4410 CurDAG,
N, FixedPos, RegWidth,
false);
4413bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(SDValue
N,
4415 unsigned RegWidth) {
4417 CurDAG,
N, FixedPos, RegWidth,
true);
4420bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(SDValue
N,
4422 unsigned RegWidth) {
4432 RegString.
split(Fields,
':');
4434 if (Fields.
size() == 1)
4438 &&
"Invalid number of fields in read register string");
4441 bool AllIntFields =
true;
4445 AllIntFields &= !
Field.getAsInteger(10, IntField);
4446 Ops.push_back(IntField);
4450 "Unexpected non-integer value in special register string.");
4455 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4463bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4465 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4468 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4470 unsigned Opcode64Bit = AArch64::MRS;
4475 const auto *TheReg =
4476 AArch64SysReg::lookupSysRegByName(RegString->getString());
4477 if (TheReg && TheReg->Readable &&
4478 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4479 Imm = TheReg->Encoding;
4485 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4486 Opcode64Bit = AArch64::ADR;
4495 RegString->getString());
4496 unsigned PseudoOp = 0;
4497 if (AArch64::GPR64RegClass.
contains(PReg))
4498 PseudoOp = AArch64::READ_REGISTER_GPR64;
4499 else if (AArch64::FPR64RegClass.
contains(PReg))
4500 PseudoOp = AArch64::READ_REGISTER_FPR64;
4501 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4502 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4503 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4512 SDValue InChain =
N->getOperand(0);
4513 SDValue SysRegImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
4514 if (!ReadIs128Bit) {
4515 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4516 {SysRegImm, InChain});
4518 SDNode *MRRS = CurDAG->getMachineNode(
4520 {MVT::Untyped , MVT::Other },
4521 {SysRegImm, InChain});
4525 SDValue
Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4527 SDValue
Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4529 SDValue OutChain = SDValue(MRRS, 1);
4531 ReplaceUses(SDValue(
N, 0),
Lo);
4532 ReplaceUses(SDValue(
N, 1),
Hi);
4533 ReplaceUses(SDValue(
N, 2), OutChain);
4542bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4544 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4547 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4549 if (!WriteIs128Bit) {
4555 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4558 "Expected a constant integer expression.");
4559 unsigned Reg = PMapper->Encoding;
4560 uint64_t Immed =
N->getConstantOperandVal(2);
4561 CurDAG->SelectNodeTo(
4562 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4563 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4569 if (trySelectPState(
4570 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4571 AArch64::MSRpstateImm4))
4573 if (trySelectPState(
4574 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4575 AArch64::MSRpstateImm1))
4584 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4585 if (TheReg && TheReg->Writeable &&
4586 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4587 Imm = TheReg->Encoding;
4597 RegString->getString());
4598 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4599 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4600 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4601 N->getOperand(2).getValueType() == MVT::i64) {
4603 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4604 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4605 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4606 MVT::Other, {RegOp,
Copy});
4607 ReplaceUses(SDValue(
N, 0), SDValue(FakeUse, 0));
4608 CurDAG->RemoveDeadNode(
N);
4616 if (!WriteIs128Bit) {
4617 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4618 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4619 N->getOperand(2), InChain);
4623 SDNode *Pair = CurDAG->getMachineNode(
4624 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4625 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4628 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4630 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4632 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4633 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4634 SDValue(Pair, 0), InChain);
4641bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4646 if (Subtarget->hasLSE())
return false;
4648 if (MemTy == MVT::i8)
4649 Opcode = AArch64::CMP_SWAP_8;
4650 else if (MemTy == MVT::i16)
4651 Opcode = AArch64::CMP_SWAP_16;
4652 else if (MemTy == MVT::i32)
4653 Opcode = AArch64::CMP_SWAP_32;
4654 else if (MemTy == MVT::i64)
4655 Opcode = AArch64::CMP_SWAP_64;
4659 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4660 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4662 SDNode *CmpSwap = CurDAG->getMachineNode(
4664 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4669 ReplaceUses(SDValue(
N, 0), SDValue(CmpSwap, 0));
4670 ReplaceUses(SDValue(
N, 1), SDValue(CmpSwap, 2));
4671 CurDAG->RemoveDeadNode(
N);
4677AArch64DAGToDAGISel::decodeMemoryHintFlags(MachineMemOperand *MMO)
const {
4678 int MemoryHint = -1;
4681 return AArch64MemoryHint::NONE;
4694bool AArch64DAGToDAGISel::isAtomicMemoryHint(SDNode *
N,
4699bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue
N, MVT VT, SDValue &
Imm,
4700 SDValue &Shift,
bool Negate) {
4707 return SelectSVEAddSubImm(SDLoc(
N), Val, VT,
Imm, Shift, Negate);
4710bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4711 SDValue &
Imm, SDValue &Shift,
4719 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4726 if ((Val & ~0xff) == 0) {
4727 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4732 if ((Val & ~0xff00) == 0) {
4733 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4745bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(SDValue
N, MVT VT,
4746 SDValue &
Imm, SDValue &Shift,
4769 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4770 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4777 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4778 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4782 if (Val <= 65280 && Val % 256 == 0) {
4783 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4784 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4795bool AArch64DAGToDAGISel::SelectSVECpyDupImm(SDValue
N, MVT VT, SDValue &
Imm,
4805 int32_t ImmVal, ShiftVal;
4810 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4811 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4815bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDValue
N, SDValue &
Imm) {
4817 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(),
Imm);
4821bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4824 if (ImmVal >= -128 && ImmVal < 128) {
4825 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4831bool AArch64DAGToDAGISel::SelectSVEArithImm(SDValue
N, MVT VT, SDValue &
Imm) {
4833 uint64_t ImmVal = CNode->getZExtValue();
4843 ImmVal &= 0xFFFFFFFF;
4852 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4859bool AArch64DAGToDAGISel::SelectSVELogicalImm(SDValue
N, MVT VT, SDValue &
Imm,
4863 ImmVal = CI->getZExtValue();
4865 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4876 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4885bool AArch64DAGToDAGISel::SelectSVEShiftImm(SDValue
N,
uint64_t Low,
4889 uint64_t ImmVal = CN->getZExtValue();
4896 if (ImmVal >
High) {
4897 if (!AllowSaturation)
4902 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4909bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4917 SDValue IRG_SP =
N->getOperand(2);
4923 const TargetLowering *TLI = getTargetLowering();
4926 SDValue FiOp = CurDAG->getTargetFrameIndex(
4928 int TagOffset =
N->getConstantOperandVal(3);
4930 SDNode *
Out = CurDAG->getMachineNode(
4931 AArch64::TAGPstack,
DL, MVT::i64,
4932 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4933 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4934 ReplaceNode(
N, Out);
4938void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4940 "llvm.aarch64.tagp third argument must be an immediate");
4941 if (trySelectStackSlotTagP(
N))
4948 int TagOffset =
N->getConstantOperandVal(3);
4949 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4950 {
N->getOperand(1),
N->getOperand(2)});
4951 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4952 {SDValue(N1, 0),
N->getOperand(2)});
4953 SDNode *N3 = CurDAG->getMachineNode(
4954 AArch64::ADDG,
DL, MVT::i64,
4955 {SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4956 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4960bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4964 if (
N->getConstantOperandVal(2) != 0)
4966 if (!
N->getOperand(0).isUndef())
4970 EVT VT =
N->getValueType(0);
4971 EVT InVT =
N->getOperand(1).getValueType();
4982 "Expected to insert into a packed scalable vector!");
4985 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4986 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4987 N->getOperand(1), RC));
4991bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4995 if (
N->getConstantOperandVal(1) != 0)
4999 EVT VT =
N->getValueType(0);
5000 EVT InVT =
N->getOperand(0).getValueType();
5011 "Expected to extract from a packed scalable vector!");
5014 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
5015 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
5016 N->getOperand(0), RC));
5020bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
5023 SDValue N0 =
N->getOperand(0);
5026 EVT VT =
N->getValueType(0);
5039 (Subtarget->hasSVE2() ||
5040 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
5041 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
5044 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
5048 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
5049 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
5050 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
5057 bool IsXOROperand =
true;
5059 IsXOROperand =
false;
5065 APInt ShlAmt, ShrAmt;
5073 if (!IsXOROperand) {
5074 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
5075 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
5076 SDValue MOVIV = SDValue(MOV, 0);
5078 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5079 SDNode *SubRegToReg =
5080 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
5083 R2 = SDValue(SubRegToReg, 0);
5091 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5092 AArch64::XAR_ZZZI_D})) {
5093 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5118 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5128 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5136 bool IsXOROperand =
true;
5138 IsXOROperand =
false;
5141 R1 =
XOR.getOperand(0);
5142 R2 =
XOR.getOperand(1);
5148 SDValue
Imm = CurDAG->getTargetConstant(
5152 if (ShAmt + HsAmt != VTSizeInBits)
5155 if (!IsXOROperand) {
5156 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
5158 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5159 SDValue MOVIV = SDValue(MOV, 0);
5167 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5172 SDValue UndefQ = SDValue(
5173 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5174 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5176 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5179 if (
R2.getValueType() == VT)
5180 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5185 SDValue SubReg = CurDAG->getTargetConstant(
5188 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5193 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5199 SDNode *XAR =
nullptr;
5203 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5204 AArch64::XAR_ZZZI_D}))
5205 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5207 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5210 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5216 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5217 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5218 SDValue(XAR, 0), ZSub);
5220 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5221 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5222 SDValue(Q, 0), DSub);
5224 SDValue SubReg = CurDAG->getTargetConstant(
5227 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5228 SDValue(XAR, 0), SubReg);
5231 ReplaceNode(
N, XAR);
5238 assert(VT == MVT::i32 || VT == MVT::i64);
5240 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5243void AArch64DAGToDAGISel::Select(SDNode *Node) {
5245 if (
Node->isMachineOpcode()) {
5247 Node->setNodeId(-1);
5252 EVT VT =
Node->getValueType(0);
5254 switch (
Node->getOpcode()) {
5259 if (SelectCMP_SWAP(Node))
5264 case AArch64ISD::MRRS:
5265 if (tryReadRegister(Node))
5270 case AArch64ISD::MSRR:
5271 if (tryWriteRegister(Node))
5278 if (tryIndexedLoad(Node))
5287 if (tryBitfieldExtractOp(Node))
5289 if (tryBitfieldInsertInZeroOp(Node))
5294 if (tryShiftAmountMod(Node))
5299 if (tryBitfieldInsertOp(Node))
5301 if (trySelectXAR(Node))
5306 if (trySelectCastScalableToFixedLengthVector(Node))
5312 if (trySelectCastFixedLengthToScalableVector(Node))
5317 case AArch64ISD::CSEL:
5318 if (tryFoldCselToFMaxMin(Node))
5326 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5337 const TargetLowering *TLI = getTargetLowering();
5338 SDValue TFI = CurDAG->getTargetFrameIndex(
5341 SDValue
Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5342 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5343 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5347 unsigned IntNo =
Node->getConstantOperandVal(1);
5351 case Intrinsic::aarch64_gcsss: {
5353 SDValue Chain =
Node->getOperand(0);
5354 SDValue Val =
Node->getOperand(2);
5355 SDValue
Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5357 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5358 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5359 MVT::Other, Zero, SDValue(SS1, 0));
5360 ReplaceNode(Node, SS2);
5363 case Intrinsic::aarch64_ldaxp:
5364 case Intrinsic::aarch64_ldxp: {
5366 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5367 SDValue MemAddr =
Node->getOperand(2);
5369 SDValue Chain =
Node->getOperand(0);
5371 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5372 MVT::Other, MemAddr, Chain);
5375 MachineMemOperand *MemOp =
5378 ReplaceNode(Node, Ld);
5381 case Intrinsic::aarch64_stlxp:
5382 case Intrinsic::aarch64_stxp: {
5384 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5386 SDValue Chain =
Node->getOperand(0);
5387 SDValue ValLo =
Node->getOperand(2);
5388 SDValue ValHi =
Node->getOperand(3);
5389 SDValue MemAddr =
Node->getOperand(4);
5392 SDValue
Ops[] = {ValLo, ValHi, MemAddr, Chain};
5394 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5396 MachineMemOperand *MemOp =
5400 ReplaceNode(Node, St);
5403 case Intrinsic::aarch64_neon_ld1x2:
5404 if (VT == MVT::v8i8) {
5405 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5407 }
else if (VT == MVT::v16i8) {
5408 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5410 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5411 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5413 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5414 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5416 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5417 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5419 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5420 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5422 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5423 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5425 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5426 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5430 case Intrinsic::aarch64_neon_ld1x3:
5431 if (VT == MVT::v8i8) {
5432 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5434 }
else if (VT == MVT::v16i8) {
5435 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5437 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5438 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5440 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5441 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5443 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5444 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5446 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5447 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5449 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5450 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5452 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5453 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5457 case Intrinsic::aarch64_neon_ld1x4:
5458 if (VT == MVT::v8i8) {
5459 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5461 }
else if (VT == MVT::v16i8) {
5462 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5464 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5465 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5467 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5468 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5470 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5471 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5473 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5474 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5476 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5477 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5479 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5480 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5484 case Intrinsic::aarch64_neon_ld2:
5485 if (VT == MVT::v8i8) {
5486 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5488 }
else if (VT == MVT::v16i8) {
5489 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5491 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5492 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5494 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5495 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5497 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5498 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5500 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5501 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5503 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5504 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5506 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5507 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5511 case Intrinsic::aarch64_neon_ld3:
5512 if (VT == MVT::v8i8) {
5513 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5515 }
else if (VT == MVT::v16i8) {
5516 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5518 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5519 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5521 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5522 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5524 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5525 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5527 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5528 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5530 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5531 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5533 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5534 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5538 case Intrinsic::aarch64_neon_ld4:
5539 if (VT == MVT::v8i8) {
5540 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5542 }
else if (VT == MVT::v16i8) {
5543 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5545 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5546 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5548 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5549 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5551 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5552 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5554 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5555 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5557 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5558 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5560 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5561 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5565 case Intrinsic::aarch64_neon_ld2r:
5566 if (VT == MVT::v8i8) {
5567 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5569 }
else if (VT == MVT::v16i8) {
5570 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5572 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5573 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5575 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5576 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5578 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5579 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5581 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5582 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5584 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5585 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5587 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5588 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5592 case Intrinsic::aarch64_neon_ld3r:
5593 if (VT == MVT::v8i8) {
5594 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5596 }
else if (VT == MVT::v16i8) {
5597 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5599 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5600 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5602 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5603 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5605 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5606 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5608 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5609 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5611 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5612 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5614 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5615 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5619 case Intrinsic::aarch64_neon_ld4r:
5620 if (VT == MVT::v8i8) {
5621 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5623 }
else if (VT == MVT::v16i8) {
5624 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5626 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5627 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5629 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5630 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5632 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5633 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5635 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5636 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5638 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5639 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5641 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5642 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5646 case Intrinsic::aarch64_neon_ld2lane:
5647 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5648 SelectLoadLane(Node, 2, AArch64::LD2i8);
5650 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5651 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5652 SelectLoadLane(Node, 2, AArch64::LD2i16);
5654 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5656 SelectLoadLane(Node, 2, AArch64::LD2i32);
5658 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5660 SelectLoadLane(Node, 2, AArch64::LD2i64);
5664 case Intrinsic::aarch64_neon_ld3lane:
5665 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5666 SelectLoadLane(Node, 3, AArch64::LD3i8);
5668 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5669 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5670 SelectLoadLane(Node, 3, AArch64::LD3i16);
5672 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5674 SelectLoadLane(Node, 3, AArch64::LD3i32);
5676 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5678 SelectLoadLane(Node, 3, AArch64::LD3i64);
5682 case Intrinsic::aarch64_neon_ld4lane:
5683 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5684 SelectLoadLane(Node, 4, AArch64::LD4i8);
5686 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5687 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5688 SelectLoadLane(Node, 4, AArch64::LD4i16);
5690 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5692 SelectLoadLane(Node, 4, AArch64::LD4i32);
5694 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5696 SelectLoadLane(Node, 4, AArch64::LD4i64);
5700 case Intrinsic::aarch64_ld64b:
5701 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5703 case Intrinsic::aarch64_sve_ld2q_sret: {
5704 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5707 case Intrinsic::aarch64_sve_ld3q_sret: {
5708 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5711 case Intrinsic::aarch64_sve_ld4q_sret: {
5712 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5715 case Intrinsic::aarch64_sve_ld2_sret: {
5716 if (VT == MVT::nxv16i8) {
5717 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5720 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5721 VT == MVT::nxv8bf16) {
5722 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5725 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5726 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5729 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5730 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5736 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5737 if (VT == MVT::nxv16i8) {
5738 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5739 SelectContiguousMultiVectorLoad(
5740 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5741 else if (Subtarget->hasSVE2p1())
5742 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5747 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5748 VT == MVT::nxv8bf16) {
5749 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5750 SelectContiguousMultiVectorLoad(
5751 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5752 else if (Subtarget->hasSVE2p1())
5753 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5758 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5759 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5760 SelectContiguousMultiVectorLoad(
5761 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5762 else if (Subtarget->hasSVE2p1())
5763 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5768 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5769 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5770 SelectContiguousMultiVectorLoad(
5771 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5772 else if (Subtarget->hasSVE2p1())
5773 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5781 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5782 if (VT == MVT::nxv16i8) {
5783 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5784 SelectContiguousMultiVectorLoad(
5785 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5786 else if (Subtarget->hasSVE2p1())
5787 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5792 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5793 VT == MVT::nxv8bf16) {
5794 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5795 SelectContiguousMultiVectorLoad(
5796 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5797 else if (Subtarget->hasSVE2p1())
5798 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5803 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5804 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5805 SelectContiguousMultiVectorLoad(
5806 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5807 else if (Subtarget->hasSVE2p1())
5808 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5813 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5814 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5815 SelectContiguousMultiVectorLoad(
5816 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5817 else if (Subtarget->hasSVE2p1())
5818 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5826 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5827 if (VT == MVT::nxv16i8) {
5828 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5829 SelectContiguousMultiVectorLoad(Node, 2, 0,
5830 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5831 AArch64::LDNT1B_2Z_PSEUDO);
5832 else if (Subtarget->hasSVE2p1())
5833 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5834 AArch64::LDNT1B_2Z);
5838 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5839 VT == MVT::nxv8bf16) {
5840 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5841 SelectContiguousMultiVectorLoad(Node, 2, 1,
5842 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5843 AArch64::LDNT1H_2Z_PSEUDO);
5844 else if (Subtarget->hasSVE2p1())
5845 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5846 AArch64::LDNT1H_2Z);
5850 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5851 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5852 SelectContiguousMultiVectorLoad(Node, 2, 2,
5853 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5854 AArch64::LDNT1W_2Z_PSEUDO);
5855 else if (Subtarget->hasSVE2p1())
5856 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5857 AArch64::LDNT1W_2Z);
5861 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5862 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5863 SelectContiguousMultiVectorLoad(Node, 2, 3,
5864 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5865 AArch64::LDNT1D_2Z_PSEUDO);
5866 else if (Subtarget->hasSVE2p1())
5867 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5868 AArch64::LDNT1D_2Z);
5875 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5876 if (VT == MVT::nxv16i8) {
5877 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5878 SelectContiguousMultiVectorLoad(Node, 4, 0,
5879 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5880 AArch64::LDNT1B_4Z_PSEUDO);
5881 else if (Subtarget->hasSVE2p1())
5882 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5883 AArch64::LDNT1B_4Z);
5887 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5888 VT == MVT::nxv8bf16) {
5889 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5890 SelectContiguousMultiVectorLoad(Node, 4, 1,
5891 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5892 AArch64::LDNT1H_4Z_PSEUDO);
5893 else if (Subtarget->hasSVE2p1())
5894 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5895 AArch64::LDNT1H_4Z);
5899 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5900 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5901 SelectContiguousMultiVectorLoad(Node, 4, 2,
5902 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5903 AArch64::LDNT1W_4Z_PSEUDO);
5904 else if (Subtarget->hasSVE2p1())
5905 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5906 AArch64::LDNT1W_4Z);
5910 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5911 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5912 SelectContiguousMultiVectorLoad(Node, 4, 3,
5913 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5914 AArch64::LDNT1D_4Z_PSEUDO);
5915 else if (Subtarget->hasSVE2p1())
5916 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5917 AArch64::LDNT1D_4Z);
5924 case Intrinsic::aarch64_sve_ld3_sret: {
5925 if (VT == MVT::nxv16i8) {
5926 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5929 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5930 VT == MVT::nxv8bf16) {
5931 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5934 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5935 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5938 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5939 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5945 case Intrinsic::aarch64_sve_ld4_sret: {
5946 if (VT == MVT::nxv16i8) {
5947 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5950 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5951 VT == MVT::nxv8bf16) {
5952 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5955 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5956 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5959 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5960 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5966 case Intrinsic::aarch64_sme_read_hor_vg2: {
5967 if (VT == MVT::nxv16i8) {
5968 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5969 AArch64::MOVA_2ZMXI_H_B);
5971 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5972 VT == MVT::nxv8bf16) {
5973 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5974 AArch64::MOVA_2ZMXI_H_H);
5976 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5977 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5978 AArch64::MOVA_2ZMXI_H_S);
5980 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5981 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5982 AArch64::MOVA_2ZMXI_H_D);
5987 case Intrinsic::aarch64_sme_read_ver_vg2: {
5988 if (VT == MVT::nxv16i8) {
5989 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5990 AArch64::MOVA_2ZMXI_V_B);
5992 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5993 VT == MVT::nxv8bf16) {
5994 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5995 AArch64::MOVA_2ZMXI_V_H);
5997 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5998 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5999 AArch64::MOVA_2ZMXI_V_S);
6001 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6002 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
6003 AArch64::MOVA_2ZMXI_V_D);
6008 case Intrinsic::aarch64_sme_read_hor_vg4: {
6009 if (VT == MVT::nxv16i8) {
6010 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
6011 AArch64::MOVA_4ZMXI_H_B);
6013 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6014 VT == MVT::nxv8bf16) {
6015 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
6016 AArch64::MOVA_4ZMXI_H_H);
6018 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6019 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
6020 AArch64::MOVA_4ZMXI_H_S);
6022 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6023 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
6024 AArch64::MOVA_4ZMXI_H_D);
6029 case Intrinsic::aarch64_sme_read_ver_vg4: {
6030 if (VT == MVT::nxv16i8) {
6031 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
6032 AArch64::MOVA_4ZMXI_V_B);
6034 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6035 VT == MVT::nxv8bf16) {
6036 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
6037 AArch64::MOVA_4ZMXI_V_H);
6039 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6040 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
6041 AArch64::MOVA_4ZMXI_V_S);
6043 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6044 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
6045 AArch64::MOVA_4ZMXI_V_D);
6050 case Intrinsic::aarch64_sme_read_vg1x2: {
6051 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
6052 AArch64::MOVA_VG2_2ZMXI);
6055 case Intrinsic::aarch64_sme_read_vg1x4: {
6056 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
6057 AArch64::MOVA_VG4_4ZMXI);
6060 case Intrinsic::aarch64_sme_readz_horiz_x2: {
6061 if (VT == MVT::nxv16i8) {
6062 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
6064 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6065 VT == MVT::nxv8bf16) {
6066 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
6068 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6069 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
6071 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6072 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
6077 case Intrinsic::aarch64_sme_readz_vert_x2: {
6078 if (VT == MVT::nxv16i8) {
6079 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
6081 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6082 VT == MVT::nxv8bf16) {
6083 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
6085 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6086 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
6088 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6089 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
6094 case Intrinsic::aarch64_sme_readz_horiz_x4: {
6095 if (VT == MVT::nxv16i8) {
6096 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
6098 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6099 VT == MVT::nxv8bf16) {
6100 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6102 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6103 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6105 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6106 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6111 case Intrinsic::aarch64_sme_readz_vert_x4: {
6112 if (VT == MVT::nxv16i8) {
6113 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6115 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6116 VT == MVT::nxv8bf16) {
6117 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6119 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6120 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6122 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6123 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6128 case Intrinsic::aarch64_sme_readz_x2: {
6129 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6133 case Intrinsic::aarch64_sme_readz_x4: {
6134 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6138 case Intrinsic::swift_async_context_addr: {
6140 SDValue Chain =
Node->getOperand(0);
6141 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6142 SDValue Res = SDValue(
6143 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6144 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6145 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6147 ReplaceUses(SDValue(Node, 0), Res);
6148 ReplaceUses(SDValue(Node, 1), CopyFP.
getValue(1));
6149 CurDAG->RemoveDeadNode(Node);
6151 auto &MF = CurDAG->getMachineFunction();
6152 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6153 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6156 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6158 Node->getValueType(0),
6159 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6160 AArch64::LUTI2_4ZTZI_S}))
6162 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6165 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6167 Node->getValueType(0),
6168 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6170 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6173 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6175 Node->getValueType(0),
6176 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6177 AArch64::LUTI2_2ZTZI_S}))
6179 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6182 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6184 Node->getValueType(0),
6185 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6186 AArch64::LUTI4_2ZTZI_S}))
6188 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6191 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6192 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6195 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6196 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6199 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6201 Node->getValueType(0),
6202 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6203 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6205 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6207 Node->getValueType(0),
6208 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6209 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6211 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6213 Node->getValueType(0),
6214 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6215 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6217 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6219 Node->getValueType(0),
6220 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6221 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6223 case Intrinsic::ptrauth_resign_load_relative:
6224 SelectPtrauthResign(Node);
6229 unsigned IntNo =
Node->getConstantOperandVal(0);
6233 case Intrinsic::aarch64_tagp:
6237 case Intrinsic::ptrauth_auth:
6238 SelectPtrauthAuth(Node);
6241 case Intrinsic::ptrauth_resign:
6242 SelectPtrauthResign(Node);
6245 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6246 SelectPtrauthResignWithPC(Node);
6249 case Intrinsic::aarch64_neon_tbl2:
6250 SelectTable(Node, 2,
6251 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6254 case Intrinsic::aarch64_neon_tbl3:
6255 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6256 : AArch64::TBLv16i8Three,
6259 case Intrinsic::aarch64_neon_tbl4:
6260 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6261 : AArch64::TBLv16i8Four,
6264 case Intrinsic::aarch64_neon_tbx2:
6265 SelectTable(Node, 2,
6266 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6269 case Intrinsic::aarch64_neon_tbx3:
6270 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6271 : AArch64::TBXv16i8Three,
6274 case Intrinsic::aarch64_neon_tbx4:
6275 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6276 : AArch64::TBXv16i8Four,
6279 case Intrinsic::aarch64_sve_srshl_single_x2:
6281 Node->getValueType(0),
6282 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6283 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6284 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6286 case Intrinsic::aarch64_sve_srshl_single_x4:
6288 Node->getValueType(0),
6289 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6290 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6291 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6293 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6294 SelectMultiVectorLuti6LaneX4(Node, 2);
6296 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6297 SelectMultiVectorLuti6LaneX4(Node, 3);
6299 case Intrinsic::aarch64_sve_urshl_single_x2:
6301 Node->getValueType(0),
6302 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6303 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6304 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6306 case Intrinsic::aarch64_sve_urshl_single_x4:
6308 Node->getValueType(0),
6309 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6310 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6311 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6313 case Intrinsic::aarch64_sve_srshl_x2:
6315 Node->getValueType(0),
6316 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6317 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6318 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6320 case Intrinsic::aarch64_sve_srshl_x4:
6322 Node->getValueType(0),
6323 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6324 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6325 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6327 case Intrinsic::aarch64_sve_urshl_x2:
6329 Node->getValueType(0),
6330 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6331 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6332 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6334 case Intrinsic::aarch64_sve_urshl_x4:
6336 Node->getValueType(0),
6337 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6338 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6339 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6341 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6343 Node->getValueType(0),
6344 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6345 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6346 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6348 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6350 Node->getValueType(0),
6351 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6352 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6353 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6355 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6357 Node->getValueType(0),
6358 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6359 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6360 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6362 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6364 Node->getValueType(0),
6365 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6366 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6367 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6369 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6371 Node->getValueType(0),
6372 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6373 AArch64::FSCALE_2ZZ_D}))
6374 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6376 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6378 Node->getValueType(0),
6379 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6380 AArch64::FSCALE_4ZZ_D}))
6381 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6383 case Intrinsic::aarch64_sme_fp8_scale_x2:
6385 Node->getValueType(0),
6386 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6387 AArch64::FSCALE_2Z2Z_D}))
6388 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6390 case Intrinsic::aarch64_sme_fp8_scale_x4:
6392 Node->getValueType(0),
6393 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6394 AArch64::FSCALE_4Z4Z_D}))
6395 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6397 case Intrinsic::aarch64_sve_whilege_x2:
6399 Node->getValueType(0),
6400 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6401 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6402 SelectWhilePair(Node,
Op);
6404 case Intrinsic::aarch64_sve_whilegt_x2:
6406 Node->getValueType(0),
6407 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6408 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6409 SelectWhilePair(Node,
Op);
6411 case Intrinsic::aarch64_sve_whilehi_x2:
6413 Node->getValueType(0),
6414 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6415 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6416 SelectWhilePair(Node,
Op);
6418 case Intrinsic::aarch64_sve_whilehs_x2:
6420 Node->getValueType(0),
6421 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6422 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6423 SelectWhilePair(Node,
Op);
6425 case Intrinsic::aarch64_sve_whilele_x2:
6427 Node->getValueType(0),
6428 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6429 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6430 SelectWhilePair(Node,
Op);
6432 case Intrinsic::aarch64_sve_whilelo_x2:
6434 Node->getValueType(0),
6435 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6436 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6437 SelectWhilePair(Node,
Op);
6439 case Intrinsic::aarch64_sve_whilels_x2:
6441 Node->getValueType(0),
6442 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6443 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6444 SelectWhilePair(Node,
Op);
6446 case Intrinsic::aarch64_sve_whilelt_x2:
6448 Node->getValueType(0),
6449 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6450 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6451 SelectWhilePair(Node,
Op);
6453 case Intrinsic::aarch64_sve_smax_single_x2:
6455 Node->getValueType(0),
6456 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6457 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6458 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6460 case Intrinsic::aarch64_sve_umax_single_x2:
6462 Node->getValueType(0),
6463 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6464 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6465 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6467 case Intrinsic::aarch64_sve_fmax_single_x2:
6469 Node->getValueType(0),
6470 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6471 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6472 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6474 case Intrinsic::aarch64_sve_smax_single_x4:
6476 Node->getValueType(0),
6477 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6478 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6479 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6481 case Intrinsic::aarch64_sve_umax_single_x4:
6483 Node->getValueType(0),
6484 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6485 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6486 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6488 case Intrinsic::aarch64_sve_fmax_single_x4:
6490 Node->getValueType(0),
6491 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6492 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6493 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6495 case Intrinsic::aarch64_sve_smin_single_x2:
6497 Node->getValueType(0),
6498 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6499 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6500 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6502 case Intrinsic::aarch64_sve_umin_single_x2:
6504 Node->getValueType(0),
6505 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6506 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6507 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6509 case Intrinsic::aarch64_sve_fmin_single_x2:
6511 Node->getValueType(0),
6512 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6513 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6514 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6516 case Intrinsic::aarch64_sve_smin_single_x4:
6518 Node->getValueType(0),
6519 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6520 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6521 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6523 case Intrinsic::aarch64_sve_umin_single_x4:
6525 Node->getValueType(0),
6526 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6527 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6528 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6530 case Intrinsic::aarch64_sve_fmin_single_x4:
6532 Node->getValueType(0),
6533 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6534 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6535 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6537 case Intrinsic::aarch64_sve_smax_x2:
6539 Node->getValueType(0),
6540 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6541 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6542 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6544 case Intrinsic::aarch64_sve_umax_x2:
6546 Node->getValueType(0),
6547 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6548 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6549 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6551 case Intrinsic::aarch64_sve_fmax_x2:
6553 Node->getValueType(0),
6554 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6555 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6556 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6558 case Intrinsic::aarch64_sve_smax_x4:
6560 Node->getValueType(0),
6561 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6562 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6563 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6565 case Intrinsic::aarch64_sve_umax_x4:
6567 Node->getValueType(0),
6568 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6569 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6570 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6572 case Intrinsic::aarch64_sve_fmax_x4:
6574 Node->getValueType(0),
6575 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6576 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6577 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6579 case Intrinsic::aarch64_sme_famax_x2:
6581 Node->getValueType(0),
6582 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6583 AArch64::FAMAX_2Z2Z_D}))
6584 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6586 case Intrinsic::aarch64_sme_famax_x4:
6588 Node->getValueType(0),
6589 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6590 AArch64::FAMAX_4Z4Z_D}))
6591 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6593 case Intrinsic::aarch64_sme_famin_x2:
6595 Node->getValueType(0),
6596 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6597 AArch64::FAMIN_2Z2Z_D}))
6598 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6600 case Intrinsic::aarch64_sme_famin_x4:
6602 Node->getValueType(0),
6603 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6604 AArch64::FAMIN_4Z4Z_D}))
6605 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6607 case Intrinsic::aarch64_sve_smin_x2:
6609 Node->getValueType(0),
6610 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6611 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6612 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6614 case Intrinsic::aarch64_sve_umin_x2:
6616 Node->getValueType(0),
6617 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6618 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6619 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6621 case Intrinsic::aarch64_sve_fmin_x2:
6623 Node->getValueType(0),
6624 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6625 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6626 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6628 case Intrinsic::aarch64_sve_smin_x4:
6630 Node->getValueType(0),
6631 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6632 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6633 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6635 case Intrinsic::aarch64_sve_umin_x4:
6637 Node->getValueType(0),
6638 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6639 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6640 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6642 case Intrinsic::aarch64_sve_fmin_x4:
6644 Node->getValueType(0),
6645 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6646 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6647 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6649 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6651 Node->getValueType(0),
6652 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6653 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6654 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6656 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6658 Node->getValueType(0),
6659 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6660 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6661 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6663 case Intrinsic::aarch64_sve_fminnm_single_x2:
6665 Node->getValueType(0),
6666 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6667 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6668 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6670 case Intrinsic::aarch64_sve_fminnm_single_x4:
6672 Node->getValueType(0),
6673 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6674 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6675 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6677 case Intrinsic::aarch64_sve_fscale_single_x4:
6678 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6680 case Intrinsic::aarch64_sve_fscale_single_x2:
6681 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6683 case Intrinsic::aarch64_sve_fmul_single_x4:
6685 Node->getValueType(0),
6686 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6687 AArch64::FMUL_4ZZ_D}))
6688 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6690 case Intrinsic::aarch64_sve_fmul_single_x2:
6692 Node->getValueType(0),
6693 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6694 AArch64::FMUL_2ZZ_D}))
6695 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6697 case Intrinsic::aarch64_sve_fmaxnm_x2:
6699 Node->getValueType(0),
6700 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6701 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6702 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6704 case Intrinsic::aarch64_sve_fmaxnm_x4:
6706 Node->getValueType(0),
6707 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6708 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6709 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6711 case Intrinsic::aarch64_sve_fminnm_x2:
6713 Node->getValueType(0),
6714 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6715 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6716 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6718 case Intrinsic::aarch64_sve_fminnm_x4:
6720 Node->getValueType(0),
6721 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6722 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6723 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6725 case Intrinsic::aarch64_sve_aese_lane_x2:
6726 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6728 case Intrinsic::aarch64_sve_aesd_lane_x2:
6729 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6731 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6732 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6734 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6735 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6737 case Intrinsic::aarch64_sve_aese_lane_x4:
6738 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6740 case Intrinsic::aarch64_sve_aesd_lane_x4:
6741 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6743 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6744 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6746 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6747 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6749 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6750 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6752 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6756 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6757 SDValue SuperReg = SDValue(Res, 0);
6758 for (
unsigned I = 0;
I < 2;
I++)
6759 ReplaceUses(SDValue(Node,
I),
6760 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6762 CurDAG->RemoveDeadNode(Node);
6765 case Intrinsic::aarch64_sve_fscale_x4:
6766 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6768 case Intrinsic::aarch64_sve_fscale_x2:
6769 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6771 case Intrinsic::aarch64_sve_fmul_x4:
6773 Node->getValueType(0),
6774 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6775 AArch64::FMUL_4Z4Z_D}))
6776 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6778 case Intrinsic::aarch64_sve_fmul_x2:
6780 Node->getValueType(0),
6781 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6782 AArch64::FMUL_2Z2Z_D}))
6783 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6785 case Intrinsic::aarch64_sve_fcvtzs_x2:
6786 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6788 case Intrinsic::aarch64_sve_scvtf_x2:
6789 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6791 case Intrinsic::aarch64_sve_fcvtzu_x2:
6792 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6794 case Intrinsic::aarch64_sve_ucvtf_x2:
6795 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6797 case Intrinsic::aarch64_sve_fcvtzs_x4:
6798 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6800 case Intrinsic::aarch64_sve_scvtf_x4:
6801 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6803 case Intrinsic::aarch64_sve_fcvtzu_x4:
6804 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6806 case Intrinsic::aarch64_sve_ucvtf_x4:
6807 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6809 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6810 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6812 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6813 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6815 case Intrinsic::aarch64_sve_sclamp_single_x2:
6817 Node->getValueType(0),
6818 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6819 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6820 SelectClamp(Node, 2,
Op);
6822 case Intrinsic::aarch64_sve_uclamp_single_x2:
6824 Node->getValueType(0),
6825 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6826 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6827 SelectClamp(Node, 2,
Op);
6829 case Intrinsic::aarch64_sve_fclamp_single_x2:
6831 Node->getValueType(0),
6832 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6833 AArch64::FCLAMP_VG2_2Z2Z_D}))
6834 SelectClamp(Node, 2,
Op);
6836 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6837 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6839 case Intrinsic::aarch64_sve_sclamp_single_x4:
6841 Node->getValueType(0),
6842 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6843 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6844 SelectClamp(Node, 4,
Op);
6846 case Intrinsic::aarch64_sve_uclamp_single_x4:
6848 Node->getValueType(0),
6849 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6850 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6851 SelectClamp(Node, 4,
Op);
6853 case Intrinsic::aarch64_sve_fclamp_single_x4:
6855 Node->getValueType(0),
6856 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6857 AArch64::FCLAMP_VG4_4Z4Z_D}))
6858 SelectClamp(Node, 4,
Op);
6860 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6861 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6863 case Intrinsic::aarch64_sve_add_single_x2:
6865 Node->getValueType(0),
6866 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6867 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6868 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6870 case Intrinsic::aarch64_sve_add_single_x4:
6872 Node->getValueType(0),
6873 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6874 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6875 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6877 case Intrinsic::aarch64_sve_zip_x2:
6879 Node->getValueType(0),
6880 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6881 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6882 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6884 case Intrinsic::aarch64_sve_zipq_x2:
6885 SelectUnaryMultiIntrinsic(Node, 2,
false,
6886 AArch64::ZIP_VG2_2ZZZ_Q);
6888 case Intrinsic::aarch64_sve_zip_x4:
6890 Node->getValueType(0),
6891 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6892 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6893 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6895 case Intrinsic::aarch64_sve_zipq_x4:
6896 SelectUnaryMultiIntrinsic(Node, 4,
true,
6897 AArch64::ZIP_VG4_4Z4Z_Q);
6899 case Intrinsic::aarch64_sve_uzp_x2:
6901 Node->getValueType(0),
6902 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6903 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6904 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6906 case Intrinsic::aarch64_sve_uzpq_x2:
6907 SelectUnaryMultiIntrinsic(Node, 2,
false,
6908 AArch64::UZP_VG2_2ZZZ_Q);
6910 case Intrinsic::aarch64_sve_uzp_x4:
6912 Node->getValueType(0),
6913 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6914 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6915 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6917 case Intrinsic::aarch64_sve_uzpq_x4:
6918 SelectUnaryMultiIntrinsic(Node, 4,
true,
6919 AArch64::UZP_VG4_4Z4Z_Q);
6921 case Intrinsic::aarch64_sve_sel_x2:
6923 Node->getValueType(0),
6924 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6925 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6926 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6928 case Intrinsic::aarch64_sve_sel_x4:
6930 Node->getValueType(0),
6931 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6932 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6933 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6935 case Intrinsic::aarch64_sve_frinta_x2:
6936 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6938 case Intrinsic::aarch64_sve_frinta_x4:
6939 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6941 case Intrinsic::aarch64_sve_frintm_x2:
6942 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6944 case Intrinsic::aarch64_sve_frintm_x4:
6945 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6947 case Intrinsic::aarch64_sve_frintn_x2:
6948 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6950 case Intrinsic::aarch64_sve_frintn_x4:
6951 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6953 case Intrinsic::aarch64_sve_frintp_x2:
6954 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6956 case Intrinsic::aarch64_sve_frintp_x4:
6957 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6959 case Intrinsic::aarch64_sve_sunpk_x2:
6961 Node->getValueType(0),
6962 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6963 AArch64::SUNPK_VG2_2ZZ_D}))
6964 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6966 case Intrinsic::aarch64_sve_uunpk_x2:
6968 Node->getValueType(0),
6969 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6970 AArch64::UUNPK_VG2_2ZZ_D}))
6971 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6973 case Intrinsic::aarch64_sve_sunpk_x4:
6975 Node->getValueType(0),
6976 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6977 AArch64::SUNPK_VG4_4Z2Z_D}))
6978 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6980 case Intrinsic::aarch64_sve_uunpk_x4:
6982 Node->getValueType(0),
6983 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6984 AArch64::UUNPK_VG4_4Z2Z_D}))
6985 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6987 case Intrinsic::aarch64_sve_pext_x2: {
6989 Node->getValueType(0),
6990 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6991 AArch64::PEXT_2PCI_D}))
6992 SelectPExtPair(Node,
Op);
6999 unsigned IntNo =
Node->getConstantOperandVal(1);
7000 if (
Node->getNumOperands() >= 3)
7001 VT =
Node->getOperand(2)->getValueType(0);
7005 case Intrinsic::aarch64_neon_st1x2: {
7006 if (VT == MVT::v8i8) {
7007 SelectStore(Node, 2, AArch64::ST1Twov8b);
7009 }
else if (VT == MVT::v16i8) {
7010 SelectStore(Node, 2, AArch64::ST1Twov16b);
7012 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7013 VT == MVT::v4bf16) {
7014 SelectStore(Node, 2, AArch64::ST1Twov4h);
7016 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7017 VT == MVT::v8bf16) {
7018 SelectStore(Node, 2, AArch64::ST1Twov8h);
7020 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7021 SelectStore(Node, 2, AArch64::ST1Twov2s);
7023 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7024 SelectStore(Node, 2, AArch64::ST1Twov4s);
7026 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7027 SelectStore(Node, 2, AArch64::ST1Twov2d);
7029 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7030 SelectStore(Node, 2, AArch64::ST1Twov1d);
7035 case Intrinsic::aarch64_neon_st1x3: {
7036 if (VT == MVT::v8i8) {
7037 SelectStore(Node, 3, AArch64::ST1Threev8b);
7039 }
else if (VT == MVT::v16i8) {
7040 SelectStore(Node, 3, AArch64::ST1Threev16b);
7042 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7043 VT == MVT::v4bf16) {
7044 SelectStore(Node, 3, AArch64::ST1Threev4h);
7046 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7047 VT == MVT::v8bf16) {
7048 SelectStore(Node, 3, AArch64::ST1Threev8h);
7050 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7051 SelectStore(Node, 3, AArch64::ST1Threev2s);
7053 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7054 SelectStore(Node, 3, AArch64::ST1Threev4s);
7056 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7057 SelectStore(Node, 3, AArch64::ST1Threev2d);
7059 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7060 SelectStore(Node, 3, AArch64::ST1Threev1d);
7065 case Intrinsic::aarch64_neon_st1x4: {
7066 if (VT == MVT::v8i8) {
7067 SelectStore(Node, 4, AArch64::ST1Fourv8b);
7069 }
else if (VT == MVT::v16i8) {
7070 SelectStore(Node, 4, AArch64::ST1Fourv16b);
7072 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7073 VT == MVT::v4bf16) {
7074 SelectStore(Node, 4, AArch64::ST1Fourv4h);
7076 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7077 VT == MVT::v8bf16) {
7078 SelectStore(Node, 4, AArch64::ST1Fourv8h);
7080 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7081 SelectStore(Node, 4, AArch64::ST1Fourv2s);
7083 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7084 SelectStore(Node, 4, AArch64::ST1Fourv4s);
7086 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7087 SelectStore(Node, 4, AArch64::ST1Fourv2d);
7089 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7090 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7095 case Intrinsic::aarch64_neon_st2: {
7096 if (VT == MVT::v8i8) {
7097 SelectStore(Node, 2, AArch64::ST2Twov8b);
7099 }
else if (VT == MVT::v16i8) {
7100 SelectStore(Node, 2, AArch64::ST2Twov16b);
7102 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7103 VT == MVT::v4bf16) {
7104 SelectStore(Node, 2, AArch64::ST2Twov4h);
7106 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7107 VT == MVT::v8bf16) {
7108 SelectStore(Node, 2, AArch64::ST2Twov8h);
7110 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7111 SelectStore(Node, 2, AArch64::ST2Twov2s);
7113 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7114 SelectStore(Node, 2, AArch64::ST2Twov4s);
7116 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7117 SelectStore(Node, 2, AArch64::ST2Twov2d);
7119 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7120 SelectStore(Node, 2, AArch64::ST1Twov1d);
7125 case Intrinsic::aarch64_neon_st3: {
7126 if (VT == MVT::v8i8) {
7127 SelectStore(Node, 3, AArch64::ST3Threev8b);
7129 }
else if (VT == MVT::v16i8) {
7130 SelectStore(Node, 3, AArch64::ST3Threev16b);
7132 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7133 VT == MVT::v4bf16) {
7134 SelectStore(Node, 3, AArch64::ST3Threev4h);
7136 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7137 VT == MVT::v8bf16) {
7138 SelectStore(Node, 3, AArch64::ST3Threev8h);
7140 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7141 SelectStore(Node, 3, AArch64::ST3Threev2s);
7143 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7144 SelectStore(Node, 3, AArch64::ST3Threev4s);
7146 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7147 SelectStore(Node, 3, AArch64::ST3Threev2d);
7149 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7150 SelectStore(Node, 3, AArch64::ST1Threev1d);
7155 case Intrinsic::aarch64_neon_st4: {
7156 if (VT == MVT::v8i8) {
7157 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7159 }
else if (VT == MVT::v16i8) {
7160 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7162 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7163 VT == MVT::v4bf16) {
7164 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7166 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7167 VT == MVT::v8bf16) {
7168 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7170 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7171 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7173 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7174 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7176 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7177 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7179 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7180 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7185 case Intrinsic::aarch64_neon_st2lane: {
7186 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7187 SelectStoreLane(Node, 2, AArch64::ST2i8);
7189 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7190 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7191 SelectStoreLane(Node, 2, AArch64::ST2i16);
7193 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7195 SelectStoreLane(Node, 2, AArch64::ST2i32);
7197 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7199 SelectStoreLane(Node, 2, AArch64::ST2i64);
7204 case Intrinsic::aarch64_neon_st3lane: {
7205 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7206 SelectStoreLane(Node, 3, AArch64::ST3i8);
7208 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7209 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7210 SelectStoreLane(Node, 3, AArch64::ST3i16);
7212 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7214 SelectStoreLane(Node, 3, AArch64::ST3i32);
7216 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7218 SelectStoreLane(Node, 3, AArch64::ST3i64);
7223 case Intrinsic::aarch64_neon_st4lane: {
7224 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7225 SelectStoreLane(Node, 4, AArch64::ST4i8);
7227 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7228 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7229 SelectStoreLane(Node, 4, AArch64::ST4i16);
7231 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7233 SelectStoreLane(Node, 4, AArch64::ST4i32);
7235 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7237 SelectStoreLane(Node, 4, AArch64::ST4i64);
7242 case Intrinsic::aarch64_sve_st2q: {
7243 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7246 case Intrinsic::aarch64_sve_st3q: {
7247 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7250 case Intrinsic::aarch64_sve_st4q: {
7251 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7254 case Intrinsic::aarch64_sve_st2: {
7255 if (VT == MVT::nxv16i8) {
7256 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7258 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7259 VT == MVT::nxv8bf16) {
7260 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7262 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7263 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7265 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7266 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7271 case Intrinsic::aarch64_sve_st3: {
7272 if (VT == MVT::nxv16i8) {
7273 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7275 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7276 VT == MVT::nxv8bf16) {
7277 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7279 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7280 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7282 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7283 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7288 case Intrinsic::aarch64_sve_st4: {
7289 if (VT == MVT::nxv16i8) {
7290 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7292 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7293 VT == MVT::nxv8bf16) {
7294 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7296 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7297 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7299 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7300 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7308 case AArch64ISD::LD2post: {
7309 if (VT == MVT::v8i8) {
7310 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7312 }
else if (VT == MVT::v16i8) {
7313 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7315 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7316 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7318 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7319 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7321 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7322 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7324 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7325 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7327 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7328 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7330 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7331 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7336 case AArch64ISD::LD3post: {
7337 if (VT == MVT::v8i8) {
7338 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7340 }
else if (VT == MVT::v16i8) {
7341 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7343 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7344 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7346 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7347 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7349 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7350 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7352 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7353 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7355 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7356 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7358 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7359 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7364 case AArch64ISD::LD4post: {
7365 if (VT == MVT::v8i8) {
7366 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7368 }
else if (VT == MVT::v16i8) {
7369 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7371 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7372 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7374 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7375 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7377 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7378 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7380 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7381 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7383 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7384 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7386 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7387 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7392 case AArch64ISD::LD1x2post: {
7393 if (VT == MVT::v8i8) {
7394 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7396 }
else if (VT == MVT::v16i8) {
7397 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7399 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7400 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7402 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7403 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7405 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7406 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7408 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7409 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7411 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7412 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7414 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7415 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7420 case AArch64ISD::LD1x3post: {
7421 if (VT == MVT::v8i8) {
7422 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7424 }
else if (VT == MVT::v16i8) {
7425 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7427 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7428 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7430 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7431 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7433 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7434 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7436 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7437 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7439 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7440 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7442 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7443 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7448 case AArch64ISD::LD1x4post: {
7449 if (VT == MVT::v8i8) {
7450 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7452 }
else if (VT == MVT::v16i8) {
7453 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7455 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7456 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7458 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7459 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7461 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7462 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7464 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7465 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7467 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7468 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7470 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7471 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7476 case AArch64ISD::LD1DUPpost: {
7477 if (VT == MVT::v8i8) {
7478 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7480 }
else if (VT == MVT::v16i8) {
7481 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7483 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7484 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7486 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7487 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7489 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7490 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7492 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7493 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7495 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7496 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7498 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7499 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7504 case AArch64ISD::LD2DUPpost: {
7505 if (VT == MVT::v8i8) {
7506 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7508 }
else if (VT == MVT::v16i8) {
7509 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7511 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7512 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7514 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7515 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7517 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7518 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7520 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7521 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7523 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7524 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7526 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7527 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7532 case AArch64ISD::LD3DUPpost: {
7533 if (VT == MVT::v8i8) {
7534 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7536 }
else if (VT == MVT::v16i8) {
7537 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7539 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7540 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7542 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7543 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7545 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7546 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7548 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7549 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7551 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7552 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7554 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7555 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7560 case AArch64ISD::LD4DUPpost: {
7561 if (VT == MVT::v8i8) {
7562 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7564 }
else if (VT == MVT::v16i8) {
7565 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7567 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7568 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7570 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7571 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7573 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7574 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7576 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7577 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7579 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7580 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7582 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7583 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7588 case AArch64ISD::LD1LANEpost: {
7589 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7590 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7592 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7593 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7594 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7596 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7598 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7600 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7602 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7607 case AArch64ISD::LD2LANEpost: {
7608 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7609 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7611 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7612 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7613 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7615 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7617 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7619 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7621 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7626 case AArch64ISD::LD3LANEpost: {
7627 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7628 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7630 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7631 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7632 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7634 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7636 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7638 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7640 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7645 case AArch64ISD::LD4LANEpost: {
7646 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7647 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7649 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7650 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7651 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7653 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7655 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7657 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7659 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7664 case AArch64ISD::ST2post: {
7665 VT =
Node->getOperand(1).getValueType();
7666 if (VT == MVT::v8i8) {
7667 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7669 }
else if (VT == MVT::v16i8) {
7670 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7672 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7673 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7675 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7676 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7678 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7679 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7681 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7682 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7684 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7685 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7687 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7688 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7693 case AArch64ISD::ST3post: {
7694 VT =
Node->getOperand(1).getValueType();
7695 if (VT == MVT::v8i8) {
7696 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7698 }
else if (VT == MVT::v16i8) {
7699 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7701 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7702 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7704 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7705 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7707 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7708 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7710 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7711 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7713 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7714 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7716 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7717 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7722 case AArch64ISD::ST4post: {
7723 VT =
Node->getOperand(1).getValueType();
7724 if (VT == MVT::v8i8) {
7725 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7727 }
else if (VT == MVT::v16i8) {
7728 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7730 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7731 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7733 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7734 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7736 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7737 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7739 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7740 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7742 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7743 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7745 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7746 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7751 case AArch64ISD::ST1x2post: {
7752 VT =
Node->getOperand(1).getValueType();
7753 if (VT == MVT::v8i8) {
7754 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7756 }
else if (VT == MVT::v16i8) {
7757 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7759 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7760 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7762 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7763 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7765 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7766 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7768 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7769 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7771 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7772 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7774 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7775 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7780 case AArch64ISD::ST1x3post: {
7781 VT =
Node->getOperand(1).getValueType();
7782 if (VT == MVT::v8i8) {
7783 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7785 }
else if (VT == MVT::v16i8) {
7786 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7788 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7789 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7791 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7792 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7794 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7795 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7797 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7798 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7800 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7801 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7803 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7804 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7809 case AArch64ISD::ST1x4post: {
7810 VT =
Node->getOperand(1).getValueType();
7811 if (VT == MVT::v8i8) {
7812 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7814 }
else if (VT == MVT::v16i8) {
7815 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7817 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7818 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7820 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7821 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7823 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7824 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7826 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7827 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7829 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7830 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7832 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7833 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7838 case AArch64ISD::ST2LANEpost: {
7839 VT =
Node->getOperand(1).getValueType();
7840 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7841 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7843 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7844 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7845 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7847 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7849 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7851 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7853 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7858 case AArch64ISD::ST3LANEpost: {
7859 VT =
Node->getOperand(1).getValueType();
7860 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7861 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7863 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7864 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7865 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7867 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7869 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7871 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7873 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7878 case AArch64ISD::ST4LANEpost: {
7879 VT =
Node->getOperand(1).getValueType();
7880 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7881 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7883 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7884 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7885 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7887 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7889 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7891 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7893 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7908 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7920 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7924 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7925 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7947 return MemIntr->getMemoryVT();
7954 DataVT =
Load->getValueType(0);
7956 DataVT =
Load->getValueType(0);
7958 DataVT =
Store->getValue().getValueType();
7960 DataVT =
Store->getValue().getValueType();
7967 const unsigned Opcode = Root->
getOpcode();
7971 case AArch64ISD::LD1_MERGE_ZERO:
7972 case AArch64ISD::LD1S_MERGE_ZERO:
7973 case AArch64ISD::LDNF1_MERGE_ZERO:
7974 case AArch64ISD::LDNF1S_MERGE_ZERO:
7976 case AArch64ISD::ST1_PRED:
7988 case Intrinsic::aarch64_sme_ldr:
7989 case Intrinsic::aarch64_sme_str:
7990 return MVT::nxv16i8;
7991 case Intrinsic::aarch64_sve_prf:
7996 case Intrinsic::aarch64_sve_ld2_sret:
7997 case Intrinsic::aarch64_sve_ld2q_sret:
8000 case Intrinsic::aarch64_sve_st2q:
8003 case Intrinsic::aarch64_sve_ld3_sret:
8004 case Intrinsic::aarch64_sve_ld3q_sret:
8007 case Intrinsic::aarch64_sve_st3q:
8010 case Intrinsic::aarch64_sve_ld4_sret:
8011 case Intrinsic::aarch64_sve_ld4q_sret:
8014 case Intrinsic::aarch64_sve_st4q:
8017 case Intrinsic::aarch64_sve_ld1_pn_x2:
8018 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
8021 case Intrinsic::aarch64_sve_ld1_pn_x4:
8022 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
8025 case Intrinsic::aarch64_sve_st1_pn_x2:
8026 case Intrinsic::aarch64_sve_stnt1_pn_x2:
8029 case Intrinsic::aarch64_sve_st1_pn_x4:
8030 case Intrinsic::aarch64_sve_stnt1_pn_x4:
8033 case Intrinsic::aarch64_sve_ld1udq:
8034 case Intrinsic::aarch64_sve_st1dq:
8035 return EVT(MVT::nxv1i64);
8036 case Intrinsic::aarch64_sve_ld1uwq:
8037 case Intrinsic::aarch64_sve_st1wq:
8038 return EVT(MVT::nxv1i32);
8045template <
int64_t Min,
int64_t Max>
8046bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue
N,
8050 const DataLayout &
DL = CurDAG->getDataLayout();
8051 const MachineFrameInfo &MFI = MF->getFrameInfo();
8059 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8072 SDValue VScale =
N.getOperand(1);
8073 int64_t MulImm = std::numeric_limits<int64_t>::max();
8077 int64_t ByteOffset =
C->getSExtValue();
8078 const auto KnownVScale =
8081 if (!KnownVScale || ByteOffset % KnownVScale != 0)
8084 MulImm = ByteOffset / KnownVScale;
8091 if ((MulImm % MemWidthBytes) != 0)
8094 int64_t
Offset = MulImm / MemWidthBytes;
8098 Base =
N.getOperand(0);
8107 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8113bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(SDValue
N,
unsigned Scale,
8120 const SDValue
LHS =
N.getOperand(0);
8121 const SDValue
RHS =
N.getOperand(1);
8132 int64_t ImmOff =
C->getSExtValue();
8133 unsigned Size = 1 << Scale;
8142 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8144 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8153 const SDValue ShiftRHS =
RHS.getOperand(1);
8155 if (
C->getZExtValue() == Scale) {
8164bool AArch64DAGToDAGISel::SelectAllActivePredicate(SDValue
N) {
8165 const AArch64TargetLowering *TLI =
8166 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8171bool AArch64DAGToDAGISel::SelectAnyPredicate(SDValue
N) {
8172 return N.getValueType().isScalableVectorOf(MVT::i1);
8175bool AArch64DAGToDAGISel::SelectSMETileSlice(SDValue
N,
unsigned MaxSize,
8178 auto MatchConstantOffset = [&](SDValue CN) -> SDValue {
8180 int64_t ImmOff =
C->getSExtValue();
8181 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8182 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8187 if (SDValue
C = MatchConstantOffset(
N)) {
8194 if (CurDAG->isBaseWithConstantOffset(
N)) {
8195 if (SDValue
C = MatchConstantOffset(
N.getOperand(1))) {
8196 Base =
N.getOperand(0);
8204 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8208bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P, SDValue
N,
8246 if (CN->getAPIntValue().uge(LowerBound) &&
8247 CN->getAPIntValue().ult(UpperBound)) {
8249 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8257template <
bool MatchCBB>
8258bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue
N, SDValue &
Reg,
8264 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8266 Reg =
N.getOperand(0);
8268 SDLoc(
N), MVT::i32);
8276 Reg =
N.getOperand(0);
8296bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *
N) {
8297 EVT VT =
N->getValueType(0);
8303 SDValue TVal =
N->getOperand(0);
8304 SDValue FVal =
N->getOperand(1);
8305 SDValue CCVal =
N->getOperand(2);
8306 SDValue
Cmp =
N->getOperand(3);
8308 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8315 SDValue CmpLHS =
Cmp.getOperand(0);
8316 SDValue CmpRHS =
Cmp.getOperand(1);
8317 unsigned CondCode = CC->getZExtValue();
8320 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8322 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8323 else if (VT == MVT::f32)
8324 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8325 else if (VT == MVT::f64)
8326 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8334 if (TVal == CmpLHS && FVal == CmpRHS)
8339 if (TVal == CmpLHS && FVal == CmpRHS)
8348 unsigned Opc = getOpc(VT, isMax);
8354 if (!CFP || CFP->getValueAPF().isNaN())
8359 if (CFP->isZero() && !
N->getFlags().hasNoSignedZeros())
8365 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8368 CurDAG->SelectNodeTo(
N,
Opc, VT, CmpLHS, CmpRHS);
8372void AArch64DAGToDAGISel::PreprocessISelDAG() {
8373 bool MadeChange =
false;
8379 switch (
N.getOpcode()) {
8381 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8382 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8383 ScalarTy ==
N.getOperand(0).getValueType())
8388 case AArch64ISD::VSHL: {
8391 EVT VT =
N.getValueType(0);
8392 SDValue
A,
B,
C =
N.getOperand(1);
8398 if (
B.getOpcode() ==
A.getOpcode())
8401 SDValue
SHL = CurDAG->getNode(AArch64ISD::VSHL,
DL, VT,
A,
C);
8411 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8417 CurDAG->ReplaceAllUsesOfValueWith(SDValue(&
N, 0), Result);
8423 CurDAG->RemoveDeadNodes();
static std::optional< APInt > GetNEONSplatValue(SDValue N, const AArch64Subtarget *Subtarget)
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 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 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 std::optional< APInt > DecodeNEONSplat(SDValue N, const AArch64Subtarget *Subtarget)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec)
Builds an integer vector type large enough to hold NumVec instances of VecVT.
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Contains matchers for matching SelectionDAG nodes and values.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64InstrInfo * getInstrInfo() 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
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
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.
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
bool equalsStr(StringRef Str) const
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.
A description of a memory reference used in the backend.
const MDNode * getMemCacheHint() const
Return the cache hint metadata for the memory reference.
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
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ POISON
POISON - A poison node.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_SExt(const Opnd &Op)
bool sd_match(SDValue N, Pattern &&P)
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
NUses_match< 1, Value_match > m_OneUse()
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
AArch64MemoryHint toAArch64MemoryHint(Int I)
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.