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);
451 bool tryReadRegister(
SDNode *
N);
452 bool tryWriteRegister(
SDNode *
N);
454 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
455 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
459 bool tryFoldCselToFMaxMin(
SDNode *
N);
462#include "AArch64GenDAGISel.inc"
470 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
472 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
485 bool isWorthNegatingImm(
SDValue V)
const;
486 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
487 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
488 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
491 template<
unsigned RegW
idth>
493 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
495 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
497 template <
unsigned RegW
idth>
499 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
501 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
503 template<
unsigned RegW
idth>
505 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
511 template <
unsigned FloatW
idth>
513 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
519 bool SelectCMP_SWAP(
SDNode *
N);
551 bool SelectAllActivePredicate(
SDValue N);
556 template <
bool MatchCBB>
566 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
570char AArch64DAGToDAGISelLegacy::ID = 0;
576 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
582 auto getFloatVT = [&](
EVT VT) {
584 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
585 return VT.changeElementType(*(DAG.
getContext()),
586 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
591 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
592 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
596 EVT OrigVT =
N.getValueType(0);
605 Imm =
C->getZExtValue();
622 return N->getOpcode() ==
Opc &&
633 return Imm == ImmExpected;
638 assert(RegWidth == 32 || RegWidth == 64);
640 return APInt(RegWidth,
648 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
649 if (
N->getOpcode() == AArch64ISD::NVCAST ||
651 N =
N->getOperand(0);
652 unsigned SplatWidth =
N.getScalarValueSizeInBits();
653 if (
N.getOpcode() == AArch64ISD::FMOV)
655 if (
N->getOpcode() == AArch64ISD::MOVI)
656 return APInt(SplatWidth,
N.getConstantOperandVal(0));
657 if (
N->getOpcode() == AArch64ISD::MOVIshift)
658 return APInt(SplatWidth,
N.getConstantOperandVal(0)
659 <<
N.getConstantOperandVal(1));
660 if (
N->getOpcode() == AArch64ISD::MVNIshift)
661 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
662 <<
N.getConstantOperandVal(1));
663 if (
N->getOpcode() == AArch64ISD::MOVIedit)
665 N.getConstantOperandVal(0)));
666 if (
N->getOpcode() == AArch64ISD::DUP)
668 return Const->getAPIntValue().trunc(SplatWidth);
671 return SplatVal.
trunc(SplatWidth);
679static std::optional<APInt>
681 unsigned SplatWidth =
N.getScalarValueSizeInBits();
683 if (SplatVal->getBitWidth() <= SplatWidth)
685 if (SplatVal->isSplat(SplatWidth))
686 return SplatVal->trunc(SplatWidth);
691bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
698 ImmVal->getZExtValue(), Encoding))
701 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
705bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(SDValue
N, SDValue &
Imm,
708 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
709 N.getValueType().getScalarType().getSimpleVT(),
715bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(SDValue
N,
718 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal,
Imm);
722bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(SDValue
N, SDValue &
Imm) {
727 int64_t ImmVal = ImmAPIntVal->getSExtValue();
728 if (ImmVal < -128 || ImmVal > 127)
731 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
735bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(SDValue
N, SDValue &
Imm) {
740 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
744 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
748bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
750 std::vector<SDValue> &OutOps) {
751 switch(ConstraintID) {
754 case InlineAsm::ConstraintCode::m:
755 case InlineAsm::ConstraintCode::o:
756 case InlineAsm::ConstraintCode::Q:
763 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
765 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
766 dl,
Op.getValueType(),
768 OutOps.push_back(NewOp);
780 switch (User->getOpcode()) {
785 return User->getOperand(1).getNode() == N.getNode();
786 case ISD::ANY_EXTEND:
787 case ISD::ZERO_EXTEND:
788 case ISD::SIGN_EXTEND:
791 return allUsesAreShiftAmounts(SDValue(User, 0));
798template <
unsigned ShiftW
idth>
799bool AArch64DAGToDAGISel::SelectShiftMask(SDValue
N, SDValue &ShAmt) {
808 (
N.getValueType() == MVT::i32 ||
N.getValueType() == MVT::i64)) {
820 (
N.getValueType() == MVT::i32 ||
N.getValueType() == MVT::i64)) {
823 (
Imm % ShiftWidth == 0)) {
832 (
N.getValueType() == MVT::i32 ||
N.getValueType() == MVT::i64)) {
835 (
Imm % ShiftWidth == 0)) {
837 EVT VT =
N.getValueType();
838 bool Is32 = VT == MVT::i32;
839 unsigned NegOpc = Is32 ? AArch64::SUBWrr : AArch64::SUBXrr;
840 unsigned ZeroReg = Is32 ? AArch64::WZR : AArch64::XZR;
842 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, VT);
844 CurDAG->getMachineNode(NegOpc,
DL, VT, Zero,
N.getOperand(1));
845 ShAmt = SDValue(Neg, 0);
853 (
N.getValueType() == MVT::i32 ||
N.getValueType() == MVT::i64)) {
856 (
Imm % ShiftWidth == ShiftWidth - 1)) {
858 EVT VT =
N.getValueType();
859 bool Is32 = VT == MVT::i32;
860 unsigned NotOpc = Is32 ? AArch64::ORNWrr : AArch64::ORNXrr;
861 unsigned ZeroReg = Is32 ? AArch64::WZR : AArch64::XZR;
863 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, VT);
865 CurDAG->getMachineNode(NotOpc,
DL, VT, Zero,
N.getOperand(1));
866 ShAmt = SDValue(
Not, 0);
877bool AArch64DAGToDAGISel::SelectArithImmed(SDValue
N, SDValue &Val,
887 uint64_t Immed =
N.getNode()->getAsZExtVal();
897 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
898 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
904bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue
N, SDValue &Val,
915 uint64_t Immed =
N.getNode()->getAsZExtVal();
923 if (
N.getValueType() == MVT::i32)
924 Immed = ~((uint32_t)Immed) + 1;
926 Immed = ~Immed + 1ULL;
927 if (Immed & 0xFFFFFFFFFF000000ULL)
930 Immed &= 0xFFFFFFULL;
931 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
938 switch (
N.getOpcode()) {
964 unsigned ShiftVal = CSD->getZExtValue();
982bool AArch64DAGToDAGISel::isWorthFoldingAddr(SDValue V,
unsigned Size)
const {
985 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
990 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
998 const SDValue
LHS =
V.getOperand(0);
999 const SDValue
RHS =
V.getOperand(1);
1012bool AArch64DAGToDAGISel::SelectShiftedRegisterFromAnd(SDValue
N, SDValue &
Reg,
1014 EVT VT =
N.getValueType();
1015 if (VT != MVT::i32 && VT != MVT::i64)
1018 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
1020 SDValue
LHS =
N.getOperand(0);
1024 unsigned LHSOpcode =
LHS->getOpcode();
1038 unsigned LowZBits, MaskLen;
1042 unsigned BitWidth =
N.getValueSizeInBits();
1045 unsigned NewShiftOp;
1049 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
1052 NewShiftC = LowZBits - ShiftAmtC;
1053 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1059 NewShiftC = LowZBits + ShiftAmtC;
1072 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1074 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
1078 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
1079 SDValue BitWidthMinus1 = CurDAG->getTargetConstant(
BitWidth - 1,
DL, VT);
1080 Reg = SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
1081 NewShiftAmt, BitWidthMinus1),
1084 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
1098 SrcVT =
N.getOperand(0).getValueType();
1100 if (!IsLoadStore && SrcVT == MVT::i8)
1102 else if (!IsLoadStore && SrcVT == MVT::i16)
1104 else if (SrcVT == MVT::i32)
1106 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1111 EVT SrcVT =
N.getOperand(0).getValueType();
1112 if (!IsLoadStore && SrcVT == MVT::i8)
1114 else if (!IsLoadStore && SrcVT == MVT::i16)
1116 else if (SrcVT == MVT::i32)
1118 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1143bool AArch64DAGToDAGISel::isWorthNegatingImm(SDValue V)
const {
1146 EVT VT =
V.getValueType();
1147 assert((VT == MVT::i32 || VT == MVT::i64) &&
"invalid type");
1158 return NewCost.
size() < OrigCost.
size();
1165bool AArch64DAGToDAGISel::isWorthFoldingALU(SDValue V,
bool LSL)
const {
1168 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1173 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1174 V.getConstantOperandVal(1) <= 4 &&
1187bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue
N,
bool AllowROR,
1188 SDValue &
Reg, SDValue &Shift) {
1189 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1199 unsigned BitSize =
N.getValueSizeInBits();
1200 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1203 Reg =
N.getOperand(0);
1204 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1205 return isWorthFoldingALU(
N,
true);
1216 if (
N.getValueType() == MVT::i32)
1224template<
signed Low,
signed High,
signed Scale>
1225bool AArch64DAGToDAGISel::SelectRDVLImm(SDValue
N, SDValue &
Imm) {
1230 if ((MulImm % std::abs(Scale)) == 0) {
1231 int64_t RDVLImm = MulImm / Scale;
1232 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1233 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1242template <
signed Low,
signed High>
1243bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue
N, SDValue &
Imm) {
1248 if (MulImm >=
Low && MulImm <=
High) {
1249 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1258bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue
N, SDValue &
Reg,
1260 unsigned ShiftVal = 0;
1275 Reg =
N.getOperand(0).getOperand(0);
1285 SDValue
Op =
N.getOperand(0);
1287 Op =
Op->getOperand(0);
1289 Op.getOperand(0).getValueType().isFixedLengthVector())
1293 Reg =
N.getOperand(0);
1297 auto isDef32 = [](SDValue
N) {
1298 unsigned Opc =
N.getOpcode();
1311 Reg.getValueType() == MVT::i32 &&
1322 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1324 return isWorthFoldingALU(
N);
1329bool AArch64DAGToDAGISel::SelectArithUXTXRegister(SDValue
N, SDValue &
Reg,
1331 unsigned ShiftVal = 0;
1345 Reg =
N.getOperand(0);
1346 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1348 return isWorthFoldingALU(
N);
1357 for (
auto *
User :
N->users()) {
1384bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue
N,
bool IsSignedImm,
1385 unsigned BW,
unsigned Size,
1389 const DataLayout &
DL = CurDAG->getDataLayout();
1390 const TargetLowering *TLI = getTargetLowering();
1394 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1400 if (CurDAG->isBaseWithConstantOffset(
N)) {
1403 int64_t RHSC =
RHS->getSExtValue();
1405 int64_t
Range = 0x1LL << (BW - 1);
1407 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1408 RHSC < (
Range << Scale)) {
1409 Base =
N.getOperand(0);
1414 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1423 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1424 Base =
N.getOperand(0);
1429 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1440 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1447bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue
N,
unsigned Size,
1448 SDValue &
Base, SDValue &OffImm) {
1450 const DataLayout &
DL = CurDAG->getDataLayout();
1451 const TargetLowering *TLI = getTargetLowering();
1455 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1460 GlobalAddressSDNode *GAN =
1462 Base =
N.getOperand(0);
1472 if (CurDAG->isBaseWithConstantOffset(
N)) {
1474 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1477 Base =
N.getOperand(0);
1482 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1490 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1498 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1507bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue
N,
unsigned Size,
1510 if (!CurDAG->isBaseWithConstantOffset(
N))
1513 int64_t RHSC =
RHS->getSExtValue();
1514 if (RHSC >= -256 && RHSC < 256) {
1515 Base =
N.getOperand(0);
1518 const TargetLowering *TLI = getTargetLowering();
1519 Base = CurDAG->getTargetFrameIndex(
1522 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1532 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1539bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue
N,
unsigned Size,
1540 bool WantExtend, SDValue &
Offset,
1541 SDValue &SignExtend) {
1559 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1565 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1568 return isWorthFoldingAddr(
N,
Size);
1571bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue
N,
unsigned Size,
1573 SDValue &SignExtend,
1577 SDValue
LHS =
N.getOperand(0);
1578 SDValue
RHS =
N.getOperand(1);
1589 const SDNode *
Node =
N.getNode();
1590 for (SDNode *UI :
Node->users()) {
1596 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1599 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1602 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1607 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1610 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1615 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1619 if (IsExtendedRegisterWorthFolding &&
1626 if (isWorthFoldingAddr(
LHS,
Size))
1631 if (IsExtendedRegisterWorthFolding &&
1638 if (isWorthFoldingAddr(
RHS,
Size))
1650 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1653 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1655 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1656 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1660bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue
N,
unsigned Size,
1662 SDValue &SignExtend,
1666 SDValue
LHS =
N.getOperand(0);
1667 SDValue
RHS =
N.getOperand(1);
1673 const SDNode *
Node =
N.getNode();
1674 for (SDNode *UI :
Node->users()) {
1691 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1701 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1702 SDValue MOVIV = SDValue(MOVI, 0);
1708 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1711 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1714 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1719 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1722 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1729 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1730 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1736 static const unsigned RegClassIDs[] = {
1737 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1738 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1739 AArch64::dsub2, AArch64::dsub3};
1745 static const unsigned RegClassIDs[] = {
1746 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1747 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1748 AArch64::qsub2, AArch64::qsub3};
1754 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1755 AArch64::ZPR3RegClassID,
1756 AArch64::ZPR4RegClassID};
1757 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1758 AArch64::zsub2, AArch64::zsub3};
1768 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1769 AArch64::ZPR4Mul4RegClassID};
1770 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1771 AArch64::zsub2, AArch64::zsub3};
1776 const unsigned RegClassIDs[],
1777 const unsigned SubRegs[]) {
1780 if (Regs.
size() == 1)
1791 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1794 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1795 Ops.push_back(Regs[i]);
1796 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1800 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1801 return SDValue(
N, 0);
1804void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1807 EVT VT =
N->getValueType(0);
1809 unsigned ExtOff = isExt;
1812 unsigned Vec0Off = ExtOff + 1;
1818 Ops.push_back(
N->getOperand(1));
1819 Ops.push_back(RegSeq);
1820 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1821 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1824static std::tuple<SDValue, SDValue>
1845 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1850 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1852 return std::make_tuple(
1857void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1860 SDValue Val =
N->getOperand(1);
1861 SDValue AUTKey =
N->getOperand(2);
1862 SDValue AUTDisc =
N->getOperand(3);
1865 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1867 SDValue AUTAddrDisc, AUTConstDisc;
1868 std::tie(AUTConstDisc, AUTAddrDisc) =
1872 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1874 if (
N->getNumOperands() > 4)
1875 Ops.push_back(
N->getOperand(4));
1878 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1879 ReplaceNode(
N, AUT);
1881 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1882 AArch64::X16, Val, SDValue());
1883 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.
getValue(1)};
1885 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1886 ReplaceNode(
N, AUT);
1890void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1900 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1905 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1906 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1908 SDValue AUTAddrDisc, AUTConstDisc;
1909 std::tie(AUTConstDisc, AUTAddrDisc) =
1912 SDValue PACAddrDisc, PACConstDisc;
1913 std::tie(PACConstDisc, PACAddrDisc) =
1916 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1917 AArch64::X16, Val, SDValue());
1920 SDValue Addend =
N->getOperand(OffsetBase + 6);
1921 SDValue IncomingChain =
N->getOperand(0);
1922 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1923 PACKey, PACConstDisc, PACAddrDisc,
1924 Addend, IncomingChain, X16Copy.
getValue(1)};
1926 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1927 MVT::i64, MVT::Other,
Ops);
1928 ReplaceNode(
N, AUTRELLOADPAC);
1930 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1931 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1933 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1934 ReplaceNode(
N, AUTPAC);
1938void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *
N) {
1950 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1951 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1953 SDValue PACAddrDisc, PACConstDisc;
1954 std::tie(PACConstDisc, PACAddrDisc) =
1957 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1958 AArch64::X17, Val, SDValue());
1959 SDValue X16Copy = CurDAG->getCopyToReg(
1960 CurDAG->getEntryNode(),
DL, AArch64::X16, AUTDisc, X17Copy.
getValue(1));
1961 SDValue X15Copy = CurDAG->getCopyToReg(
1962 CurDAG->getEntryNode(),
DL, AArch64::X15, AUTPC, X16Copy.
getValue(1));
1964 SDValue
Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1967 CurDAG->getMachineNode(AArch64::AUTPCPAC,
DL, MVT::i64,
Ops);
1968 ReplaceNode(
N, AUTPCPAC);
1971bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1973 if (
LD->isUnindexed())
1975 EVT VT =
LD->getMemoryVT();
1976 EVT DstVT =
N->getValueType(0);
1980 int OffsetVal = (int)
OffsetOp->getZExtValue();
1985 unsigned Opcode = 0;
1988 bool InsertTo64 =
false;
1991 (!Subtarget->
isLittleEndian() || (Subtarget->requiresStrictAlign() &&
1994 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1995 else if (VT == MVT::i32) {
1997 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1999 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
2001 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
2007 }
else if (VT == MVT::i16) {
2009 if (DstVT == MVT::i64)
2010 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
2012 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
2014 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
2015 InsertTo64 = DstVT == MVT::i64;
2020 }
else if (VT == MVT::i8) {
2022 if (DstVT == MVT::i64)
2023 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
2025 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
2027 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
2028 InsertTo64 = DstVT == MVT::i64;
2033 }
else if (VT == MVT::f16) {
2034 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2035 }
else if (VT == MVT::bf16) {
2036 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2037 }
else if (VT == MVT::f32) {
2038 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
2039 }
else if (VT == MVT::f64 || (VT.
is64BitVector() && !UseLd1)) {
2040 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
2042 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
2044 if (IsPre || OffsetVal != 8)
2048 Opcode = AArch64::LD1Onev8b_POST;
2051 Opcode = AArch64::LD1Onev4h_POST;
2054 Opcode = AArch64::LD1Onev2s_POST;
2057 Opcode = AArch64::LD1Onev1d_POST;
2063 if (IsPre || OffsetVal != 16)
2067 Opcode = AArch64::LD1Onev16b_POST;
2070 Opcode = AArch64::LD1Onev8h_POST;
2073 Opcode = AArch64::LD1Onev4s_POST;
2076 Opcode = AArch64::LD1Onev2d_POST;
2083 SDValue Chain =
LD->getChain();
2084 SDValue
Base =
LD->getBasePtr();
2087 SDValue
Offset = UseLd1 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
2088 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
2090 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
2098 SDValue LoadedVal = SDValue(Res, 1);
2100 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
2101 LoadedVal = SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
2102 MVT::i64, LoadedVal, SubReg),
2106 ReplaceUses(SDValue(
N, 0), LoadedVal);
2107 ReplaceUses(SDValue(
N, 1), SDValue(Res, 0));
2108 ReplaceUses(SDValue(
N, 2), SDValue(Res, 2));
2109 CurDAG->RemoveDeadNode(
N);
2113void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
2114 unsigned SubRegIdx) {
2116 EVT VT =
N->getValueType(0);
2119 SDValue
Ops[] = {
N->getOperand(2),
2122 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2124 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2125 SDValue SuperReg = SDValue(Ld, 0);
2126 for (
unsigned i = 0; i < NumVecs; ++i)
2127 ReplaceUses(SDValue(
N, i),
2128 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2130 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2135 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2139 CurDAG->RemoveDeadNode(
N);
2142void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2143 unsigned Opc,
unsigned SubRegIdx) {
2145 EVT VT =
N->getValueType(0);
2148 SDValue
Ops[] = {
N->getOperand(1),
2152 const EVT ResTys[] = {MVT::i64,
2153 MVT::Untyped, MVT::Other};
2155 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2158 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2161 SDValue SuperReg = SDValue(Ld, 1);
2163 ReplaceUses(SDValue(
N, 0), SuperReg);
2165 for (
unsigned i = 0; i < NumVecs; ++i)
2166 ReplaceUses(SDValue(
N, i),
2167 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2174 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2175 CurDAG->RemoveDeadNode(
N);
2181std::tuple<unsigned, SDValue, SDValue>
2182AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2184 const SDValue &OldBase,
2185 const SDValue &OldOffset,
2187 SDValue NewBase = OldBase;
2188 SDValue NewOffset = OldOffset;
2190 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2191 N, OldBase, NewBase, NewOffset);
2195 const bool IsRegReg =
2196 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2199 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2212template <SelectTypeKind Kind>
2224 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2229 if (EltVT != MVT::i1)
2233 if (EltVT == MVT::bf16)
2235 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2265void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2268 if (
Imm->getZExtValue() > 1)
2272 EVT VT =
N->getValueType(0);
2273 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2274 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2275 SDValue SuperReg = SDValue(WhilePair, 0);
2277 for (
unsigned I = 0;
I < 2; ++
I)
2278 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2279 AArch64::psub0 +
I,
DL, VT, SuperReg));
2281 CurDAG->RemoveDeadNode(
N);
2284void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2286 EVT VT =
N->getValueType(0);
2288 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2290 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2291 SDValue SuperReg = SDValue(WhilePair, 0);
2293 for (
unsigned I = 0;
I < 2; ++
I)
2294 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2295 AArch64::psub0 +
I,
DL, VT, SuperReg));
2297 CurDAG->RemoveDeadNode(
N);
2300void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2302 EVT VT =
N->getValueType(0);
2304 SDValue
Ops = createZTuple(Regs);
2306 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2307 SDValue SuperReg = SDValue(Intrinsic, 0);
2308 for (
unsigned i = 0; i < NumVecs; ++i)
2309 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2310 AArch64::zsub0 + i,
DL, VT, SuperReg));
2312 CurDAG->RemoveDeadNode(
N);
2315void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2318 EVT VT =
N->getValueType(0);
2320 Ops.push_back(
N->getOperand(0));
2323 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2324 SDValue SuperReg = SDValue(Instruction, 0);
2326 for (
unsigned i = 0; i < NumVecs; ++i)
2327 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2328 AArch64::zsub0 + i,
DL, VT, SuperReg));
2331 unsigned ChainIdx = NumVecs;
2332 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Instruction, 1));
2333 CurDAG->RemoveDeadNode(
N);
2336void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2341 assert(Opcode != 0 &&
"Unexpected opcode");
2344 EVT VT =
N->getValueType(0);
2345 SDUse *OpsIter =
N->op_begin() + 1;
2348 auto GetMultiVecOperand = [&]() {
2351 return createZMulTuple(Regs);
2355 Ops.push_back(*OpsIter++);
2357 Ops.push_back(GetMultiVecOperand());
2359 Ops.push_back(GetMultiVecOperand());
2361 Ops.push_back(*OpsIter++);
2364 Ops.append(OpsIter,
N->op_end());
2366 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2367 SDValue SuperReg = SDValue(Intrinsic, 0);
2368 for (
unsigned i = 0; i < NumVecs; ++i)
2369 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2370 AArch64::zsub0 + i,
DL, VT, SuperReg));
2372 CurDAG->RemoveDeadNode(
N);
2375void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2376 unsigned Scale,
unsigned Opc_ri,
2377 unsigned Opc_rr,
bool IsIntr) {
2378 assert(Scale < 5 &&
"Invalid scaling value.");
2380 EVT VT =
N->getValueType(0);
2387 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2388 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2390 SDValue
Ops[] = {
N->getOperand(IsIntr ? 2 : 1),
2394 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2396 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2397 SDValue SuperReg = SDValue(
Load, 0);
2398 for (
unsigned i = 0; i < NumVecs; ++i)
2399 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2400 AArch64::zsub0 + i,
DL, VT, SuperReg));
2403 unsigned ChainIdx = NumVecs;
2404 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2405 CurDAG->RemoveDeadNode(
N);
2408void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2413 assert(Scale < 4 &&
"Invalid scaling value.");
2415 EVT VT =
N->getValueType(0);
2420 SDValue
Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
2423 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2425 SDValue
Ops[] = {PNg,
2429 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2431 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2432 SDValue SuperReg = SDValue(
Load, 0);
2433 for (
unsigned i = 0; i < NumVecs; ++i)
2434 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2435 AArch64::zsub0 + i,
DL, VT, SuperReg));
2438 unsigned ChainIdx = NumVecs;
2439 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2440 CurDAG->RemoveDeadNode(
N);
2443void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2445 if (
N->getValueType(0) != MVT::nxv4f32)
2447 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2450void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2451 unsigned NumOutVecs,
2455 if (
Imm->getZExtValue() > MaxImm)
2459 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2462 SDValue Chain =
Node->getOperand(0);
2463 SDValue
Ops[] = {ZtValue,
Node->getOperand(3),
Node->getOperand(4), Chain};
2465 EVT VT =
Node->getValueType(0);
2468 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2469 SDValue SuperReg = SDValue(Instruction, 0);
2471 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2472 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2473 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2476 unsigned ChainIdx = NumOutVecs;
2477 ReplaceUses(SDValue(Node, ChainIdx), SDValue(Instruction, 1));
2478 CurDAG->RemoveDeadNode(Node);
2481void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2482 unsigned NumIndexVecs) {
2483 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2484 "unexpected number of index vectors");
2486 constexpr unsigned FirstIndexOp = 3;
2487 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2489 if (!
Imm ||
Imm->getZExtValue() > 1)
2495 unsigned Lane =
Imm->getZExtValue();
2496 unsigned IndexOp = FirstIndexOp;
2497 if (NumIndexVecs == 3)
2500 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2501 SDValue IndexTuple =
2502 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2503 SDValue
Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2506 EVT VT =
Node->getValueType(0);
2508 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2509 SDValue SuperReg = SDValue(Instruction, 0);
2511 for (
unsigned I = 0;
I < 4; ++
I)
2512 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2513 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2515 CurDAG->RemoveDeadNode(Node);
2518void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2519 unsigned NumOutVecs,
2521 unsigned NumInVecs) {
2522 assert((NumInVecs == 2 || NumInVecs == 3) &&
2523 "unexpected number of input vectors");
2526 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2530 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2531 SDValue
Ops[] = {ZtValue, ZTuple,
Node->getOperand(0)};
2534 EVT VT =
Node->getValueType(0);
2537 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2538 SDValue SuperReg = SDValue(Instruction, 0);
2540 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2541 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2542 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2544 ReplaceUses(SDValue(Node, NumOutVecs), SDValue(Instruction, 1));
2545 CurDAG->RemoveDeadNode(Node);
2548void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2551 EVT VT =
N->getValueType(0);
2554 SDValue Zd = createZMulTuple(Regs);
2555 SDValue Zn =
N->getOperand(1 + NumVecs);
2556 SDValue Zm =
N->getOperand(2 + NumVecs);
2558 SDValue
Ops[] = {Zd, Zn, Zm};
2561 SDValue SuperReg = SDValue(Intrinsic, 0);
2562 for (
unsigned i = 0; i < NumVecs; ++i)
2563 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2564 AArch64::zsub0 + i,
DL, VT, SuperReg));
2566 CurDAG->RemoveDeadNode(
N);
2596template <
unsigned MaxIdx,
unsigned Scale>
2597void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2598 unsigned BaseReg,
unsigned Op) {
2599 unsigned TileNum = 0;
2600 if (BaseReg != AArch64::ZA)
2601 TileNum =
N->getConstantOperandVal(2);
2607 if (BaseReg == AArch64::ZA)
2612 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2616 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2618 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2620 EVT VT =
N->getValueType(0);
2621 for (
unsigned I = 0;
I < NumVecs; ++
I)
2622 ReplaceUses(SDValue(
N,
I),
2623 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2626 unsigned ChainIdx = NumVecs;
2627 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2628 CurDAG->RemoveDeadNode(
N);
2631void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2632 unsigned Op,
unsigned MaxIdx,
2633 unsigned Scale,
unsigned BaseReg) {
2638 if (BaseReg != AArch64::ZA)
2642 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2649 if (BaseReg != AArch64::ZA )
2650 Ops.push_back(
N->getOperand(2));
2653 Ops.push_back(
N->getOperand(0));
2654 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2656 EVT VT =
N->getValueType(0);
2657 for (
unsigned I = 0;
I < NumVecs; ++
I)
2658 ReplaceUses(SDValue(
N,
I),
2659 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2663 unsigned ChainIdx = NumVecs;
2664 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2665 CurDAG->RemoveDeadNode(
N);
2668void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2669 unsigned NumOutVecs,
2673 EVT VT =
N->getValueType(0);
2674 unsigned NumInVecs =
N->getNumOperands() - 1;
2678 assert((NumInVecs == 2 || NumInVecs == 4) &&
2679 "Don't know how to handle multi-register input!");
2681 Ops.push_back(createZMulTuple(Regs));
2684 for (
unsigned I = 0;
I < NumInVecs;
I++)
2685 Ops.push_back(
N->getOperand(1 +
I));
2688 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2689 SDValue SuperReg = SDValue(Res, 0);
2691 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2692 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2693 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2694 CurDAG->RemoveDeadNode(
N);
2697void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2700 EVT VT =
N->getOperand(2)->getValueType(0);
2708 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2717void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2718 unsigned Scale,
unsigned Opc_rr,
2724 SDValue RegSeq = createZTuple(Regs);
2730 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2731 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2737 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2746void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2749 EVT VT =
N->getOperand(2)->getValueType(0);
2750 const EVT ResTys[] = {MVT::i64,
2758 SDValue
Ops[] = {RegSeq,
2762 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2780 SDValue operator()(SDValue V64Reg) {
2806void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2809 EVT VT =
N->getValueType(0);
2821 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2823 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2825 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2827 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2828 SDValue SuperReg = SDValue(Ld, 0);
2831 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2832 AArch64::qsub2, AArch64::qsub3 };
2833 for (
unsigned i = 0; i < NumVecs; ++i) {
2834 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2837 ReplaceUses(SDValue(
N, i), NV);
2840 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2841 CurDAG->RemoveDeadNode(
N);
2844void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2847 EVT VT =
N->getValueType(0);
2859 const EVT ResTys[] = {MVT::i64,
2862 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2864 SDValue
Ops[] = {RegSeq,
2865 CurDAG->getTargetConstant(LaneNo, dl,
2870 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2873 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2876 SDValue SuperReg = SDValue(Ld, 1);
2878 ReplaceUses(SDValue(
N, 0),
2882 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2883 AArch64::qsub2, AArch64::qsub3 };
2884 for (
unsigned i = 0; i < NumVecs; ++i) {
2885 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2889 ReplaceUses(SDValue(
N, i), NV);
2894 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2895 CurDAG->RemoveDeadNode(
N);
2898void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2901 EVT VT =
N->getOperand(2)->getValueType(0);
2913 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2915 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2917 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2926void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2929 EVT VT =
N->getOperand(2)->getValueType(0);
2941 const EVT ResTys[] = {MVT::i64,
2944 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2946 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2950 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2961 unsigned &LSB,
unsigned &MSB,
2962 unsigned NumberOfIgnoredLowBits,
2963 bool BiggerPattern) {
2965 "N must be a AND operation to call this function");
2967 EVT VT =
N->getValueType(0);
2972 assert((VT == MVT::i32 || VT == MVT::i64) &&
2973 "Type checking must have been done before calling this function");
2987 const SDNode *Op0 =
N->getOperand(0).getNode();
2994 if (AndImm & (AndImm + 1))
2997 bool ClampMSB =
false;
3017 ClampMSB = (VT == MVT::i32);
3018 }
else if (BiggerPattern) {
3024 Opd0 =
N->getOperand(0);
3030 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
3033 <<
": Found large shift immediate, this should not happen\n"));
3047 MSB = MSB > 31 ? 31 : MSB;
3049 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3054 SDValue &Opd0,
unsigned &Immr,
3058 EVT VT =
N->getValueType(0);
3060 assert((VT == MVT::i32 || VT == MVT::i64) &&
3061 "Type checking must have been done before calling this function");
3065 Op =
Op->getOperand(0);
3066 VT =
Op->getValueType(0);
3075 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3079 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
3080 Opd0 =
Op.getOperand(0);
3082 Imms = ShiftImm + Width - 1;
3110 Opd0 =
N->getOperand(0).getOperand(0);
3120 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3127 unsigned &Immr,
unsigned &Imms,
3128 bool BiggerPattern) {
3130 "N must be a SHR/SRA operation to call this function");
3132 EVT VT =
N->getValueType(0);
3137 assert((VT == MVT::i32 || VT == MVT::i64) &&
3138 "Type checking must have been done before calling this function");
3148 Opd0 =
N->getOperand(0).getOperand(0);
3149 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3155 Opd0 =
N->getOperand(0).getOperand(0);
3158 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3159 }
else if (BiggerPattern) {
3163 Opd0 =
N->getOperand(0);
3172 <<
": Found large shift immediate, this should not happen\n"));
3181 "bad amount in shift node!");
3182 int immr = SrlImm - ShlImm;
3187 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3189 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3194 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3195 unsigned NumberOfIgnoredLowBits = 0,
3196 bool BiggerPattern =
false) {
3197 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3200 switch (
N->getOpcode()) {
3202 if (!
N->isMachineOpcode())
3207 NumberOfIgnoredLowBits, BiggerPattern);
3216 unsigned NOpc =
N->getMachineOpcode();
3220 case AArch64::SBFMWri:
3221 case AArch64::UBFMWri:
3222 case AArch64::SBFMXri:
3223 case AArch64::UBFMXri:
3225 Opd0 =
N->getOperand(0);
3226 Immr =
N->getConstantOperandVal(1);
3227 Imms =
N->getConstantOperandVal(2);
3234bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3235 unsigned Opc, Immr, Imms;
3240 EVT VT =
N->getValueType(0);
3245 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3246 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3247 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3249 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3250 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3251 MVT::i32, SDValue(BFM, 0));
3256 SDValue
Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3257 CurDAG->getTargetConstant(Imms, dl, VT)};
3258 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3267 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3268 assert((VT == MVT::i32 || VT == MVT::i64) &&
3269 "i32 or i64 mask type expected!");
3273 APInt SignificantDstMask =
3277 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3278 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3311 APInt OpUsefulBits(UsefulBits);
3315 OpUsefulBits <<= MSB -
Imm + 1;
3320 OpUsefulBits <<=
Imm;
3322 OpUsefulBits <<= MSB + 1;
3331 UsefulBits &= OpUsefulBits;
3348 APInt Mask(UsefulBits);
3349 Mask.clearAllBits();
3357 Mask.lshrInPlace(ShiftAmt);
3363 Mask.lshrInPlace(ShiftAmt);
3379 APInt OpUsefulBits(UsefulBits);
3393 OpUsefulBits <<= Width;
3396 if (
Op.getOperand(1) == Orig) {
3398 Mask = ResultUsefulBits & OpUsefulBits;
3402 if (
Op.getOperand(0) == Orig)
3404 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3410 OpUsefulBits <<= Width;
3412 OpUsefulBits <<= LSB;
3414 if (
Op.getOperand(1) == Orig) {
3416 Mask = ResultUsefulBits & OpUsefulBits;
3417 Mask.lshrInPlace(LSB);
3420 if (
Op.getOperand(0) == Orig)
3421 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3438 case AArch64::ANDSWri:
3439 case AArch64::ANDSXri:
3440 case AArch64::ANDWri:
3441 case AArch64::ANDXri:
3445 case AArch64::UBFMWri:
3446 case AArch64::UBFMXri:
3449 case AArch64::ORRWrs:
3450 case AArch64::ORRXrs:
3455 case AArch64::BFMWri:
3456 case AArch64::BFMXri:
3459 case AArch64::STRBBui:
3460 case AArch64::STURBBi:
3466 case AArch64::STRHHui:
3467 case AArch64::STURHHi:
3480 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3482 UsefulBits =
APInt(Bitwidth, 0);
3491 UsersUsefulBits |= UsefulBitsForUse;
3496 UsefulBits &= UsersUsefulBits;
3506 EVT VT =
Op.getValueType();
3509 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3512 if (ShlAmount > 0) {
3515 UBFMOpc, dl, VT,
Op,
3520 assert(ShlAmount < 0 &&
"expected right shift");
3521 int ShrAmount = -ShlAmount;
3534 SDValue &Src,
int &DstLSB,
3541 SDValue &Src,
int &DstLSB,
3547 bool BiggerPattern,
SDValue &Src,
3548 int &DstLSB,
int &Width) {
3549 EVT VT =
Op.getValueType();
3562 switch (
Op.getOpcode()) {
3567 NonZeroBits, Src, DstLSB, Width);
3570 NonZeroBits, Src, DstLSB, Width);
3583 EVT VT =
Op.getValueType();
3584 assert((VT == MVT::i32 || VT == MVT::i64) &&
3585 "Caller guarantees VT is one of i32 or i64");
3598 assert((~AndImm & NonZeroBits) == 0 &&
3599 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3628 if (!BiggerPattern && !AndOp0.
hasOneUse())
3647 <<
"Found large Width in bit-field-positioning -- this indicates no "
3648 "proper combining / constant folding was performed\n");
3657 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3672 "Op.getNode() should be a SHL node to call this function");
3674 "Op.getNode() should shift ShlImm to call this function");
3681 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3705 EVT VT =
Op.getValueType();
3706 assert((VT == MVT::i32 || VT == MVT::i64) &&
3707 "Caller guarantees that type is i32 or i64");
3714 if (!BiggerPattern && !
Op.hasOneUse())
3723 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3731 assert(VT == MVT::i32 || VT == MVT::i64);
3742 EVT VT =
N->getValueType(0);
3743 if (VT != MVT::i32 && VT != MVT::i64)
3761 if (!
And.hasOneUse() ||
3778 if ((OrImm & NotKnownZero) != 0) {
3790 unsigned ImmS = Width - 1;
3796 bool IsBFI = LSB != 0;
3801 unsigned OrChunks = 0, BFIChunks = 0;
3802 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3803 if (((OrImm >> Shift) & 0xFFFF) != 0)
3805 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3808 if (BFIChunks > OrChunks)
3814 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3822 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3831 if (!Dst.hasOneUse())
3834 EVT VT = Dst.getValueType();
3835 assert((VT == MVT::i32 || VT == MVT::i64) &&
3836 "Caller should guarantee that VT is one of i32 or i64");
3864 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3865 unsigned MaskWidth =
3868 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3874 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3875 ShiftedOperand =
SDValue(UBFMNode, 0);
3904 const bool BiggerPattern) {
3905 EVT VT =
N->getValueType(0);
3906 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3907 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3908 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3909 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3910 assert((VT == MVT::i32 || VT == MVT::i64) &&
3911 "Expect result type to be i32 or i64 since N is combinable to BFM");
3918 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3921 if (BiggerPattern) {
3944 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
4006 EVT VT =
N->getValueType(0);
4007 if (VT != MVT::i32 && VT != MVT::i64)
4015 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
4016 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
4036 for (
int I = 0;
I < 4; ++
I) {
4039 unsigned ImmR, ImmS;
4040 bool BiggerPattern =
I / 2;
4041 SDValue OrOpd0Val =
N->getOperand(
I % 2);
4043 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
4049 NumberOfIgnoredLowBits, BiggerPattern)) {
4052 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
4053 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
4058 Width = ImmS - ImmR + 1;
4069 Src, DstLSB, Width)) {
4077 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
4087 APInt BitsToBeInserted =
4090 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4114 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4147 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4149 if (Src->hasOneUse() &&
4152 Src = Src->getOperand(0);
4162 unsigned ImmS = Width - 1;
4168 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4176bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4185 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4198bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4202 EVT VT =
N->getValueType(0);
4203 if (VT != MVT::i32 && VT != MVT::i64)
4209 Op0, DstLSB, Width))
4215 unsigned ImmS = Width - 1;
4218 SDValue
Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4219 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4220 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4221 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4228 bool isReciprocal) {
4231 FVal = CN->getValueAPF();
4234 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4244 if (
unsigned FBits =
4257 bool isReciprocal) {
4258 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4259 N.getValueType().getScalarSizeInBits() ==
4260 N.getOperand(0).getValueType().getScalarSizeInBits())
4261 N =
N.getOperand(0);
4263 auto ImmToFloat = [RegWidth](
APInt Imm) {
4277 switch (
N->getOpcode()) {
4278 case AArch64ISD::MOVIshift:
4279 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4280 <<
N.getConstantOperandVal(1)));
4282 case AArch64ISD::FMOV:
4283 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4285 case AArch64ISD::DUP:
4287 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4295 if (
unsigned FBits =
4304bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue
N, SDValue &FixedPos,
4305 unsigned RegWidth) {
4310bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(SDValue
N, SDValue &FixedPos,
4311 unsigned RegWidth) {
4313 CurDAG,
N, FixedPos, RegWidth,
false);
4316bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(SDValue
N,
4318 unsigned RegWidth) {
4320 CurDAG,
N, FixedPos, RegWidth,
true);
4323bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(SDValue
N,
4325 unsigned RegWidth) {
4335 RegString.
split(Fields,
':');
4337 if (Fields.
size() == 1)
4341 &&
"Invalid number of fields in read register string");
4344 bool AllIntFields =
true;
4348 AllIntFields &= !
Field.getAsInteger(10, IntField);
4349 Ops.push_back(IntField);
4353 "Unexpected non-integer value in special register string.");
4358 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4366bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4368 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4371 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4373 unsigned Opcode64Bit = AArch64::MRS;
4378 const auto *TheReg =
4379 AArch64SysReg::lookupSysRegByName(RegString->getString());
4380 if (TheReg && TheReg->Readable &&
4381 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4382 Imm = TheReg->Encoding;
4388 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4389 Opcode64Bit = AArch64::ADR;
4398 RegString->getString());
4399 unsigned PseudoOp = 0;
4400 if (AArch64::GPR64RegClass.
contains(PReg))
4401 PseudoOp = AArch64::READ_REGISTER_GPR64;
4402 else if (AArch64::FPR64RegClass.
contains(PReg))
4403 PseudoOp = AArch64::READ_REGISTER_FPR64;
4404 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4405 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4406 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4415 SDValue InChain =
N->getOperand(0);
4416 SDValue SysRegImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
4417 if (!ReadIs128Bit) {
4418 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4419 {SysRegImm, InChain});
4421 SDNode *MRRS = CurDAG->getMachineNode(
4423 {MVT::Untyped , MVT::Other },
4424 {SysRegImm, InChain});
4428 SDValue
Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4430 SDValue
Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4432 SDValue OutChain = SDValue(MRRS, 1);
4434 ReplaceUses(SDValue(
N, 0),
Lo);
4435 ReplaceUses(SDValue(
N, 1),
Hi);
4436 ReplaceUses(SDValue(
N, 2), OutChain);
4445bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4447 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4450 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4452 if (!WriteIs128Bit) {
4458 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4461 "Expected a constant integer expression.");
4462 unsigned Reg = PMapper->Encoding;
4463 uint64_t Immed =
N->getConstantOperandVal(2);
4464 CurDAG->SelectNodeTo(
4465 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4466 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4472 if (trySelectPState(
4473 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4474 AArch64::MSRpstateImm4))
4476 if (trySelectPState(
4477 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4478 AArch64::MSRpstateImm1))
4487 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4488 if (TheReg && TheReg->Writeable &&
4489 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4490 Imm = TheReg->Encoding;
4500 RegString->getString());
4501 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4502 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4503 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4504 N->getOperand(2).getValueType() == MVT::i64) {
4506 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4507 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4508 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4509 MVT::Other, {RegOp,
Copy});
4510 ReplaceUses(SDValue(
N, 0), SDValue(FakeUse, 0));
4511 CurDAG->RemoveDeadNode(
N);
4519 if (!WriteIs128Bit) {
4520 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4521 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4522 N->getOperand(2), InChain);
4526 SDNode *Pair = CurDAG->getMachineNode(
4527 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4528 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4531 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4533 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4535 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4536 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4537 SDValue(Pair, 0), InChain);
4544bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4549 if (Subtarget->hasLSE())
return false;
4551 if (MemTy == MVT::i8)
4552 Opcode = AArch64::CMP_SWAP_8;
4553 else if (MemTy == MVT::i16)
4554 Opcode = AArch64::CMP_SWAP_16;
4555 else if (MemTy == MVT::i32)
4556 Opcode = AArch64::CMP_SWAP_32;
4557 else if (MemTy == MVT::i64)
4558 Opcode = AArch64::CMP_SWAP_64;
4562 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4563 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4565 SDNode *CmpSwap = CurDAG->getMachineNode(
4567 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4572 ReplaceUses(SDValue(
N, 0), SDValue(CmpSwap, 0));
4573 ReplaceUses(SDValue(
N, 1), SDValue(CmpSwap, 2));
4574 CurDAG->RemoveDeadNode(
N);
4580AArch64DAGToDAGISel::decodeMemoryHintFlags(MachineMemOperand *MMO)
const {
4581 int MemoryHint = -1;
4584 return AArch64MemoryHint::NONE;
4597bool AArch64DAGToDAGISel::isAtomicMemoryHint(SDNode *
N,
4602bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue
N, MVT VT, SDValue &
Imm,
4603 SDValue &Shift,
bool Negate) {
4610 return SelectSVEAddSubImm(SDLoc(
N), Val, VT,
Imm, Shift, Negate);
4613bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4614 SDValue &
Imm, SDValue &Shift,
4622 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4629 if ((Val & ~0xff) == 0) {
4630 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4635 if ((Val & ~0xff00) == 0) {
4636 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4648bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(SDValue
N, MVT VT,
4649 SDValue &
Imm, SDValue &Shift,
4672 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4673 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4680 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4681 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4685 if (Val <= 65280 && Val % 256 == 0) {
4686 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4687 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4698bool AArch64DAGToDAGISel::SelectSVECpyDupImm(SDValue
N, MVT VT, SDValue &
Imm,
4708 int32_t ImmVal, ShiftVal;
4713 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4714 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4718bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDValue
N, SDValue &
Imm) {
4720 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(),
Imm);
4724bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4727 if (ImmVal >= -128 && ImmVal < 128) {
4728 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4734bool AArch64DAGToDAGISel::SelectSVEArithImm(SDValue
N, MVT VT, SDValue &
Imm) {
4736 uint64_t ImmVal = CNode->getZExtValue();
4746 ImmVal &= 0xFFFFFFFF;
4755 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4762bool AArch64DAGToDAGISel::SelectSVELogicalImm(SDValue
N, MVT VT, SDValue &
Imm,
4766 ImmVal = CI->getZExtValue();
4768 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4779 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4788bool AArch64DAGToDAGISel::SelectSVEShiftImm(SDValue
N,
uint64_t Low,
4792 uint64_t ImmVal = CN->getZExtValue();
4799 if (ImmVal >
High) {
4800 if (!AllowSaturation)
4805 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4812bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4820 SDValue IRG_SP =
N->getOperand(2);
4826 const TargetLowering *TLI = getTargetLowering();
4829 SDValue FiOp = CurDAG->getTargetFrameIndex(
4831 int TagOffset =
N->getConstantOperandVal(3);
4833 SDNode *
Out = CurDAG->getMachineNode(
4834 AArch64::TAGPstack,
DL, MVT::i64,
4835 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4836 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4837 ReplaceNode(
N, Out);
4841void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4843 "llvm.aarch64.tagp third argument must be an immediate");
4844 if (trySelectStackSlotTagP(
N))
4851 int TagOffset =
N->getConstantOperandVal(3);
4852 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4853 {
N->getOperand(1),
N->getOperand(2)});
4854 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4855 {SDValue(N1, 0),
N->getOperand(2)});
4856 SDNode *N3 = CurDAG->getMachineNode(
4857 AArch64::ADDG,
DL, MVT::i64,
4858 {SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4859 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4863bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4867 if (
N->getConstantOperandVal(2) != 0)
4869 if (!
N->getOperand(0).isUndef())
4873 EVT VT =
N->getValueType(0);
4874 EVT InVT =
N->getOperand(1).getValueType();
4885 "Expected to insert into a packed scalable vector!");
4888 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4889 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4890 N->getOperand(1), RC));
4894bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4898 if (
N->getConstantOperandVal(1) != 0)
4902 EVT VT =
N->getValueType(0);
4903 EVT InVT =
N->getOperand(0).getValueType();
4914 "Expected to extract from a packed scalable vector!");
4917 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4918 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4919 N->getOperand(0), RC));
4923bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
4926 SDValue N0 =
N->getOperand(0);
4929 EVT VT =
N->getValueType(0);
4942 (Subtarget->hasSVE2() ||
4943 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
4944 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4947 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
4951 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
4952 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
4953 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
4960 bool IsXOROperand =
true;
4962 IsXOROperand =
false;
4968 APInt ShlAmt, ShrAmt;
4976 if (!IsXOROperand) {
4977 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
4978 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
4979 SDValue MOVIV = SDValue(MOV, 0);
4981 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
4982 SDNode *SubRegToReg =
4983 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
4986 R2 = SDValue(SubRegToReg, 0);
4994 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4995 AArch64::XAR_ZZZI_D})) {
4996 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5021 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5031 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5039 bool IsXOROperand =
true;
5041 IsXOROperand =
false;
5044 R1 =
XOR.getOperand(0);
5045 R2 =
XOR.getOperand(1);
5051 SDValue
Imm = CurDAG->getTargetConstant(
5055 if (ShAmt + HsAmt != VTSizeInBits)
5058 if (!IsXOROperand) {
5059 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
5061 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5062 SDValue MOVIV = SDValue(MOV, 0);
5070 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5075 SDValue UndefQ = SDValue(
5076 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5077 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5079 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5082 if (
R2.getValueType() == VT)
5083 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5088 SDValue SubReg = CurDAG->getTargetConstant(
5091 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5096 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5102 SDNode *XAR =
nullptr;
5106 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5107 AArch64::XAR_ZZZI_D}))
5108 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5110 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5113 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5119 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5120 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5121 SDValue(XAR, 0), ZSub);
5123 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5124 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5125 SDValue(Q, 0), DSub);
5127 SDValue SubReg = CurDAG->getTargetConstant(
5130 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5131 SDValue(XAR, 0), SubReg);
5134 ReplaceNode(
N, XAR);
5141 assert(VT == MVT::i32 || VT == MVT::i64);
5143 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5146void AArch64DAGToDAGISel::Select(SDNode *Node) {
5148 if (
Node->isMachineOpcode()) {
5150 Node->setNodeId(-1);
5155 EVT VT =
Node->getValueType(0);
5157 switch (
Node->getOpcode()) {
5162 if (SelectCMP_SWAP(Node))
5167 case AArch64ISD::MRRS:
5168 if (tryReadRegister(Node))
5173 case AArch64ISD::MSRR:
5174 if (tryWriteRegister(Node))
5181 if (tryIndexedLoad(Node))
5190 if (tryBitfieldExtractOp(Node))
5192 if (tryBitfieldInsertInZeroOp(Node))
5200 if (tryBitfieldInsertOp(Node))
5202 if (trySelectXAR(Node))
5207 if (trySelectCastScalableToFixedLengthVector(Node))
5213 if (trySelectCastFixedLengthToScalableVector(Node))
5218 case AArch64ISD::CSEL:
5219 if (tryFoldCselToFMaxMin(Node))
5227 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5238 const TargetLowering *TLI = getTargetLowering();
5239 SDValue TFI = CurDAG->getTargetFrameIndex(
5242 SDValue
Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5243 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5244 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5248 unsigned IntNo =
Node->getConstantOperandVal(1);
5252 case Intrinsic::aarch64_gcsss: {
5254 SDValue Chain =
Node->getOperand(0);
5255 SDValue Val =
Node->getOperand(2);
5256 SDValue
Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5258 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5259 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5260 MVT::Other, Zero, SDValue(SS1, 0));
5261 ReplaceNode(Node, SS2);
5264 case Intrinsic::aarch64_ldaxp:
5265 case Intrinsic::aarch64_ldxp: {
5267 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5268 SDValue MemAddr =
Node->getOperand(2);
5270 SDValue Chain =
Node->getOperand(0);
5272 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5273 MVT::Other, MemAddr, Chain);
5276 MachineMemOperand *MemOp =
5279 ReplaceNode(Node, Ld);
5282 case Intrinsic::aarch64_stlxp:
5283 case Intrinsic::aarch64_stxp: {
5285 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5287 SDValue Chain =
Node->getOperand(0);
5288 SDValue ValLo =
Node->getOperand(2);
5289 SDValue ValHi =
Node->getOperand(3);
5290 SDValue MemAddr =
Node->getOperand(4);
5293 SDValue
Ops[] = {ValLo, ValHi, MemAddr, Chain};
5295 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5297 MachineMemOperand *MemOp =
5301 ReplaceNode(Node, St);
5304 case Intrinsic::aarch64_neon_ld1x2:
5305 if (VT == MVT::v8i8) {
5306 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5308 }
else if (VT == MVT::v16i8) {
5309 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5311 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5312 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5314 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5315 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5317 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5318 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5320 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5321 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5323 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5324 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5326 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5327 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5331 case Intrinsic::aarch64_neon_ld1x3:
5332 if (VT == MVT::v8i8) {
5333 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5335 }
else if (VT == MVT::v16i8) {
5336 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5338 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5339 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5341 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5342 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5344 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5345 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5347 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5348 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5350 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5351 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5353 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5354 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5358 case Intrinsic::aarch64_neon_ld1x4:
5359 if (VT == MVT::v8i8) {
5360 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5362 }
else if (VT == MVT::v16i8) {
5363 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5365 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5366 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5368 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5369 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5371 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5372 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5374 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5375 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5377 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5378 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5380 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5381 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5385 case Intrinsic::aarch64_neon_ld2:
5386 if (VT == MVT::v8i8) {
5387 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5389 }
else if (VT == MVT::v16i8) {
5390 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5392 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5393 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5395 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5396 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5398 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5399 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5401 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5402 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5404 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5405 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5407 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5408 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5412 case Intrinsic::aarch64_neon_ld3:
5413 if (VT == MVT::v8i8) {
5414 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5416 }
else if (VT == MVT::v16i8) {
5417 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5419 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5420 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5422 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5423 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5425 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5426 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5428 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5429 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5431 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5432 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5434 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5435 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5439 case Intrinsic::aarch64_neon_ld4:
5440 if (VT == MVT::v8i8) {
5441 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5443 }
else if (VT == MVT::v16i8) {
5444 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5446 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5447 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5449 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5450 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5452 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5453 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5455 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5456 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5458 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5459 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5461 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5462 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5466 case Intrinsic::aarch64_neon_ld2r:
5467 if (VT == MVT::v8i8) {
5468 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5470 }
else if (VT == MVT::v16i8) {
5471 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5473 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5474 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5476 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5477 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5479 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5480 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5482 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5483 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5485 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5486 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5488 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5489 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5493 case Intrinsic::aarch64_neon_ld3r:
5494 if (VT == MVT::v8i8) {
5495 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5497 }
else if (VT == MVT::v16i8) {
5498 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5500 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5501 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5503 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5504 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5506 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5507 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5509 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5510 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5512 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5513 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5515 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5516 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5520 case Intrinsic::aarch64_neon_ld4r:
5521 if (VT == MVT::v8i8) {
5522 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5524 }
else if (VT == MVT::v16i8) {
5525 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5527 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5528 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5530 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5531 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5533 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5534 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5536 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5537 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5539 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5540 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5542 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5543 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5547 case Intrinsic::aarch64_neon_ld2lane:
5548 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5549 SelectLoadLane(Node, 2, AArch64::LD2i8);
5551 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5552 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5553 SelectLoadLane(Node, 2, AArch64::LD2i16);
5555 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5557 SelectLoadLane(Node, 2, AArch64::LD2i32);
5559 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5561 SelectLoadLane(Node, 2, AArch64::LD2i64);
5565 case Intrinsic::aarch64_neon_ld3lane:
5566 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5567 SelectLoadLane(Node, 3, AArch64::LD3i8);
5569 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5570 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5571 SelectLoadLane(Node, 3, AArch64::LD3i16);
5573 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5575 SelectLoadLane(Node, 3, AArch64::LD3i32);
5577 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5579 SelectLoadLane(Node, 3, AArch64::LD3i64);
5583 case Intrinsic::aarch64_neon_ld4lane:
5584 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5585 SelectLoadLane(Node, 4, AArch64::LD4i8);
5587 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5588 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5589 SelectLoadLane(Node, 4, AArch64::LD4i16);
5591 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5593 SelectLoadLane(Node, 4, AArch64::LD4i32);
5595 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5597 SelectLoadLane(Node, 4, AArch64::LD4i64);
5601 case Intrinsic::aarch64_ld64b:
5602 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5604 case Intrinsic::aarch64_sve_ld2q_sret: {
5605 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5608 case Intrinsic::aarch64_sve_ld3q_sret: {
5609 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5612 case Intrinsic::aarch64_sve_ld4q_sret: {
5613 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5616 case Intrinsic::aarch64_sve_ld2_sret: {
5617 if (VT == MVT::nxv16i8) {
5618 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5621 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5622 VT == MVT::nxv8bf16) {
5623 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5626 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5627 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5630 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5631 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5637 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5638 if (VT == MVT::nxv16i8) {
5639 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5640 SelectContiguousMultiVectorLoad(
5641 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5642 else if (Subtarget->hasSVE2p1())
5643 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5648 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5649 VT == MVT::nxv8bf16) {
5650 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5651 SelectContiguousMultiVectorLoad(
5652 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5653 else if (Subtarget->hasSVE2p1())
5654 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5659 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5660 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5661 SelectContiguousMultiVectorLoad(
5662 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5663 else if (Subtarget->hasSVE2p1())
5664 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5669 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5670 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5671 SelectContiguousMultiVectorLoad(
5672 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5673 else if (Subtarget->hasSVE2p1())
5674 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5682 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5683 if (VT == MVT::nxv16i8) {
5684 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5685 SelectContiguousMultiVectorLoad(
5686 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5687 else if (Subtarget->hasSVE2p1())
5688 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5693 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5694 VT == MVT::nxv8bf16) {
5695 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5696 SelectContiguousMultiVectorLoad(
5697 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5698 else if (Subtarget->hasSVE2p1())
5699 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5704 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5705 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5706 SelectContiguousMultiVectorLoad(
5707 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5708 else if (Subtarget->hasSVE2p1())
5709 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5714 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5715 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5716 SelectContiguousMultiVectorLoad(
5717 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5718 else if (Subtarget->hasSVE2p1())
5719 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5727 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5728 if (VT == MVT::nxv16i8) {
5729 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5730 SelectContiguousMultiVectorLoad(Node, 2, 0,
5731 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5732 AArch64::LDNT1B_2Z_PSEUDO);
5733 else if (Subtarget->hasSVE2p1())
5734 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5735 AArch64::LDNT1B_2Z);
5739 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5740 VT == MVT::nxv8bf16) {
5741 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5742 SelectContiguousMultiVectorLoad(Node, 2, 1,
5743 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5744 AArch64::LDNT1H_2Z_PSEUDO);
5745 else if (Subtarget->hasSVE2p1())
5746 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5747 AArch64::LDNT1H_2Z);
5751 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5752 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5753 SelectContiguousMultiVectorLoad(Node, 2, 2,
5754 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5755 AArch64::LDNT1W_2Z_PSEUDO);
5756 else if (Subtarget->hasSVE2p1())
5757 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5758 AArch64::LDNT1W_2Z);
5762 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5763 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5764 SelectContiguousMultiVectorLoad(Node, 2, 3,
5765 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5766 AArch64::LDNT1D_2Z_PSEUDO);
5767 else if (Subtarget->hasSVE2p1())
5768 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5769 AArch64::LDNT1D_2Z);
5776 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5777 if (VT == MVT::nxv16i8) {
5778 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5779 SelectContiguousMultiVectorLoad(Node, 4, 0,
5780 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5781 AArch64::LDNT1B_4Z_PSEUDO);
5782 else if (Subtarget->hasSVE2p1())
5783 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5784 AArch64::LDNT1B_4Z);
5788 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5789 VT == MVT::nxv8bf16) {
5790 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5791 SelectContiguousMultiVectorLoad(Node, 4, 1,
5792 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5793 AArch64::LDNT1H_4Z_PSEUDO);
5794 else if (Subtarget->hasSVE2p1())
5795 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5796 AArch64::LDNT1H_4Z);
5800 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5801 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5802 SelectContiguousMultiVectorLoad(Node, 4, 2,
5803 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5804 AArch64::LDNT1W_4Z_PSEUDO);
5805 else if (Subtarget->hasSVE2p1())
5806 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5807 AArch64::LDNT1W_4Z);
5811 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5812 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5813 SelectContiguousMultiVectorLoad(Node, 4, 3,
5814 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5815 AArch64::LDNT1D_4Z_PSEUDO);
5816 else if (Subtarget->hasSVE2p1())
5817 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5818 AArch64::LDNT1D_4Z);
5825 case Intrinsic::aarch64_sve_ld3_sret: {
5826 if (VT == MVT::nxv16i8) {
5827 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5830 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5831 VT == MVT::nxv8bf16) {
5832 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5835 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5836 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5839 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5840 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5846 case Intrinsic::aarch64_sve_ld4_sret: {
5847 if (VT == MVT::nxv16i8) {
5848 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5851 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5852 VT == MVT::nxv8bf16) {
5853 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5856 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5857 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5860 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5861 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5867 case Intrinsic::aarch64_sme_read_hor_vg2: {
5868 if (VT == MVT::nxv16i8) {
5869 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5870 AArch64::MOVA_2ZMXI_H_B);
5872 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5873 VT == MVT::nxv8bf16) {
5874 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5875 AArch64::MOVA_2ZMXI_H_H);
5877 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5878 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5879 AArch64::MOVA_2ZMXI_H_S);
5881 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5882 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5883 AArch64::MOVA_2ZMXI_H_D);
5888 case Intrinsic::aarch64_sme_read_ver_vg2: {
5889 if (VT == MVT::nxv16i8) {
5890 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5891 AArch64::MOVA_2ZMXI_V_B);
5893 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5894 VT == MVT::nxv8bf16) {
5895 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5896 AArch64::MOVA_2ZMXI_V_H);
5898 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5899 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5900 AArch64::MOVA_2ZMXI_V_S);
5902 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5903 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5904 AArch64::MOVA_2ZMXI_V_D);
5909 case Intrinsic::aarch64_sme_read_hor_vg4: {
5910 if (VT == MVT::nxv16i8) {
5911 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5912 AArch64::MOVA_4ZMXI_H_B);
5914 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5915 VT == MVT::nxv8bf16) {
5916 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5917 AArch64::MOVA_4ZMXI_H_H);
5919 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5920 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5921 AArch64::MOVA_4ZMXI_H_S);
5923 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5924 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5925 AArch64::MOVA_4ZMXI_H_D);
5930 case Intrinsic::aarch64_sme_read_ver_vg4: {
5931 if (VT == MVT::nxv16i8) {
5932 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5933 AArch64::MOVA_4ZMXI_V_B);
5935 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5936 VT == MVT::nxv8bf16) {
5937 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5938 AArch64::MOVA_4ZMXI_V_H);
5940 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5941 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5942 AArch64::MOVA_4ZMXI_V_S);
5944 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5945 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5946 AArch64::MOVA_4ZMXI_V_D);
5951 case Intrinsic::aarch64_sme_read_vg1x2: {
5952 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5953 AArch64::MOVA_VG2_2ZMXI);
5956 case Intrinsic::aarch64_sme_read_vg1x4: {
5957 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5958 AArch64::MOVA_VG4_4ZMXI);
5961 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5962 if (VT == MVT::nxv16i8) {
5963 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5965 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5966 VT == MVT::nxv8bf16) {
5967 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5969 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5970 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5972 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5973 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5978 case Intrinsic::aarch64_sme_readz_vert_x2: {
5979 if (VT == MVT::nxv16i8) {
5980 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5982 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5983 VT == MVT::nxv8bf16) {
5984 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5986 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5987 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5989 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5990 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5995 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5996 if (VT == MVT::nxv16i8) {
5997 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5999 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6000 VT == MVT::nxv8bf16) {
6001 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6003 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6004 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6006 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6007 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6012 case Intrinsic::aarch64_sme_readz_vert_x4: {
6013 if (VT == MVT::nxv16i8) {
6014 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6016 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6017 VT == MVT::nxv8bf16) {
6018 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6020 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6021 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6023 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6024 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6029 case Intrinsic::aarch64_sme_readz_x2: {
6030 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6034 case Intrinsic::aarch64_sme_readz_x4: {
6035 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6039 case Intrinsic::swift_async_context_addr: {
6041 SDValue Chain =
Node->getOperand(0);
6042 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6043 SDValue Res = SDValue(
6044 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6045 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6046 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6048 ReplaceUses(SDValue(Node, 0), Res);
6049 ReplaceUses(SDValue(Node, 1), CopyFP.
getValue(1));
6050 CurDAG->RemoveDeadNode(Node);
6052 auto &MF = CurDAG->getMachineFunction();
6053 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6054 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6057 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6059 Node->getValueType(0),
6060 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6061 AArch64::LUTI2_4ZTZI_S}))
6063 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6066 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6068 Node->getValueType(0),
6069 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6071 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6074 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6076 Node->getValueType(0),
6077 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6078 AArch64::LUTI2_2ZTZI_S}))
6080 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6083 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6085 Node->getValueType(0),
6086 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6087 AArch64::LUTI4_2ZTZI_S}))
6089 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6092 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6093 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6096 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6097 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6100 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6102 Node->getValueType(0),
6103 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6104 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6106 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6108 Node->getValueType(0),
6109 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6110 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6112 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6114 Node->getValueType(0),
6115 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6116 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6118 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6120 Node->getValueType(0),
6121 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6122 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6124 case Intrinsic::ptrauth_resign_load_relative:
6125 SelectPtrauthResign(Node);
6130 unsigned IntNo =
Node->getConstantOperandVal(0);
6134 case Intrinsic::aarch64_tagp:
6138 case Intrinsic::ptrauth_auth:
6139 SelectPtrauthAuth(Node);
6142 case Intrinsic::ptrauth_resign:
6143 SelectPtrauthResign(Node);
6146 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6147 SelectPtrauthResignWithPC(Node);
6150 case Intrinsic::aarch64_neon_tbl2:
6151 SelectTable(Node, 2,
6152 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6155 case Intrinsic::aarch64_neon_tbl3:
6156 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6157 : AArch64::TBLv16i8Three,
6160 case Intrinsic::aarch64_neon_tbl4:
6161 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6162 : AArch64::TBLv16i8Four,
6165 case Intrinsic::aarch64_neon_tbx2:
6166 SelectTable(Node, 2,
6167 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6170 case Intrinsic::aarch64_neon_tbx3:
6171 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6172 : AArch64::TBXv16i8Three,
6175 case Intrinsic::aarch64_neon_tbx4:
6176 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6177 : AArch64::TBXv16i8Four,
6180 case Intrinsic::aarch64_sve_srshl_single_x2:
6182 Node->getValueType(0),
6183 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6184 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6185 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6187 case Intrinsic::aarch64_sve_srshl_single_x4:
6189 Node->getValueType(0),
6190 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6191 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6192 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6194 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6195 SelectMultiVectorLuti6LaneX4(Node, 2);
6197 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6198 SelectMultiVectorLuti6LaneX4(Node, 3);
6200 case Intrinsic::aarch64_sve_urshl_single_x2:
6202 Node->getValueType(0),
6203 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6204 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6205 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6207 case Intrinsic::aarch64_sve_urshl_single_x4:
6209 Node->getValueType(0),
6210 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6211 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6212 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6214 case Intrinsic::aarch64_sve_srshl_x2:
6216 Node->getValueType(0),
6217 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6218 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6219 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6221 case Intrinsic::aarch64_sve_srshl_x4:
6223 Node->getValueType(0),
6224 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6225 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6226 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6228 case Intrinsic::aarch64_sve_urshl_x2:
6230 Node->getValueType(0),
6231 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6232 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6233 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6235 case Intrinsic::aarch64_sve_urshl_x4:
6237 Node->getValueType(0),
6238 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6239 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6240 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6242 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6244 Node->getValueType(0),
6245 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6246 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6247 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6249 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6251 Node->getValueType(0),
6252 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6253 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6254 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6256 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6258 Node->getValueType(0),
6259 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6260 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6261 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6263 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6265 Node->getValueType(0),
6266 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6267 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6268 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6270 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6272 Node->getValueType(0),
6273 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6274 AArch64::FSCALE_2ZZ_D}))
6275 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6277 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6279 Node->getValueType(0),
6280 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6281 AArch64::FSCALE_4ZZ_D}))
6282 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6284 case Intrinsic::aarch64_sme_fp8_scale_x2:
6286 Node->getValueType(0),
6287 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6288 AArch64::FSCALE_2Z2Z_D}))
6289 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6291 case Intrinsic::aarch64_sme_fp8_scale_x4:
6293 Node->getValueType(0),
6294 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6295 AArch64::FSCALE_4Z4Z_D}))
6296 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6298 case Intrinsic::aarch64_sve_whilege_x2:
6300 Node->getValueType(0),
6301 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6302 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6303 SelectWhilePair(Node,
Op);
6305 case Intrinsic::aarch64_sve_whilegt_x2:
6307 Node->getValueType(0),
6308 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6309 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6310 SelectWhilePair(Node,
Op);
6312 case Intrinsic::aarch64_sve_whilehi_x2:
6314 Node->getValueType(0),
6315 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6316 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6317 SelectWhilePair(Node,
Op);
6319 case Intrinsic::aarch64_sve_whilehs_x2:
6321 Node->getValueType(0),
6322 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6323 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6324 SelectWhilePair(Node,
Op);
6326 case Intrinsic::aarch64_sve_whilele_x2:
6328 Node->getValueType(0),
6329 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6330 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6331 SelectWhilePair(Node,
Op);
6333 case Intrinsic::aarch64_sve_whilelo_x2:
6335 Node->getValueType(0),
6336 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6337 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6338 SelectWhilePair(Node,
Op);
6340 case Intrinsic::aarch64_sve_whilels_x2:
6342 Node->getValueType(0),
6343 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6344 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6345 SelectWhilePair(Node,
Op);
6347 case Intrinsic::aarch64_sve_whilelt_x2:
6349 Node->getValueType(0),
6350 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6351 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6352 SelectWhilePair(Node,
Op);
6354 case Intrinsic::aarch64_sve_smax_single_x2:
6356 Node->getValueType(0),
6357 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6358 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6359 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6361 case Intrinsic::aarch64_sve_umax_single_x2:
6363 Node->getValueType(0),
6364 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6365 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6366 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6368 case Intrinsic::aarch64_sve_fmax_single_x2:
6370 Node->getValueType(0),
6371 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6372 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6373 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6375 case Intrinsic::aarch64_sve_smax_single_x4:
6377 Node->getValueType(0),
6378 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6379 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6380 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6382 case Intrinsic::aarch64_sve_umax_single_x4:
6384 Node->getValueType(0),
6385 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6386 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6387 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6389 case Intrinsic::aarch64_sve_fmax_single_x4:
6391 Node->getValueType(0),
6392 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6393 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6394 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6396 case Intrinsic::aarch64_sve_smin_single_x2:
6398 Node->getValueType(0),
6399 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6400 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6401 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6403 case Intrinsic::aarch64_sve_umin_single_x2:
6405 Node->getValueType(0),
6406 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6407 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6408 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6410 case Intrinsic::aarch64_sve_fmin_single_x2:
6412 Node->getValueType(0),
6413 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6414 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6415 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6417 case Intrinsic::aarch64_sve_smin_single_x4:
6419 Node->getValueType(0),
6420 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6421 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6422 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6424 case Intrinsic::aarch64_sve_umin_single_x4:
6426 Node->getValueType(0),
6427 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6428 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6429 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6431 case Intrinsic::aarch64_sve_fmin_single_x4:
6433 Node->getValueType(0),
6434 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6435 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6436 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6438 case Intrinsic::aarch64_sve_smax_x2:
6440 Node->getValueType(0),
6441 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6442 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6443 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6445 case Intrinsic::aarch64_sve_umax_x2:
6447 Node->getValueType(0),
6448 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6449 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6450 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6452 case Intrinsic::aarch64_sve_fmax_x2:
6454 Node->getValueType(0),
6455 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6456 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6457 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6459 case Intrinsic::aarch64_sve_smax_x4:
6461 Node->getValueType(0),
6462 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6463 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6464 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6466 case Intrinsic::aarch64_sve_umax_x4:
6468 Node->getValueType(0),
6469 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6470 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6471 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6473 case Intrinsic::aarch64_sve_fmax_x4:
6475 Node->getValueType(0),
6476 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6477 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6478 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6480 case Intrinsic::aarch64_sme_famax_x2:
6482 Node->getValueType(0),
6483 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6484 AArch64::FAMAX_2Z2Z_D}))
6485 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6487 case Intrinsic::aarch64_sme_famax_x4:
6489 Node->getValueType(0),
6490 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6491 AArch64::FAMAX_4Z4Z_D}))
6492 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6494 case Intrinsic::aarch64_sme_famin_x2:
6496 Node->getValueType(0),
6497 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6498 AArch64::FAMIN_2Z2Z_D}))
6499 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6501 case Intrinsic::aarch64_sme_famin_x4:
6503 Node->getValueType(0),
6504 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6505 AArch64::FAMIN_4Z4Z_D}))
6506 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6508 case Intrinsic::aarch64_sve_smin_x2:
6510 Node->getValueType(0),
6511 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6512 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6513 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6515 case Intrinsic::aarch64_sve_umin_x2:
6517 Node->getValueType(0),
6518 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6519 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6520 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6522 case Intrinsic::aarch64_sve_fmin_x2:
6524 Node->getValueType(0),
6525 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6526 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6527 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6529 case Intrinsic::aarch64_sve_smin_x4:
6531 Node->getValueType(0),
6532 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6533 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6534 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6536 case Intrinsic::aarch64_sve_umin_x4:
6538 Node->getValueType(0),
6539 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6540 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6541 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6543 case Intrinsic::aarch64_sve_fmin_x4:
6545 Node->getValueType(0),
6546 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6547 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6548 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6550 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6552 Node->getValueType(0),
6553 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6554 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6555 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6557 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6559 Node->getValueType(0),
6560 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6561 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6562 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6564 case Intrinsic::aarch64_sve_fminnm_single_x2:
6566 Node->getValueType(0),
6567 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6568 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6569 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6571 case Intrinsic::aarch64_sve_fminnm_single_x4:
6573 Node->getValueType(0),
6574 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6575 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6576 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6578 case Intrinsic::aarch64_sve_fscale_single_x4:
6579 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6581 case Intrinsic::aarch64_sve_fscale_single_x2:
6582 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6584 case Intrinsic::aarch64_sve_fmul_single_x4:
6586 Node->getValueType(0),
6587 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6588 AArch64::FMUL_4ZZ_D}))
6589 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6591 case Intrinsic::aarch64_sve_fmul_single_x2:
6593 Node->getValueType(0),
6594 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6595 AArch64::FMUL_2ZZ_D}))
6596 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6598 case Intrinsic::aarch64_sve_fmaxnm_x2:
6600 Node->getValueType(0),
6601 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6602 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6603 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6605 case Intrinsic::aarch64_sve_fmaxnm_x4:
6607 Node->getValueType(0),
6608 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6609 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6610 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6612 case Intrinsic::aarch64_sve_fminnm_x2:
6614 Node->getValueType(0),
6615 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6616 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6617 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6619 case Intrinsic::aarch64_sve_fminnm_x4:
6621 Node->getValueType(0),
6622 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6623 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6624 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6626 case Intrinsic::aarch64_sve_aese_lane_x2:
6627 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6629 case Intrinsic::aarch64_sve_aesd_lane_x2:
6630 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6632 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6633 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6635 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6636 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6638 case Intrinsic::aarch64_sve_aese_lane_x4:
6639 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6641 case Intrinsic::aarch64_sve_aesd_lane_x4:
6642 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6644 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6645 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6647 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6648 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6650 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6651 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6653 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6657 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6658 SDValue SuperReg = SDValue(Res, 0);
6659 for (
unsigned I = 0;
I < 2;
I++)
6660 ReplaceUses(SDValue(Node,
I),
6661 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6663 CurDAG->RemoveDeadNode(Node);
6666 case Intrinsic::aarch64_sve_fscale_x4:
6667 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6669 case Intrinsic::aarch64_sve_fscale_x2:
6670 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6672 case Intrinsic::aarch64_sve_fmul_x4:
6674 Node->getValueType(0),
6675 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6676 AArch64::FMUL_4Z4Z_D}))
6677 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6679 case Intrinsic::aarch64_sve_fmul_x2:
6681 Node->getValueType(0),
6682 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6683 AArch64::FMUL_2Z2Z_D}))
6684 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6686 case Intrinsic::aarch64_sve_fcvtzs_x2:
6687 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6689 case Intrinsic::aarch64_sve_scvtf_x2:
6690 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6692 case Intrinsic::aarch64_sve_fcvtzu_x2:
6693 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6695 case Intrinsic::aarch64_sve_ucvtf_x2:
6696 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6698 case Intrinsic::aarch64_sve_fcvtzs_x4:
6699 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6701 case Intrinsic::aarch64_sve_scvtf_x4:
6702 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6704 case Intrinsic::aarch64_sve_fcvtzu_x4:
6705 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6707 case Intrinsic::aarch64_sve_ucvtf_x4:
6708 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6710 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6711 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6713 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6714 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6716 case Intrinsic::aarch64_sve_sclamp_single_x2:
6718 Node->getValueType(0),
6719 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6720 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6721 SelectClamp(Node, 2,
Op);
6723 case Intrinsic::aarch64_sve_uclamp_single_x2:
6725 Node->getValueType(0),
6726 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6727 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6728 SelectClamp(Node, 2,
Op);
6730 case Intrinsic::aarch64_sve_fclamp_single_x2:
6732 Node->getValueType(0),
6733 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6734 AArch64::FCLAMP_VG2_2Z2Z_D}))
6735 SelectClamp(Node, 2,
Op);
6737 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6738 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6740 case Intrinsic::aarch64_sve_sclamp_single_x4:
6742 Node->getValueType(0),
6743 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6744 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6745 SelectClamp(Node, 4,
Op);
6747 case Intrinsic::aarch64_sve_uclamp_single_x4:
6749 Node->getValueType(0),
6750 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6751 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6752 SelectClamp(Node, 4,
Op);
6754 case Intrinsic::aarch64_sve_fclamp_single_x4:
6756 Node->getValueType(0),
6757 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6758 AArch64::FCLAMP_VG4_4Z4Z_D}))
6759 SelectClamp(Node, 4,
Op);
6761 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6762 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6764 case Intrinsic::aarch64_sve_add_single_x2:
6766 Node->getValueType(0),
6767 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6768 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6769 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6771 case Intrinsic::aarch64_sve_add_single_x4:
6773 Node->getValueType(0),
6774 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6775 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6776 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6778 case Intrinsic::aarch64_sve_zip_x2:
6780 Node->getValueType(0),
6781 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6782 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6783 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6785 case Intrinsic::aarch64_sve_zipq_x2:
6786 SelectUnaryMultiIntrinsic(Node, 2,
false,
6787 AArch64::ZIP_VG2_2ZZZ_Q);
6789 case Intrinsic::aarch64_sve_zip_x4:
6791 Node->getValueType(0),
6792 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6793 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6794 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6796 case Intrinsic::aarch64_sve_zipq_x4:
6797 SelectUnaryMultiIntrinsic(Node, 4,
true,
6798 AArch64::ZIP_VG4_4Z4Z_Q);
6800 case Intrinsic::aarch64_sve_uzp_x2:
6802 Node->getValueType(0),
6803 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6804 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6805 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6807 case Intrinsic::aarch64_sve_uzpq_x2:
6808 SelectUnaryMultiIntrinsic(Node, 2,
false,
6809 AArch64::UZP_VG2_2ZZZ_Q);
6811 case Intrinsic::aarch64_sve_uzp_x4:
6813 Node->getValueType(0),
6814 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6815 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6816 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6818 case Intrinsic::aarch64_sve_uzpq_x4:
6819 SelectUnaryMultiIntrinsic(Node, 4,
true,
6820 AArch64::UZP_VG4_4Z4Z_Q);
6822 case Intrinsic::aarch64_sve_sel_x2:
6824 Node->getValueType(0),
6825 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6826 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6827 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6829 case Intrinsic::aarch64_sve_sel_x4:
6831 Node->getValueType(0),
6832 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6833 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6834 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6836 case Intrinsic::aarch64_sve_frinta_x2:
6837 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6839 case Intrinsic::aarch64_sve_frinta_x4:
6840 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6842 case Intrinsic::aarch64_sve_frintm_x2:
6843 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6845 case Intrinsic::aarch64_sve_frintm_x4:
6846 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6848 case Intrinsic::aarch64_sve_frintn_x2:
6849 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6851 case Intrinsic::aarch64_sve_frintn_x4:
6852 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6854 case Intrinsic::aarch64_sve_frintp_x2:
6855 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6857 case Intrinsic::aarch64_sve_frintp_x4:
6858 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6860 case Intrinsic::aarch64_sve_sunpk_x2:
6862 Node->getValueType(0),
6863 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6864 AArch64::SUNPK_VG2_2ZZ_D}))
6865 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6867 case Intrinsic::aarch64_sve_uunpk_x2:
6869 Node->getValueType(0),
6870 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6871 AArch64::UUNPK_VG2_2ZZ_D}))
6872 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6874 case Intrinsic::aarch64_sve_sunpk_x4:
6876 Node->getValueType(0),
6877 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6878 AArch64::SUNPK_VG4_4Z2Z_D}))
6879 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6881 case Intrinsic::aarch64_sve_uunpk_x4:
6883 Node->getValueType(0),
6884 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6885 AArch64::UUNPK_VG4_4Z2Z_D}))
6886 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6888 case Intrinsic::aarch64_sve_pext_x2: {
6890 Node->getValueType(0),
6891 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6892 AArch64::PEXT_2PCI_D}))
6893 SelectPExtPair(Node,
Op);
6900 unsigned IntNo =
Node->getConstantOperandVal(1);
6901 if (
Node->getNumOperands() >= 3)
6902 VT =
Node->getOperand(2)->getValueType(0);
6906 case Intrinsic::aarch64_neon_st1x2: {
6907 if (VT == MVT::v8i8) {
6908 SelectStore(Node, 2, AArch64::ST1Twov8b);
6910 }
else if (VT == MVT::v16i8) {
6911 SelectStore(Node, 2, AArch64::ST1Twov16b);
6913 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6914 VT == MVT::v4bf16) {
6915 SelectStore(Node, 2, AArch64::ST1Twov4h);
6917 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6918 VT == MVT::v8bf16) {
6919 SelectStore(Node, 2, AArch64::ST1Twov8h);
6921 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6922 SelectStore(Node, 2, AArch64::ST1Twov2s);
6924 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6925 SelectStore(Node, 2, AArch64::ST1Twov4s);
6927 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6928 SelectStore(Node, 2, AArch64::ST1Twov2d);
6930 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6931 SelectStore(Node, 2, AArch64::ST1Twov1d);
6936 case Intrinsic::aarch64_neon_st1x3: {
6937 if (VT == MVT::v8i8) {
6938 SelectStore(Node, 3, AArch64::ST1Threev8b);
6940 }
else if (VT == MVT::v16i8) {
6941 SelectStore(Node, 3, AArch64::ST1Threev16b);
6943 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6944 VT == MVT::v4bf16) {
6945 SelectStore(Node, 3, AArch64::ST1Threev4h);
6947 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6948 VT == MVT::v8bf16) {
6949 SelectStore(Node, 3, AArch64::ST1Threev8h);
6951 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6952 SelectStore(Node, 3, AArch64::ST1Threev2s);
6954 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6955 SelectStore(Node, 3, AArch64::ST1Threev4s);
6957 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6958 SelectStore(Node, 3, AArch64::ST1Threev2d);
6960 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6961 SelectStore(Node, 3, AArch64::ST1Threev1d);
6966 case Intrinsic::aarch64_neon_st1x4: {
6967 if (VT == MVT::v8i8) {
6968 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6970 }
else if (VT == MVT::v16i8) {
6971 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6973 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6974 VT == MVT::v4bf16) {
6975 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6977 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6978 VT == MVT::v8bf16) {
6979 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6981 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6982 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6984 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6985 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6987 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6988 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6990 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6991 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6996 case Intrinsic::aarch64_neon_st2: {
6997 if (VT == MVT::v8i8) {
6998 SelectStore(Node, 2, AArch64::ST2Twov8b);
7000 }
else if (VT == MVT::v16i8) {
7001 SelectStore(Node, 2, AArch64::ST2Twov16b);
7003 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7004 VT == MVT::v4bf16) {
7005 SelectStore(Node, 2, AArch64::ST2Twov4h);
7007 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7008 VT == MVT::v8bf16) {
7009 SelectStore(Node, 2, AArch64::ST2Twov8h);
7011 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7012 SelectStore(Node, 2, AArch64::ST2Twov2s);
7014 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7015 SelectStore(Node, 2, AArch64::ST2Twov4s);
7017 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7018 SelectStore(Node, 2, AArch64::ST2Twov2d);
7020 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7021 SelectStore(Node, 2, AArch64::ST1Twov1d);
7026 case Intrinsic::aarch64_neon_st3: {
7027 if (VT == MVT::v8i8) {
7028 SelectStore(Node, 3, AArch64::ST3Threev8b);
7030 }
else if (VT == MVT::v16i8) {
7031 SelectStore(Node, 3, AArch64::ST3Threev16b);
7033 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7034 VT == MVT::v4bf16) {
7035 SelectStore(Node, 3, AArch64::ST3Threev4h);
7037 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7038 VT == MVT::v8bf16) {
7039 SelectStore(Node, 3, AArch64::ST3Threev8h);
7041 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7042 SelectStore(Node, 3, AArch64::ST3Threev2s);
7044 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7045 SelectStore(Node, 3, AArch64::ST3Threev4s);
7047 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7048 SelectStore(Node, 3, AArch64::ST3Threev2d);
7050 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7051 SelectStore(Node, 3, AArch64::ST1Threev1d);
7056 case Intrinsic::aarch64_neon_st4: {
7057 if (VT == MVT::v8i8) {
7058 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7060 }
else if (VT == MVT::v16i8) {
7061 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7063 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7064 VT == MVT::v4bf16) {
7065 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7067 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7068 VT == MVT::v8bf16) {
7069 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7071 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7072 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7074 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7075 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7077 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7078 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7080 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7081 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7086 case Intrinsic::aarch64_neon_st2lane: {
7087 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7088 SelectStoreLane(Node, 2, AArch64::ST2i8);
7090 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7091 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7092 SelectStoreLane(Node, 2, AArch64::ST2i16);
7094 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7096 SelectStoreLane(Node, 2, AArch64::ST2i32);
7098 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7100 SelectStoreLane(Node, 2, AArch64::ST2i64);
7105 case Intrinsic::aarch64_neon_st3lane: {
7106 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7107 SelectStoreLane(Node, 3, AArch64::ST3i8);
7109 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7110 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7111 SelectStoreLane(Node, 3, AArch64::ST3i16);
7113 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7115 SelectStoreLane(Node, 3, AArch64::ST3i32);
7117 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7119 SelectStoreLane(Node, 3, AArch64::ST3i64);
7124 case Intrinsic::aarch64_neon_st4lane: {
7125 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7126 SelectStoreLane(Node, 4, AArch64::ST4i8);
7128 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7129 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7130 SelectStoreLane(Node, 4, AArch64::ST4i16);
7132 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7134 SelectStoreLane(Node, 4, AArch64::ST4i32);
7136 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7138 SelectStoreLane(Node, 4, AArch64::ST4i64);
7143 case Intrinsic::aarch64_sve_st2q: {
7144 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7147 case Intrinsic::aarch64_sve_st3q: {
7148 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7151 case Intrinsic::aarch64_sve_st4q: {
7152 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7155 case Intrinsic::aarch64_sve_st2: {
7156 if (VT == MVT::nxv16i8) {
7157 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7159 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7160 VT == MVT::nxv8bf16) {
7161 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7163 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7164 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7166 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7167 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7172 case Intrinsic::aarch64_sve_st3: {
7173 if (VT == MVT::nxv16i8) {
7174 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7176 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7177 VT == MVT::nxv8bf16) {
7178 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7180 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7181 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7183 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7184 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7189 case Intrinsic::aarch64_sve_st4: {
7190 if (VT == MVT::nxv16i8) {
7191 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7193 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7194 VT == MVT::nxv8bf16) {
7195 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7197 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7198 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7200 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7201 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7209 case AArch64ISD::LD2post: {
7210 if (VT == MVT::v8i8) {
7211 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7213 }
else if (VT == MVT::v16i8) {
7214 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7216 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7217 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7219 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7220 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7222 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7223 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7225 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7226 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7228 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7229 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7231 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7232 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7237 case AArch64ISD::LD3post: {
7238 if (VT == MVT::v8i8) {
7239 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7241 }
else if (VT == MVT::v16i8) {
7242 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7244 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7245 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7247 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7248 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7250 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7251 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7253 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7254 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7256 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7257 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7259 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7260 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7265 case AArch64ISD::LD4post: {
7266 if (VT == MVT::v8i8) {
7267 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7269 }
else if (VT == MVT::v16i8) {
7270 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7272 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7273 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7275 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7276 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7278 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7279 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7281 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7282 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7284 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7285 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7287 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7288 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7293 case AArch64ISD::LD1x2post: {
7294 if (VT == MVT::v8i8) {
7295 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7297 }
else if (VT == MVT::v16i8) {
7298 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7300 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7301 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7303 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7304 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7306 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7307 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7309 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7310 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7312 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7313 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7315 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7316 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7321 case AArch64ISD::LD1x3post: {
7322 if (VT == MVT::v8i8) {
7323 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7325 }
else if (VT == MVT::v16i8) {
7326 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7328 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7329 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7331 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7332 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7334 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7335 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7337 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7338 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7340 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7341 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7343 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7344 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7349 case AArch64ISD::LD1x4post: {
7350 if (VT == MVT::v8i8) {
7351 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7353 }
else if (VT == MVT::v16i8) {
7354 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7356 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7357 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7359 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7360 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7362 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7363 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7365 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7366 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7368 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7369 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7371 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7372 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7377 case AArch64ISD::LD1DUPpost: {
7378 if (VT == MVT::v8i8) {
7379 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7381 }
else if (VT == MVT::v16i8) {
7382 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7384 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7385 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7387 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7388 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7390 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7391 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7393 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7394 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7396 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7397 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7399 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7400 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7405 case AArch64ISD::LD2DUPpost: {
7406 if (VT == MVT::v8i8) {
7407 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7409 }
else if (VT == MVT::v16i8) {
7410 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7412 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7413 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7415 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7416 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7418 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7419 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7421 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7422 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7424 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7425 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7427 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7428 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7433 case AArch64ISD::LD3DUPpost: {
7434 if (VT == MVT::v8i8) {
7435 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7437 }
else if (VT == MVT::v16i8) {
7438 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7440 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7441 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7443 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7444 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7446 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7447 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7449 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7450 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7452 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7453 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7455 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7456 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7461 case AArch64ISD::LD4DUPpost: {
7462 if (VT == MVT::v8i8) {
7463 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7465 }
else if (VT == MVT::v16i8) {
7466 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7468 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7469 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7471 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7472 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7474 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7475 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7477 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7478 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7480 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7481 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7483 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7484 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7489 case AArch64ISD::LD1LANEpost: {
7490 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7491 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7493 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7494 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7495 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7497 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7499 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7501 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7503 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7508 case AArch64ISD::LD2LANEpost: {
7509 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7510 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7512 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7513 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7514 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7516 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7518 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7520 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7522 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7527 case AArch64ISD::LD3LANEpost: {
7528 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7529 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7531 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7532 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7533 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7535 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7537 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7539 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7541 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7546 case AArch64ISD::LD4LANEpost: {
7547 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7548 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7550 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7551 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7552 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7554 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7556 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7558 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7560 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7565 case AArch64ISD::ST2post: {
7566 VT =
Node->getOperand(1).getValueType();
7567 if (VT == MVT::v8i8) {
7568 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7570 }
else if (VT == MVT::v16i8) {
7571 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7573 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7574 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7576 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7577 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7579 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7580 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7582 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7583 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7585 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7586 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7588 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7589 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7594 case AArch64ISD::ST3post: {
7595 VT =
Node->getOperand(1).getValueType();
7596 if (VT == MVT::v8i8) {
7597 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7599 }
else if (VT == MVT::v16i8) {
7600 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7602 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7603 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7605 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7606 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7608 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7609 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7611 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7612 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7614 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7615 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7617 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7618 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7623 case AArch64ISD::ST4post: {
7624 VT =
Node->getOperand(1).getValueType();
7625 if (VT == MVT::v8i8) {
7626 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7628 }
else if (VT == MVT::v16i8) {
7629 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7631 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7632 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7634 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7635 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7637 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7638 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7640 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7641 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7643 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7644 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7646 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7647 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7652 case AArch64ISD::ST1x2post: {
7653 VT =
Node->getOperand(1).getValueType();
7654 if (VT == MVT::v8i8) {
7655 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7657 }
else if (VT == MVT::v16i8) {
7658 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7660 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7661 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7663 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7664 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7666 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7667 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7669 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7670 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7672 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7673 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7675 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7676 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7681 case AArch64ISD::ST1x3post: {
7682 VT =
Node->getOperand(1).getValueType();
7683 if (VT == MVT::v8i8) {
7684 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7686 }
else if (VT == MVT::v16i8) {
7687 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7689 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7690 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7692 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7693 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7695 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7696 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7698 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7699 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7701 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7702 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7704 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7705 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7710 case AArch64ISD::ST1x4post: {
7711 VT =
Node->getOperand(1).getValueType();
7712 if (VT == MVT::v8i8) {
7713 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7715 }
else if (VT == MVT::v16i8) {
7716 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7718 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7719 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7721 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7722 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7724 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7725 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7727 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7728 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7730 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7731 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7733 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7734 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7739 case AArch64ISD::ST2LANEpost: {
7740 VT =
Node->getOperand(1).getValueType();
7741 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7742 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7744 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7745 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7746 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7748 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7750 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7752 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7754 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7759 case AArch64ISD::ST3LANEpost: {
7760 VT =
Node->getOperand(1).getValueType();
7761 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7762 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7764 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7765 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7766 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7768 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7770 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7772 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7774 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7779 case AArch64ISD::ST4LANEpost: {
7780 VT =
Node->getOperand(1).getValueType();
7781 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7782 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7784 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7785 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7786 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7788 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7790 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7792 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7794 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7809 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7821 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7825 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7826 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7848 return MemIntr->getMemoryVT();
7855 DataVT =
Load->getValueType(0);
7857 DataVT =
Load->getValueType(0);
7859 DataVT =
Store->getValue().getValueType();
7861 DataVT =
Store->getValue().getValueType();
7868 const unsigned Opcode = Root->
getOpcode();
7872 case AArch64ISD::LD1_MERGE_ZERO:
7873 case AArch64ISD::LD1S_MERGE_ZERO:
7874 case AArch64ISD::LDNF1_MERGE_ZERO:
7875 case AArch64ISD::LDNF1S_MERGE_ZERO:
7877 case AArch64ISD::ST1_PRED:
7889 case Intrinsic::aarch64_sme_ldr:
7890 case Intrinsic::aarch64_sme_str:
7891 return MVT::nxv16i8;
7892 case Intrinsic::aarch64_sve_prf:
7897 case Intrinsic::aarch64_sve_ld2_sret:
7898 case Intrinsic::aarch64_sve_ld2q_sret:
7901 case Intrinsic::aarch64_sve_st2q:
7904 case Intrinsic::aarch64_sve_ld3_sret:
7905 case Intrinsic::aarch64_sve_ld3q_sret:
7908 case Intrinsic::aarch64_sve_st3q:
7911 case Intrinsic::aarch64_sve_ld4_sret:
7912 case Intrinsic::aarch64_sve_ld4q_sret:
7915 case Intrinsic::aarch64_sve_st4q:
7918 case Intrinsic::aarch64_sve_ld1_pn_x2:
7919 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7922 case Intrinsic::aarch64_sve_ld1_pn_x4:
7923 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7926 case Intrinsic::aarch64_sve_st1_pn_x2:
7927 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7930 case Intrinsic::aarch64_sve_st1_pn_x4:
7931 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7934 case Intrinsic::aarch64_sve_ld1udq:
7935 case Intrinsic::aarch64_sve_st1dq:
7936 return EVT(MVT::nxv1i64);
7937 case Intrinsic::aarch64_sve_ld1uwq:
7938 case Intrinsic::aarch64_sve_st1wq:
7939 return EVT(MVT::nxv1i32);
7946template <
int64_t Min,
int64_t Max>
7947bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue
N,
7951 const DataLayout &
DL = CurDAG->getDataLayout();
7952 const MachineFrameInfo &MFI = MF->getFrameInfo();
7960 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
7973 SDValue VScale =
N.getOperand(1);
7974 int64_t MulImm = std::numeric_limits<int64_t>::max();
7978 int64_t ByteOffset =
C->getSExtValue();
7979 const auto KnownVScale =
7982 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7985 MulImm = ByteOffset / KnownVScale;
7992 if ((MulImm % MemWidthBytes) != 0)
7995 int64_t
Offset = MulImm / MemWidthBytes;
7999 Base =
N.getOperand(0);
8008 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8014bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(SDValue
N,
unsigned Scale,
8021 const SDValue
LHS =
N.getOperand(0);
8022 const SDValue
RHS =
N.getOperand(1);
8033 int64_t ImmOff =
C->getSExtValue();
8034 unsigned Size = 1 << Scale;
8043 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8045 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8054 const SDValue ShiftRHS =
RHS.getOperand(1);
8056 if (
C->getZExtValue() == Scale) {
8065bool AArch64DAGToDAGISel::SelectAllActivePredicate(SDValue
N) {
8066 const AArch64TargetLowering *TLI =
8067 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8072bool AArch64DAGToDAGISel::SelectAnyPredicate(SDValue
N) {
8073 return N.getValueType().isScalableVectorOf(MVT::i1);
8076bool AArch64DAGToDAGISel::SelectSMETileSlice(SDValue
N,
unsigned MaxSize,
8079 auto MatchConstantOffset = [&](SDValue CN) -> SDValue {
8081 int64_t ImmOff =
C->getSExtValue();
8082 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8083 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8088 if (SDValue
C = MatchConstantOffset(
N)) {
8095 if (CurDAG->isBaseWithConstantOffset(
N)) {
8096 if (SDValue
C = MatchConstantOffset(
N.getOperand(1))) {
8097 Base =
N.getOperand(0);
8105 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8109bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P, SDValue
N,
8147 if (CN->getAPIntValue().uge(LowerBound) &&
8148 CN->getAPIntValue().ult(UpperBound)) {
8150 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8158template <
bool MatchCBB>
8159bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue
N, SDValue &
Reg,
8165 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8167 Reg =
N.getOperand(0);
8169 SDLoc(
N), MVT::i32);
8177 Reg =
N.getOperand(0);
8197bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *
N) {
8198 EVT VT =
N->getValueType(0);
8204 SDValue TVal =
N->getOperand(0);
8205 SDValue FVal =
N->getOperand(1);
8206 SDValue CCVal =
N->getOperand(2);
8207 SDValue
Cmp =
N->getOperand(3);
8209 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8216 SDValue CmpLHS =
Cmp.getOperand(0);
8217 SDValue CmpRHS =
Cmp.getOperand(1);
8218 unsigned CondCode = CC->getZExtValue();
8221 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8223 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8224 else if (VT == MVT::f32)
8225 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8226 else if (VT == MVT::f64)
8227 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8235 if (TVal == CmpLHS && FVal == CmpRHS)
8240 if (TVal == CmpLHS && FVal == CmpRHS)
8249 unsigned Opc = getOpc(VT, isMax);
8255 if (!CFP || CFP->getValueAPF().isNaN())
8260 if (CFP->isZero() && !
N->getFlags().hasNoSignedZeros())
8266 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8269 CurDAG->SelectNodeTo(
N,
Opc, VT, CmpLHS, CmpRHS);
8273void AArch64DAGToDAGISel::PreprocessISelDAG() {
8274 bool MadeChange =
false;
8280 switch (
N.getOpcode()) {
8282 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8283 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8284 ScalarTy ==
N.getOperand(0).getValueType())
8289 case AArch64ISD::VSHL: {
8292 EVT VT =
N.getValueType(0);
8293 SDValue
A,
B,
C =
N.getOperand(1);
8299 if (
B.getOpcode() ==
A.getOpcode())
8302 SDValue
SHL = CurDAG->getNode(AArch64ISD::VSHL,
DL, VT,
A,
C);
8312 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8318 CurDAG->ReplaceAllUsesOfValueWith(SDValue(&
N, 0), Result);
8324 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 allUsesAreShiftAmounts(SDValue N)
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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.