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 tryBitfieldExtractOpFromSExt(
SDNode *
N);
449 bool tryBitfieldInsertOp(
SDNode *
N);
450 bool tryBitfieldInsertInZeroOp(
SDNode *
N);
451 bool tryShiftAmountMod(
SDNode *
N);
453 bool tryReadRegister(
SDNode *
N);
454 bool tryWriteRegister(
SDNode *
N);
456 bool trySelectCastFixedLengthToScalableVector(
SDNode *
N);
457 bool trySelectCastScalableToFixedLengthVector(
SDNode *
N);
461 bool tryFoldCselToFMaxMin(
SDNode *
N);
464#include "AArch64GenDAGISel.inc"
472 return SelectAddrModeIndexedBitWidth(
N,
true, 7,
Size,
Base, OffImm);
474 bool SelectAddrModeIndexedBitWidth(
SDValue N,
bool IsSignedImm,
unsigned BW,
487 bool isWorthNegatingImm(
SDValue V)
const;
488 bool isWorthFoldingALU(
SDValue V,
bool LSL =
false)
const;
489 bool isWorthFoldingAddr(
SDValue V,
unsigned Size)
const;
490 bool SelectExtendedSHL(
SDValue N,
unsigned Size,
bool WantExtend,
493 template<
unsigned RegW
idth>
495 return SelectCVTFixedPosOperand(
N, FixedPos, RegWidth);
497 bool SelectCVTFixedPosOperand(
SDValue N,
SDValue &FixedPos,
unsigned Width);
499 template <
unsigned RegW
idth>
501 return SelectCVTFixedPointVec(
N, FixedPos, RegWidth);
503 bool SelectCVTFixedPointVec(
SDValue N,
SDValue &FixedPos,
unsigned Width);
505 template<
unsigned RegW
idth>
507 return SelectCVTFixedPosRecipOperand(
N, FixedPos, RegWidth);
513 template <
unsigned FloatW
idth>
515 return SelectCVTFixedPosRecipOperandVec(
N, FixedPos, FloatWidth);
521 bool SelectCMP_SWAP(
SDNode *
N);
524 bool isAtomicSTSHH_KEEP(
SDNode *
N)
const;
525 bool isAtomicSTSHH_STRM(
SDNode *
N)
const;
554 bool SelectAllActivePredicate(
SDValue N);
559 template <
bool MatchCBB>
569 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
573char AArch64DAGToDAGISelLegacy::ID = 0;
579 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
585 auto getFloatVT = [&](
EVT VT) {
587 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) &&
"Unexpected VT");
588 return VT.changeElementType(*(DAG.
getContext()),
589 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
594 for (
unsigned I = 0,
E =
N.getNumOperands();
I <
E; ++
I) {
595 auto bitcasted = DAG.
getBitcast(getFloatVT(
N.getOperand(
I).getValueType()),
599 EVT OrigVT =
N.getValueType(0);
608 Imm =
C->getZExtValue();
625 return N->getOpcode() ==
Opc &&
636 return Imm == ImmExpected;
641 assert(RegWidth == 32 || RegWidth == 64);
643 return APInt(RegWidth,
651 assert(
N.getValueType().isInteger() &&
"Only integers are supported");
652 if (
N->getOpcode() == AArch64ISD::NVCAST ||
654 N =
N->getOperand(0);
655 unsigned SplatWidth =
N.getScalarValueSizeInBits();
656 if (
N.getOpcode() == AArch64ISD::FMOV)
658 if (
N->getOpcode() == AArch64ISD::MOVI)
659 return APInt(SplatWidth,
N.getConstantOperandVal(0));
660 if (
N->getOpcode() == AArch64ISD::MOVIshift)
661 return APInt(SplatWidth,
N.getConstantOperandVal(0)
662 <<
N.getConstantOperandVal(1));
663 if (
N->getOpcode() == AArch64ISD::MVNIshift)
664 return ~APInt(SplatWidth,
N.getConstantOperandVal(0)
665 <<
N.getConstantOperandVal(1));
666 if (
N->getOpcode() == AArch64ISD::MOVIedit)
668 N.getConstantOperandVal(0)));
669 if (
N->getOpcode() == AArch64ISD::DUP)
671 return Const->getAPIntValue().trunc(SplatWidth);
674 return SplatVal.
trunc(SplatWidth);
682static std::optional<APInt>
684 unsigned SplatWidth =
N.getScalarValueSizeInBits();
686 if (SplatVal->getBitWidth() <= SplatWidth)
688 if (SplatVal->isSplat(SplatWidth))
689 return SplatVal->trunc(SplatWidth);
694bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(
SDValue N,
701 ImmVal->getZExtValue(), Encoding))
704 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(
N), MVT::i64);
708bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(SDValue
N, SDValue &
Imm,
711 return SelectSVEAddSubImm(SDLoc(
N), *ImmVal,
712 N.getValueType().getScalarType().getSimpleVT(),
718bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(SDValue
N,
721 return SelectSVESignedArithImm(SDLoc(
N), *ImmVal,
Imm);
725bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(SDValue
N, SDValue &
Imm) {
730 int64_t ImmVal = ImmAPIntVal->getSExtValue();
731 if (ImmVal < -128 || ImmVal > 127)
734 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
738bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(SDValue
N, SDValue &
Imm) {
743 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
747 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
751bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
753 std::vector<SDValue> &OutOps) {
754 switch(ConstraintID) {
757 case InlineAsm::ConstraintCode::m:
758 case InlineAsm::ConstraintCode::o:
759 case InlineAsm::ConstraintCode::Q:
766 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(), dl, MVT::i64);
768 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
769 dl,
Op.getValueType(),
771 OutOps.push_back(NewOp);
777template <
unsigned ShiftW
idth>
778bool AArch64DAGToDAGISel::SelectShiftMask(SDValue
N, SDValue &ShAmt) {
784 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
796 N.getValueType() == (ShiftWidth == 32 ? MVT::i32 : MVT::i64)) {
799 (
Imm % ShiftWidth == 0)) {
811bool AArch64DAGToDAGISel::SelectArithImmed(SDValue
N, SDValue &Val,
821 uint64_t Immed =
N.getNode()->getAsZExtVal();
831 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
832 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
838bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue
N, SDValue &Val,
849 uint64_t Immed =
N.getNode()->getAsZExtVal();
857 if (
N.getValueType() == MVT::i32)
858 Immed = ~((uint32_t)Immed) + 1;
860 Immed = ~Immed + 1ULL;
861 if (Immed & 0xFFFFFFFFFF000000ULL)
864 Immed &= 0xFFFFFFULL;
865 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(
N), MVT::i32), Val,
872 switch (
N.getOpcode()) {
898 unsigned ShiftVal = CSD->getZExtValue();
916bool AArch64DAGToDAGISel::isWorthFoldingAddr(SDValue V,
unsigned Size)
const {
919 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
924 if (Subtarget->hasAddrLSLSlow14() && (
Size == 2 ||
Size == 16))
932 const SDValue
LHS =
V.getOperand(0);
933 const SDValue
RHS =
V.getOperand(1);
946bool AArch64DAGToDAGISel::SelectShiftedRegisterFromAnd(SDValue
N, SDValue &
Reg,
948 EVT VT =
N.getValueType();
949 if (VT != MVT::i32 && VT != MVT::i64)
952 if (
N->getOpcode() !=
ISD::AND || !
N->hasOneUse())
954 SDValue
LHS =
N.getOperand(0);
958 unsigned LHSOpcode =
LHS->getOpcode();
972 unsigned LowZBits, MaskLen;
976 unsigned BitWidth =
N.getValueSizeInBits();
983 if (LowZBits <= ShiftAmtC || (
BitWidth != LowZBits + MaskLen))
986 NewShiftC = LowZBits - ShiftAmtC;
987 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
993 NewShiftC = LowZBits + ShiftAmtC;
1006 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1008 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
1012 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC,
DL, VT);
1013 SDValue BitWidthMinus1 = CurDAG->getTargetConstant(
BitWidth - 1,
DL, VT);
1014 Reg = SDValue(CurDAG->getMachineNode(NewShiftOp,
DL, VT,
LHS->getOperand(0),
1015 NewShiftAmt, BitWidthMinus1),
1018 Shift = CurDAG->getTargetConstant(ShVal,
DL, MVT::i32);
1032 SrcVT =
N.getOperand(0).getValueType();
1034 if (!IsLoadStore && SrcVT == MVT::i8)
1036 else if (!IsLoadStore && SrcVT == MVT::i16)
1038 else if (SrcVT == MVT::i32)
1040 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1045 EVT SrcVT =
N.getOperand(0).getValueType();
1046 if (!IsLoadStore && SrcVT == MVT::i8)
1048 else if (!IsLoadStore && SrcVT == MVT::i16)
1050 else if (SrcVT == MVT::i32)
1052 assert(SrcVT != MVT::i64 &&
"extend from 64-bits?");
1077bool AArch64DAGToDAGISel::isWorthNegatingImm(SDValue V)
const {
1080 EVT VT =
V.getValueType();
1081 assert((VT == MVT::i32 || VT == MVT::i64) &&
"invalid type");
1092 return NewCost.
size() < OrigCost.
size();
1099bool AArch64DAGToDAGISel::isWorthFoldingALU(SDValue V,
bool LSL)
const {
1102 if (CurDAG->shouldOptForSize() ||
V.hasOneUse())
1107 if (LSL && Subtarget->hasALULSLFast() &&
V.getOpcode() ==
ISD::SHL &&
1108 V.getConstantOperandVal(1) <= 4 &&
1121bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue
N,
bool AllowROR,
1122 SDValue &
Reg, SDValue &Shift) {
1123 if (SelectShiftedRegisterFromAnd(
N,
Reg, Shift))
1133 unsigned BitSize =
N.getValueSizeInBits();
1134 unsigned Val =
RHS->getZExtValue() & (BitSize - 1);
1137 Reg =
N.getOperand(0);
1138 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(
N), MVT::i32);
1139 return isWorthFoldingALU(
N,
true);
1150 if (
N.getValueType() == MVT::i32)
1158template<
signed Low,
signed High,
signed Scale>
1159bool AArch64DAGToDAGISel::SelectRDVLImm(SDValue
N, SDValue &
Imm) {
1164 if ((MulImm % std::abs(Scale)) == 0) {
1165 int64_t RDVLImm = MulImm / Scale;
1166 if ((RDVLImm >=
Low) && (RDVLImm <=
High)) {
1167 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(
N), MVT::i32);
1176template <
signed Low,
signed High>
1177bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue
N, SDValue &
Imm) {
1182 if (MulImm >=
Low && MulImm <=
High) {
1183 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(
N), MVT::i32);
1192bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue
N, SDValue &
Reg,
1194 unsigned ShiftVal = 0;
1209 Reg =
N.getOperand(0).getOperand(0);
1219 SDValue
Op =
N.getOperand(0);
1221 Op =
Op->getOperand(0);
1223 Op.getOperand(0).getValueType().isFixedLengthVector())
1227 Reg =
N.getOperand(0);
1231 auto isDef32 = [](SDValue
N) {
1232 unsigned Opc =
N.getOpcode();
1245 Reg.getValueType() == MVT::i32 &&
1256 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1258 return isWorthFoldingALU(
N);
1263bool AArch64DAGToDAGISel::SelectArithUXTXRegister(SDValue
N, SDValue &
Reg,
1265 unsigned ShiftVal = 0;
1279 Reg =
N.getOperand(0);
1280 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(
N),
1282 return isWorthFoldingALU(
N);
1291 for (
auto *
User :
N->users()) {
1318bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue
N,
bool IsSignedImm,
1319 unsigned BW,
unsigned Size,
1323 const DataLayout &
DL = CurDAG->getDataLayout();
1324 const TargetLowering *TLI = getTargetLowering();
1328 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1334 if (CurDAG->isBaseWithConstantOffset(
N)) {
1337 int64_t RHSC =
RHS->getSExtValue();
1339 int64_t
Range = 0x1LL << (BW - 1);
1341 if ((RHSC & (
Size - 1)) == 0 && RHSC >= -(
Range << Scale) &&
1342 RHSC < (
Range << Scale)) {
1343 Base =
N.getOperand(0);
1348 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1357 if ((RHSC & (
Size - 1)) == 0 && RHSC < (
Range << Scale)) {
1358 Base =
N.getOperand(0);
1363 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1374 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1381bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue
N,
unsigned Size,
1382 SDValue &
Base, SDValue &OffImm) {
1384 const DataLayout &
DL = CurDAG->getDataLayout();
1385 const TargetLowering *TLI = getTargetLowering();
1389 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1394 GlobalAddressSDNode *GAN =
1396 Base =
N.getOperand(0);
1406 if (CurDAG->isBaseWithConstantOffset(
N)) {
1408 int64_t RHSC = (int64_t)
RHS->getZExtValue();
1411 Base =
N.getOperand(0);
1416 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1424 if (SelectAddrModeUnscaled(
N,
Size,
Base, OffImm))
1432 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1441bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue
N,
unsigned Size,
1444 if (!CurDAG->isBaseWithConstantOffset(
N))
1447 int64_t RHSC =
RHS->getSExtValue();
1448 if (RHSC >= -256 && RHSC < 256) {
1449 Base =
N.getOperand(0);
1452 const TargetLowering *TLI = getTargetLowering();
1453 Base = CurDAG->getTargetFrameIndex(
1456 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(
N), MVT::i64);
1466 CurDAG->
getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1473bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue
N,
unsigned Size,
1474 bool WantExtend, SDValue &
Offset,
1475 SDValue &SignExtend) {
1493 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1499 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1502 return isWorthFoldingAddr(
N,
Size);
1505bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue
N,
unsigned Size,
1507 SDValue &SignExtend,
1511 SDValue
LHS =
N.getOperand(0);
1512 SDValue
RHS =
N.getOperand(1);
1523 const SDNode *
Node =
N.getNode();
1524 for (SDNode *UI :
Node->users()) {
1530 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1533 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1536 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1541 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1544 DoShift = CurDAG->getTargetConstant(
true, dl, MVT::i32);
1549 DoShift = CurDAG->getTargetConstant(
false, dl, MVT::i32);
1553 if (IsExtendedRegisterWorthFolding &&
1560 if (isWorthFoldingAddr(
LHS,
Size))
1565 if (IsExtendedRegisterWorthFolding &&
1572 if (isWorthFoldingAddr(
RHS,
Size))
1584 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1587 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1589 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1590 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1594bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue
N,
unsigned Size,
1596 SDValue &SignExtend,
1600 SDValue
LHS =
N.getOperand(0);
1601 SDValue
RHS =
N.getOperand(1);
1607 const SDNode *
Node =
N.getNode();
1608 for (SDNode *UI :
Node->users()) {
1625 int64_t ImmOff = (int64_t)
RHS->getAsZExtVal();
1635 CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
1636 SDValue MOVIV = SDValue(MOVI, 0);
1642 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(
N,
Size);
1645 if (IsExtendedRegisterWorthFolding &&
RHS.getOpcode() ==
ISD::SHL &&
1648 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1653 if (IsExtendedRegisterWorthFolding &&
LHS.getOpcode() ==
ISD::SHL &&
1656 DoShift = CurDAG->getTargetConstant(
true,
DL, MVT::i32);
1663 SignExtend = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1664 DoShift = CurDAG->getTargetConstant(
false,
DL, MVT::i32);
1670 static const unsigned RegClassIDs[] = {
1671 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1672 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1673 AArch64::dsub2, AArch64::dsub3};
1679 static const unsigned RegClassIDs[] = {
1680 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1681 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1682 AArch64::qsub2, AArch64::qsub3};
1688 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1689 AArch64::ZPR3RegClassID,
1690 AArch64::ZPR4RegClassID};
1691 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1692 AArch64::zsub2, AArch64::zsub3};
1702 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1703 AArch64::ZPR4Mul4RegClassID};
1704 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1705 AArch64::zsub2, AArch64::zsub3};
1710 const unsigned RegClassIDs[],
1711 const unsigned SubRegs[]) {
1714 if (Regs.
size() == 1)
1725 CurDAG->getTargetConstant(RegClassIDs[Regs.
size() - 2],
DL, MVT::i32));
1728 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1729 Ops.push_back(Regs[i]);
1730 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i],
DL, MVT::i32));
1734 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped,
Ops);
1735 return SDValue(
N, 0);
1738void AArch64DAGToDAGISel::SelectTable(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
1741 EVT VT =
N->getValueType(0);
1743 unsigned ExtOff = isExt;
1746 unsigned Vec0Off = ExtOff + 1;
1752 Ops.push_back(
N->getOperand(1));
1753 Ops.push_back(RegSeq);
1754 Ops.push_back(
N->getOperand(NumVecs + ExtOff + 1));
1755 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
1758static std::tuple<SDValue, SDValue>
1779 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
1784 AddrDisc = DAG->
getRegister(AArch64::XZR, MVT::i64);
1786 return std::make_tuple(
1791void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *
N) {
1794 SDValue Val =
N->getOperand(1);
1795 SDValue AUTKey =
N->getOperand(2);
1796 SDValue AUTDisc =
N->getOperand(3);
1799 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1801 SDValue AUTAddrDisc, AUTConstDisc;
1802 std::tie(AUTConstDisc, AUTAddrDisc) =
1806 std::vector<SDValue>
Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1808 if (
N->getNumOperands() > 4)
1809 Ops.push_back(
N->getOperand(4));
1812 CurDAG->getMachineNode(AArch64::AUTxMxN,
DL, MVT::i64, MVT::i64,
Ops);
1813 ReplaceNode(
N, AUT);
1815 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1816 AArch64::X16, Val, SDValue());
1817 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.
getValue(1)};
1819 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17,
DL, MVT::i64,
Ops);
1820 ReplaceNode(
N, AUT);
1824void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *
N) {
1834 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1839 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1840 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1842 SDValue AUTAddrDisc, AUTConstDisc;
1843 std::tie(AUTConstDisc, AUTAddrDisc) =
1846 SDValue PACAddrDisc, PACConstDisc;
1847 std::tie(PACConstDisc, PACAddrDisc) =
1850 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1851 AArch64::X16, Val, SDValue());
1854 SDValue Addend =
N->getOperand(OffsetBase + 6);
1855 SDValue IncomingChain =
N->getOperand(0);
1856 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1857 PACKey, PACConstDisc, PACAddrDisc,
1858 Addend, IncomingChain, X16Copy.
getValue(1)};
1860 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC,
DL,
1861 MVT::i64, MVT::Other,
Ops);
1862 ReplaceNode(
N, AUTRELLOADPAC);
1864 SDValue
Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1865 PACConstDisc, PACAddrDisc, X16Copy.
getValue(1)};
1867 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC,
DL, MVT::i64,
Ops);
1868 ReplaceNode(
N, AUTPAC);
1872void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *
N) {
1884 AUTKey = CurDAG->getTargetConstant(AUTKeyC,
DL, MVT::i64);
1885 PACKey = CurDAG->getTargetConstant(PACKeyC,
DL, MVT::i64);
1887 SDValue PACAddrDisc, PACConstDisc;
1888 std::tie(PACConstDisc, PACAddrDisc) =
1891 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
DL,
1892 AArch64::X17, Val, SDValue());
1893 SDValue X16Copy = CurDAG->getCopyToReg(
1894 CurDAG->getEntryNode(),
DL, AArch64::X16, AUTDisc, X17Copy.
getValue(1));
1895 SDValue X15Copy = CurDAG->getCopyToReg(
1896 CurDAG->getEntryNode(),
DL, AArch64::X15, AUTPC, X16Copy.
getValue(1));
1898 SDValue
Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1901 CurDAG->getMachineNode(AArch64::AUTPCPAC,
DL, MVT::i64,
Ops);
1902 ReplaceNode(
N, AUTPCPAC);
1905bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *
N) {
1907 if (
LD->isUnindexed())
1909 EVT VT =
LD->getMemoryVT();
1910 EVT DstVT =
N->getValueType(0);
1914 int OffsetVal = (int)
OffsetOp->getZExtValue();
1919 unsigned Opcode = 0;
1922 bool InsertTo64 =
false;
1925 (!Subtarget->
isLittleEndian() || (Subtarget->requiresStrictAlign() &&
1928 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1929 else if (VT == MVT::i32) {
1931 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1933 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1935 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1941 }
else if (VT == MVT::i16) {
1943 if (DstVT == MVT::i64)
1944 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
1946 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
1948 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
1949 InsertTo64 = DstVT == MVT::i64;
1954 }
else if (VT == MVT::i8) {
1956 if (DstVT == MVT::i64)
1957 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
1959 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
1961 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
1962 InsertTo64 = DstVT == MVT::i64;
1967 }
else if (VT == MVT::f16) {
1968 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1969 }
else if (VT == MVT::bf16) {
1970 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
1971 }
else if (VT == MVT::f32) {
1972 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
1973 }
else if (VT == MVT::f64 || (VT.
is64BitVector() && !UseLd1)) {
1974 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
1976 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
1978 if (IsPre || OffsetVal != 8)
1982 Opcode = AArch64::LD1Onev8b_POST;
1985 Opcode = AArch64::LD1Onev4h_POST;
1988 Opcode = AArch64::LD1Onev2s_POST;
1991 Opcode = AArch64::LD1Onev1d_POST;
1997 if (IsPre || OffsetVal != 16)
2001 Opcode = AArch64::LD1Onev16b_POST;
2004 Opcode = AArch64::LD1Onev8h_POST;
2007 Opcode = AArch64::LD1Onev4s_POST;
2010 Opcode = AArch64::LD1Onev2d_POST;
2017 SDValue Chain =
LD->getChain();
2018 SDValue
Base =
LD->getBasePtr();
2021 SDValue
Offset = UseLd1 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
2022 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
2024 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
2032 SDValue LoadedVal = SDValue(Res, 1);
2034 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
2035 LoadedVal = SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
2036 MVT::i64, LoadedVal, SubReg),
2040 ReplaceUses(SDValue(
N, 0), LoadedVal);
2041 ReplaceUses(SDValue(
N, 1), SDValue(Res, 0));
2042 ReplaceUses(SDValue(
N, 2), SDValue(Res, 2));
2043 CurDAG->RemoveDeadNode(
N);
2047void AArch64DAGToDAGISel::SelectLoad(SDNode *
N,
unsigned NumVecs,
unsigned Opc,
2048 unsigned SubRegIdx) {
2050 EVT VT =
N->getValueType(0);
2053 SDValue
Ops[] = {
N->getOperand(2),
2056 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2058 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2059 SDValue SuperReg = SDValue(Ld, 0);
2060 for (
unsigned i = 0; i < NumVecs; ++i)
2061 ReplaceUses(SDValue(
N, i),
2062 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2064 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2069 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2073 CurDAG->RemoveDeadNode(
N);
2076void AArch64DAGToDAGISel::SelectPostLoad(SDNode *
N,
unsigned NumVecs,
2077 unsigned Opc,
unsigned SubRegIdx) {
2079 EVT VT =
N->getValueType(0);
2082 SDValue
Ops[] = {
N->getOperand(1),
2086 const EVT ResTys[] = {MVT::i64,
2087 MVT::Untyped, MVT::Other};
2089 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2092 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2095 SDValue SuperReg = SDValue(Ld, 1);
2097 ReplaceUses(SDValue(
N, 0), SuperReg);
2099 for (
unsigned i = 0; i < NumVecs; ++i)
2100 ReplaceUses(SDValue(
N, i),
2101 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2108 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2109 CurDAG->RemoveDeadNode(
N);
2115std::tuple<unsigned, SDValue, SDValue>
2116AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *
N,
unsigned Opc_rr,
2118 const SDValue &OldBase,
2119 const SDValue &OldOffset,
2121 SDValue NewBase = OldBase;
2122 SDValue NewOffset = OldOffset;
2124 const bool IsRegImm = SelectAddrModeIndexedSVE<-8, 7>(
2125 N, OldBase, NewBase, NewOffset);
2129 const bool IsRegReg =
2130 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2133 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2146template <SelectTypeKind Kind>
2158 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2163 if (EltVT != MVT::i1)
2167 if (EltVT == MVT::bf16)
2169 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2199void AArch64DAGToDAGISel::SelectPExtPair(SDNode *
N,
unsigned Opc) {
2202 if (
Imm->getZExtValue() > 1)
2206 EVT VT =
N->getValueType(0);
2207 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2208 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2209 SDValue SuperReg = SDValue(WhilePair, 0);
2211 for (
unsigned I = 0;
I < 2; ++
I)
2212 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2213 AArch64::psub0 +
I,
DL, VT, SuperReg));
2215 CurDAG->RemoveDeadNode(
N);
2218void AArch64DAGToDAGISel::SelectWhilePair(SDNode *
N,
unsigned Opc) {
2220 EVT VT =
N->getValueType(0);
2222 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2)};
2224 SDNode *WhilePair = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2225 SDValue SuperReg = SDValue(WhilePair, 0);
2227 for (
unsigned I = 0;
I < 2; ++
I)
2228 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2229 AArch64::psub0 +
I,
DL, VT, SuperReg));
2231 CurDAG->RemoveDeadNode(
N);
2234void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *
N,
unsigned NumVecs,
2236 EVT VT =
N->getValueType(0);
2238 SDValue
Ops = createZTuple(Regs);
2240 SDNode *
Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2241 SDValue SuperReg = SDValue(Intrinsic, 0);
2242 for (
unsigned i = 0; i < NumVecs; ++i)
2243 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2244 AArch64::zsub0 + i,
DL, VT, SuperReg));
2246 CurDAG->RemoveDeadNode(
N);
2249void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *
N,
unsigned NumVecs,
2252 EVT VT =
N->getValueType(0);
2254 Ops.push_back(
N->getOperand(0));
2257 CurDAG->getMachineNode(Opcode,
DL, {MVT::Untyped, MVT::Other},
Ops);
2258 SDValue SuperReg = SDValue(Instruction, 0);
2260 for (
unsigned i = 0; i < NumVecs; ++i)
2261 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2262 AArch64::zsub0 + i,
DL, VT, SuperReg));
2265 unsigned ChainIdx = NumVecs;
2266 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Instruction, 1));
2267 CurDAG->RemoveDeadNode(
N);
2270void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *
N,
2275 assert(Opcode != 0 &&
"Unexpected opcode");
2278 EVT VT =
N->getValueType(0);
2279 SDUse *OpsIter =
N->op_begin() + 1;
2282 auto GetMultiVecOperand = [&]() {
2285 return createZMulTuple(Regs);
2289 Ops.push_back(*OpsIter++);
2291 Ops.push_back(GetMultiVecOperand());
2293 Ops.push_back(GetMultiVecOperand());
2295 Ops.push_back(*OpsIter++);
2298 Ops.append(OpsIter,
N->op_end());
2300 Intrinsic = CurDAG->getMachineNode(Opcode,
DL, MVT::Untyped,
Ops);
2301 SDValue SuperReg = SDValue(Intrinsic, 0);
2302 for (
unsigned i = 0; i < NumVecs; ++i)
2303 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2304 AArch64::zsub0 + i,
DL, VT, SuperReg));
2306 CurDAG->RemoveDeadNode(
N);
2309void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *
N,
unsigned NumVecs,
2310 unsigned Scale,
unsigned Opc_ri,
2311 unsigned Opc_rr,
bool IsIntr) {
2312 assert(Scale < 5 &&
"Invalid scaling value.");
2314 EVT VT =
N->getValueType(0);
2321 N, Opc_rr, Opc_ri,
N->getOperand(IsIntr ? 3 : 2),
2322 CurDAG->getTargetConstant(0,
DL, MVT::i64), Scale);
2324 SDValue
Ops[] = {
N->getOperand(IsIntr ? 2 : 1),
2328 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2330 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2331 SDValue SuperReg = SDValue(
Load, 0);
2332 for (
unsigned i = 0; i < NumVecs; ++i)
2333 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2334 AArch64::zsub0 + i,
DL, VT, SuperReg));
2337 unsigned ChainIdx = NumVecs;
2338 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2339 CurDAG->RemoveDeadNode(
N);
2342void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *
N,
2347 assert(Scale < 4 &&
"Invalid scaling value.");
2349 EVT VT =
N->getValueType(0);
2354 SDValue
Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
2357 findAddrModeSVELoadStore(
N, Opc_rr, Opc_ri,
Base,
Offset, Scale);
2359 SDValue
Ops[] = {PNg,
2363 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2365 SDNode *
Load = CurDAG->getMachineNode(
Opc,
DL, ResTys,
Ops);
2366 SDValue SuperReg = SDValue(
Load, 0);
2367 for (
unsigned i = 0; i < NumVecs; ++i)
2368 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2369 AArch64::zsub0 + i,
DL, VT, SuperReg));
2372 unsigned ChainIdx = NumVecs;
2373 ReplaceUses(SDValue(
N, ChainIdx), SDValue(
Load, 1));
2374 CurDAG->RemoveDeadNode(
N);
2377void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *
N,
unsigned NumVecs,
2379 if (
N->getValueType(0) != MVT::nxv4f32)
2381 SelectUnaryMultiIntrinsic(
N, NumVecs,
true, Opcode);
2384void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2385 unsigned NumOutVecs,
2389 if (
Imm->getZExtValue() > MaxImm)
2393 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2396 SDValue Chain =
Node->getOperand(0);
2397 SDValue
Ops[] = {ZtValue,
Node->getOperand(3),
Node->getOperand(4), Chain};
2399 EVT VT =
Node->getValueType(0);
2402 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2403 SDValue SuperReg = SDValue(Instruction, 0);
2405 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2406 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2407 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2410 unsigned ChainIdx = NumOutVecs;
2411 ReplaceUses(SDValue(Node, ChainIdx), SDValue(Instruction, 1));
2412 CurDAG->RemoveDeadNode(Node);
2415void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2416 unsigned NumIndexVecs) {
2417 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2418 "unexpected number of index vectors");
2420 constexpr unsigned FirstIndexOp = 3;
2421 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2423 if (!
Imm ||
Imm->getZExtValue() > 1)
2429 unsigned Lane =
Imm->getZExtValue();
2430 unsigned IndexOp = FirstIndexOp;
2431 if (NumIndexVecs == 3)
2434 SDValue TableTuple = createZTuple({
Node->getOperand(1),
Node->getOperand(2)});
2435 SDValue IndexTuple =
2436 createZTuple({
Node->getOperand(IndexOp),
Node->getOperand(IndexOp + 1)});
2437 SDValue
Ops[] = {TableTuple, IndexTuple,
Node->getOperand(ImmOp)};
2440 EVT VT =
Node->getValueType(0);
2442 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI,
DL, MVT::Untyped,
Ops);
2443 SDValue SuperReg = SDValue(Instruction, 0);
2445 for (
unsigned I = 0;
I < 4; ++
I)
2446 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2447 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2449 CurDAG->RemoveDeadNode(Node);
2452void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2453 unsigned NumOutVecs,
2455 unsigned NumInVecs) {
2456 assert((NumInVecs == 2 || NumInVecs == 3) &&
2457 "unexpected number of input vectors");
2460 if (!ImmToReg<AArch64::ZT0, 0>(
Node->getOperand(2), ZtValue))
2464 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2465 SDValue
Ops[] = {ZtValue, ZTuple,
Node->getOperand(0)};
2468 EVT VT =
Node->getValueType(0);
2471 CurDAG->getMachineNode(
Opc,
DL, {MVT::Untyped, MVT::Other},
Ops);
2472 SDValue SuperReg = SDValue(Instruction, 0);
2474 for (
unsigned I = 0;
I < NumOutVecs; ++
I)
2475 ReplaceUses(SDValue(Node,
I), CurDAG->getTargetExtractSubreg(
2476 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2478 ReplaceUses(SDValue(Node, NumOutVecs), SDValue(Instruction, 1));
2479 CurDAG->RemoveDeadNode(Node);
2482void AArch64DAGToDAGISel::SelectClamp(SDNode *
N,
unsigned NumVecs,
2485 EVT VT =
N->getValueType(0);
2488 SDValue Zd = createZMulTuple(Regs);
2489 SDValue Zn =
N->getOperand(1 + NumVecs);
2490 SDValue Zm =
N->getOperand(2 + NumVecs);
2492 SDValue
Ops[] = {Zd, Zn, Zm};
2495 SDValue SuperReg = SDValue(Intrinsic, 0);
2496 for (
unsigned i = 0; i < NumVecs; ++i)
2497 ReplaceUses(SDValue(
N, i), CurDAG->getTargetExtractSubreg(
2498 AArch64::zsub0 + i,
DL, VT, SuperReg));
2500 CurDAG->RemoveDeadNode(
N);
2530template <
unsigned MaxIdx,
unsigned Scale>
2531void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *
N,
unsigned NumVecs,
2532 unsigned BaseReg,
unsigned Op) {
2533 unsigned TileNum = 0;
2534 if (BaseReg != AArch64::ZA)
2535 TileNum =
N->getConstantOperandVal(2);
2541 if (BaseReg == AArch64::ZA)
2546 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2550 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2552 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2554 EVT VT =
N->getValueType(0);
2555 for (
unsigned I = 0;
I < NumVecs; ++
I)
2556 ReplaceUses(SDValue(
N,
I),
2557 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2560 unsigned ChainIdx = NumVecs;
2561 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2562 CurDAG->RemoveDeadNode(
N);
2565void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *
N,
unsigned NumVecs,
2566 unsigned Op,
unsigned MaxIdx,
2567 unsigned Scale,
unsigned BaseReg) {
2572 if (BaseReg != AArch64::ZA)
2576 if (!SelectSMETileSlice(SliceBase, MaxIdx,
Base,
Offset, Scale))
2583 if (BaseReg != AArch64::ZA )
2584 Ops.push_back(
N->getOperand(2));
2587 Ops.push_back(
N->getOperand(0));
2588 SDNode *Mov = CurDAG->getMachineNode(
Op,
DL, {MVT::Untyped, MVT::Other},
Ops);
2590 EVT VT =
N->getValueType(0);
2591 for (
unsigned I = 0;
I < NumVecs; ++
I)
2592 ReplaceUses(SDValue(
N,
I),
2593 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
2597 unsigned ChainIdx = NumVecs;
2598 ReplaceUses(SDValue(
N, ChainIdx), SDValue(Mov, 1));
2599 CurDAG->RemoveDeadNode(
N);
2602void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *
N,
2603 unsigned NumOutVecs,
2607 EVT VT =
N->getValueType(0);
2608 unsigned NumInVecs =
N->getNumOperands() - 1;
2612 assert((NumInVecs == 2 || NumInVecs == 4) &&
2613 "Don't know how to handle multi-register input!");
2615 Ops.push_back(createZMulTuple(Regs));
2618 for (
unsigned I = 0;
I < NumInVecs;
I++)
2619 Ops.push_back(
N->getOperand(1 +
I));
2622 SDNode *Res = CurDAG->getMachineNode(
Opc,
DL, MVT::Untyped,
Ops);
2623 SDValue SuperReg = SDValue(Res, 0);
2625 for (
unsigned I = 0;
I < NumOutVecs;
I++)
2626 ReplaceUses(SDValue(
N,
I), CurDAG->getTargetExtractSubreg(
2627 AArch64::zsub0 +
I,
DL, VT, SuperReg));
2628 CurDAG->RemoveDeadNode(
N);
2631void AArch64DAGToDAGISel::SelectStore(SDNode *
N,
unsigned NumVecs,
2634 EVT VT =
N->getOperand(2)->getValueType(0);
2642 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2651void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *
N,
unsigned NumVecs,
2652 unsigned Scale,
unsigned Opc_rr,
2658 SDValue RegSeq = createZTuple(Regs);
2664 N, Opc_rr, Opc_ri,
N->getOperand(NumVecs + 3),
2665 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2671 SDNode *St = CurDAG->getMachineNode(
Opc, dl,
N->getValueType(0),
Ops);
2680void AArch64DAGToDAGISel::SelectPostStore(SDNode *
N,
unsigned NumVecs,
2683 EVT VT =
N->getOperand(2)->getValueType(0);
2684 const EVT ResTys[] = {MVT::i64,
2692 SDValue
Ops[] = {RegSeq,
2696 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2714 SDValue operator()(SDValue V64Reg) {
2740void AArch64DAGToDAGISel::SelectLoadLane(SDNode *
N,
unsigned NumVecs,
2743 EVT VT =
N->getValueType(0);
2755 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2757 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2759 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2761 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2762 SDValue SuperReg = SDValue(Ld, 0);
2765 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2766 AArch64::qsub2, AArch64::qsub3 };
2767 for (
unsigned i = 0; i < NumVecs; ++i) {
2768 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2771 ReplaceUses(SDValue(
N, i), NV);
2774 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 1));
2775 CurDAG->RemoveDeadNode(
N);
2778void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *
N,
unsigned NumVecs,
2781 EVT VT =
N->getValueType(0);
2793 const EVT ResTys[] = {MVT::i64,
2796 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2798 SDValue
Ops[] = {RegSeq,
2799 CurDAG->getTargetConstant(LaneNo, dl,
2804 SDNode *Ld = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2807 ReplaceUses(SDValue(
N, NumVecs), SDValue(Ld, 0));
2810 SDValue SuperReg = SDValue(Ld, 1);
2812 ReplaceUses(SDValue(
N, 0),
2816 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2817 AArch64::qsub2, AArch64::qsub3 };
2818 for (
unsigned i = 0; i < NumVecs; ++i) {
2819 SDValue
NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2823 ReplaceUses(SDValue(
N, i), NV);
2828 ReplaceUses(SDValue(
N, NumVecs + 1), SDValue(Ld, 2));
2829 CurDAG->RemoveDeadNode(
N);
2832void AArch64DAGToDAGISel::SelectStoreLane(SDNode *
N,
unsigned NumVecs,
2835 EVT VT =
N->getOperand(2)->getValueType(0);
2847 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 2);
2849 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2851 SDNode *St = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
2860void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *
N,
unsigned NumVecs,
2863 EVT VT =
N->getOperand(2)->getValueType(0);
2875 const EVT ResTys[] = {MVT::i64,
2878 unsigned LaneNo =
N->getConstantOperandVal(NumVecs + 1);
2880 SDValue
Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2884 SDNode *St = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2895 unsigned &LSB,
unsigned &MSB,
2896 unsigned NumberOfIgnoredLowBits,
2897 bool BiggerPattern) {
2899 "N must be a AND operation to call this function");
2901 EVT VT =
N->getValueType(0);
2906 assert((VT == MVT::i32 || VT == MVT::i64) &&
2907 "Type checking must have been done before calling this function");
2921 const SDNode *Op0 =
N->getOperand(0).getNode();
2928 if (AndImm & (AndImm + 1))
2931 bool ClampMSB =
false;
2951 ClampMSB = (VT == MVT::i32);
2952 }
else if (BiggerPattern) {
2958 Opd0 =
N->getOperand(0);
2964 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.
getSizeInBits())) {
2967 <<
": Found large shift immediate, this should not happen\n"));
2981 MSB = MSB > 31 ? 31 : MSB;
2983 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
2988 SDValue &Opd0,
unsigned &Immr,
2992 EVT VT =
N->getValueType(0);
2994 assert((VT == MVT::i32 || VT == MVT::i64) &&
2995 "Type checking must have been done before calling this function");
2999 Op =
Op->getOperand(0);
3000 VT =
Op->getValueType(0);
3009 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3013 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
3014 Opd0 =
Op.getOperand(0);
3016 Imms = ShiftImm + Width - 1;
3044 Opd0 =
N->getOperand(0).getOperand(0);
3054 Opc =
N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3061 unsigned &Immr,
unsigned &Imms,
3062 bool BiggerPattern) {
3064 "N must be a SHR/SRA operation to call this function");
3066 EVT VT =
N->getValueType(0);
3071 assert((VT == MVT::i32 || VT == MVT::i64) &&
3072 "Type checking must have been done before calling this function");
3082 Opd0 =
N->getOperand(0).getOperand(0);
3083 }
else if (VT == MVT::i32 &&
N->getOpcode() ==
ISD::SRL &&
3089 Opd0 =
N->getOperand(0).getOperand(0);
3092 assert(VT == MVT::i64 &&
"the promoted type should be i64");
3093 }
else if (BiggerPattern) {
3097 Opd0 =
N->getOperand(0);
3106 <<
": Found large shift immediate, this should not happen\n"));
3115 "bad amount in shift node!");
3116 int immr = SrlImm - ShlImm;
3121 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3123 Opc =
N->getOpcode() ==
ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3127bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *
N) {
3130 EVT VT =
N->getValueType(0);
3131 EVT NarrowVT =
N->getOperand(0)->getValueType(0);
3132 if (VT != MVT::i64 || NarrowVT != MVT::i32)
3136 SDValue
Op =
N->getOperand(0);
3142 SDValue Opd0 =
Widen(CurDAG,
Op.getOperand(0));
3143 unsigned Immr = ShiftImm;
3145 SDValue
Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3146 CurDAG->getTargetConstant(Imms, dl, VT)};
3147 CurDAG->SelectNodeTo(
N, AArch64::SBFMXri, VT,
Ops);
3152 SDValue &Opd0,
unsigned &Immr,
unsigned &Imms,
3153 unsigned NumberOfIgnoredLowBits = 0,
3154 bool BiggerPattern =
false) {
3155 if (
N->getValueType(0) != MVT::i32 &&
N->getValueType(0) != MVT::i64)
3158 switch (
N->getOpcode()) {
3160 if (!
N->isMachineOpcode())
3165 NumberOfIgnoredLowBits, BiggerPattern);
3174 unsigned NOpc =
N->getMachineOpcode();
3178 case AArch64::SBFMWri:
3179 case AArch64::UBFMWri:
3180 case AArch64::SBFMXri:
3181 case AArch64::UBFMXri:
3183 Opd0 =
N->getOperand(0);
3184 Immr =
N->getConstantOperandVal(1);
3185 Imms =
N->getConstantOperandVal(2);
3192bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *
N) {
3193 unsigned Opc, Immr, Imms;
3198 EVT VT =
N->getValueType(0);
3203 if ((
Opc == AArch64::SBFMXri ||
Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3204 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3205 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3207 SDNode *BFM = CurDAG->getMachineNode(
Opc, dl, MVT::i64, Ops64);
3208 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3209 MVT::i32, SDValue(BFM, 0));
3214 SDValue
Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3215 CurDAG->getTargetConstant(Imms, dl, VT)};
3216 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
3225 unsigned NumberOfIgnoredHighBits,
EVT VT) {
3226 assert((VT == MVT::i32 || VT == MVT::i64) &&
3227 "i32 or i64 mask type expected!");
3231 APInt SignificantDstMask =
3235 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3236 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3269 APInt OpUsefulBits(UsefulBits);
3273 OpUsefulBits <<= MSB -
Imm + 1;
3278 OpUsefulBits <<=
Imm;
3280 OpUsefulBits <<= MSB + 1;
3289 UsefulBits &= OpUsefulBits;
3306 APInt Mask(UsefulBits);
3307 Mask.clearAllBits();
3315 Mask.lshrInPlace(ShiftAmt);
3321 Mask.lshrInPlace(ShiftAmt);
3337 APInt OpUsefulBits(UsefulBits);
3351 OpUsefulBits <<= Width;
3354 if (
Op.getOperand(1) == Orig) {
3356 Mask = ResultUsefulBits & OpUsefulBits;
3360 if (
Op.getOperand(0) == Orig)
3362 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3368 OpUsefulBits <<= Width;
3370 OpUsefulBits <<= LSB;
3372 if (
Op.getOperand(1) == Orig) {
3374 Mask = ResultUsefulBits & OpUsefulBits;
3375 Mask.lshrInPlace(LSB);
3378 if (
Op.getOperand(0) == Orig)
3379 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3396 case AArch64::ANDSWri:
3397 case AArch64::ANDSXri:
3398 case AArch64::ANDWri:
3399 case AArch64::ANDXri:
3403 case AArch64::UBFMWri:
3404 case AArch64::UBFMXri:
3407 case AArch64::ORRWrs:
3408 case AArch64::ORRXrs:
3413 case AArch64::BFMWri:
3414 case AArch64::BFMXri:
3417 case AArch64::STRBBui:
3418 case AArch64::STURBBi:
3424 case AArch64::STRHHui:
3425 case AArch64::STURHHi:
3438 unsigned Bitwidth =
Op.getScalarValueSizeInBits();
3440 UsefulBits =
APInt(Bitwidth, 0);
3449 UsersUsefulBits |= UsefulBitsForUse;
3454 UsefulBits &= UsersUsefulBits;
3464 EVT VT =
Op.getValueType();
3467 unsigned UBFMOpc =
BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3470 if (ShlAmount > 0) {
3473 UBFMOpc, dl, VT,
Op,
3478 assert(ShlAmount < 0 &&
"expected right shift");
3479 int ShrAmount = -ShlAmount;
3492 SDValue &Src,
int &DstLSB,
3499 SDValue &Src,
int &DstLSB,
3505 bool BiggerPattern,
SDValue &Src,
3506 int &DstLSB,
int &Width) {
3507 EVT VT =
Op.getValueType();
3520 switch (
Op.getOpcode()) {
3525 NonZeroBits, Src, DstLSB, Width);
3528 NonZeroBits, Src, DstLSB, Width);
3541 EVT VT =
Op.getValueType();
3542 assert((VT == MVT::i32 || VT == MVT::i64) &&
3543 "Caller guarantees VT is one of i32 or i64");
3556 assert((~AndImm & NonZeroBits) == 0 &&
3557 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3586 if (!BiggerPattern && !AndOp0.
hasOneUse())
3605 <<
"Found large Width in bit-field-positioning -- this indicates no "
3606 "proper combining / constant folding was performed\n");
3615 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3630 "Op.getNode() should be a SHL node to call this function");
3632 "Op.getNode() should shift ShlImm to call this function");
3639 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3663 EVT VT =
Op.getValueType();
3664 assert((VT == MVT::i32 || VT == MVT::i64) &&
3665 "Caller guarantees that type is i32 or i64");
3672 if (!BiggerPattern && !
Op.hasOneUse())
3681 if (ShlImm !=
uint64_t(DstLSB) && !BiggerPattern)
3689 assert(VT == MVT::i32 || VT == MVT::i64);
3700 EVT VT =
N->getValueType(0);
3701 if (VT != MVT::i32 && VT != MVT::i64)
3719 if (!
And.hasOneUse() ||
3736 if ((OrImm & NotKnownZero) != 0) {
3748 unsigned ImmS = Width - 1;
3754 bool IsBFI = LSB != 0;
3759 unsigned OrChunks = 0, BFIChunks = 0;
3760 for (
unsigned Shift = 0; Shift <
BitWidth; Shift += 16) {
3761 if (((OrImm >> Shift) & 0xFFFF) != 0)
3763 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3766 if (BFIChunks > OrChunks)
3772 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3780 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3789 if (!Dst.hasOneUse())
3792 EVT VT = Dst.getValueType();
3793 assert((VT == MVT::i32 || VT == MVT::i64) &&
3794 "Caller should guarantee that VT is one of i32 or i64");
3822 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3823 unsigned MaskWidth =
3826 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3832 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1,
DL, VT));
3833 ShiftedOperand =
SDValue(UBFMNode, 0);
3862 const bool BiggerPattern) {
3863 EVT VT =
N->getValueType(0);
3864 assert(
N->getOpcode() ==
ISD::OR &&
"Expect N to be an OR node");
3865 assert(((
N->getOperand(0) == OrOpd0 &&
N->getOperand(1) == OrOpd1) ||
3866 (
N->getOperand(1) == OrOpd0 &&
N->getOperand(0) == OrOpd1)) &&
3867 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3868 assert((VT == MVT::i32 || VT == MVT::i64) &&
3869 "Expect result type to be i32 or i64 since N is combinable to BFM");
3876 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3879 if (BiggerPattern) {
3902 assert((!BiggerPattern) &&
"BiggerPattern should be handled above");
3964 EVT VT =
N->getValueType(0);
3965 if (VT != MVT::i32 && VT != MVT::i64)
3973 unsigned NumberOfIgnoredLowBits = UsefulBits.
countr_zero();
3974 unsigned NumberOfIgnoredHighBits = UsefulBits.
countl_zero();
3994 for (
int I = 0;
I < 4; ++
I) {
3997 unsigned ImmR, ImmS;
3998 bool BiggerPattern =
I / 2;
3999 SDValue OrOpd0Val =
N->getOperand(
I % 2);
4001 SDValue OrOpd1Val =
N->getOperand((
I + 1) % 2);
4007 NumberOfIgnoredLowBits, BiggerPattern)) {
4010 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
4011 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
4016 Width = ImmS - ImmR + 1;
4027 Src, DstLSB, Width)) {
4035 assert((VT == MVT::i32 || VT == MVT::i64) &&
"unexpected OR operand");
4045 APInt BitsToBeInserted =
4048 if ((BitsToBeInserted & ~
Known.Zero) != 0)
4072 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4105 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4107 if (Src->hasOneUse() &&
4110 Src = Src->getOperand(0);
4120 unsigned ImmS = Width - 1;
4126 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4134bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *
N) {
4143 CurDAG->SelectNodeTo(
N, TargetOpcode::IMPLICIT_DEF,
N->getValueType(0));
4156bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *
N) {
4160 EVT VT =
N->getValueType(0);
4161 if (VT != MVT::i32 && VT != MVT::i64)
4167 Op0, DstLSB, Width))
4173 unsigned ImmS = Width - 1;
4176 SDValue
Ops[] = {Op0, CurDAG->getTargetConstant(ImmR,
DL, VT),
4177 CurDAG->getTargetConstant(ImmS,
DL, VT)};
4178 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4179 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4185bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4186 EVT VT =
N->getValueType(0);
4189 switch (
N->getOpcode()) {
4191 Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr;
4194 Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr;
4197 Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr;
4200 Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr;
4208 if (VT == MVT::i32) {
4211 }
else if (VT == MVT::i64) {
4217 SDValue ShiftAmt =
N->getOperand(1);
4219 SDValue NewShiftAmt;
4237 (Add0Imm %
Size == 0)) {
4243 if (SubVT == MVT::i32) {
4244 NegOpc = AArch64::SUBWrr;
4245 ZeroReg = AArch64::WZR;
4247 assert(SubVT == MVT::i64);
4248 NegOpc = AArch64::SUBXrr;
4249 ZeroReg = AArch64::XZR;
4252 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4253 MachineSDNode *Neg =
4254 CurDAG->getMachineNode(NegOpc,
DL, SubVT, Zero, Add1);
4255 NewShiftAmt = SDValue(Neg, 0);
4263 if (SubVT == MVT::i32) {
4264 NotOpc = AArch64::ORNWrr;
4265 ZeroReg = AArch64::WZR;
4267 assert(SubVT == MVT::i64);
4268 NotOpc = AArch64::ORNXrr;
4269 ZeroReg = AArch64::XZR;
4272 CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
DL, ZeroReg, SubVT);
4273 MachineSDNode *
Not =
4274 CurDAG->getMachineNode(NotOpc,
DL, SubVT, Zero, Add1);
4275 NewShiftAmt = SDValue(
Not, 0);
4296 else if (VT == MVT::i64 && NewShiftAmt->
getValueType(0) == MVT::i32) {
4297 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32,
DL, MVT::i32);
4298 MachineSDNode *Ext = CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT,
4299 NewShiftAmt, SubReg);
4300 NewShiftAmt = SDValue(Ext, 0);
4303 SDValue
Ops[] = {
N->getOperand(0), NewShiftAmt};
4304 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
4311 bool isReciprocal) {
4314 FVal = CN->getValueAPF();
4317 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4327 if (
unsigned FBits =
4340 bool isReciprocal) {
4341 if ((
N.getOpcode() == AArch64ISD::NVCAST ||
N.getOpcode() ==
ISD::BITCAST) &&
4342 N.getValueType().getScalarSizeInBits() ==
4343 N.getOperand(0).getValueType().getScalarSizeInBits())
4344 N =
N.getOperand(0);
4346 auto ImmToFloat = [RegWidth](
APInt Imm) {
4360 switch (
N->getOpcode()) {
4361 case AArch64ISD::MOVIshift:
4362 FVal = ImmToFloat(
APInt(RegWidth,
N.getConstantOperandVal(0)
4363 <<
N.getConstantOperandVal(1)));
4365 case AArch64ISD::FMOV:
4366 FVal = ImmToFloat(
DecodeFMOVImm(
N.getConstantOperandVal(0), RegWidth));
4368 case AArch64ISD::DUP:
4370 FVal = ImmToFloat(
N.getConstantOperandAPInt(0).trunc(RegWidth));
4378 if (
unsigned FBits =
4387bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue
N, SDValue &FixedPos,
4388 unsigned RegWidth) {
4393bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(SDValue
N, SDValue &FixedPos,
4394 unsigned RegWidth) {
4396 CurDAG,
N, FixedPos, RegWidth,
false);
4399bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(SDValue
N,
4401 unsigned RegWidth) {
4403 CurDAG,
N, FixedPos, RegWidth,
true);
4406bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(SDValue
N,
4408 unsigned RegWidth) {
4418 RegString.
split(Fields,
':');
4420 if (Fields.
size() == 1)
4424 &&
"Invalid number of fields in read register string");
4427 bool AllIntFields =
true;
4431 AllIntFields &= !
Field.getAsInteger(10, IntField);
4432 Ops.push_back(IntField);
4436 "Unexpected non-integer value in special register string.");
4441 return (
Ops[0] << 14) | (
Ops[1] << 11) | (
Ops[2] << 7) | (
Ops[3] << 3) |
4449bool AArch64DAGToDAGISel::tryReadRegister(SDNode *
N) {
4451 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4454 bool ReadIs128Bit =
N->getOpcode() == AArch64ISD::MRRS;
4456 unsigned Opcode64Bit = AArch64::MRS;
4461 const auto *TheReg =
4462 AArch64SysReg::lookupSysRegByName(RegString->getString());
4463 if (TheReg && TheReg->Readable &&
4464 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4465 Imm = TheReg->Encoding;
4471 if (!ReadIs128Bit && RegString->getString() ==
"pc") {
4472 Opcode64Bit = AArch64::ADR;
4481 RegString->getString());
4482 unsigned PseudoOp = 0;
4483 if (AArch64::GPR64RegClass.
contains(PReg))
4484 PseudoOp = AArch64::READ_REGISTER_GPR64;
4485 else if (AArch64::FPR64RegClass.
contains(PReg))
4486 PseudoOp = AArch64::READ_REGISTER_FPR64;
4487 if (!ReadIs128Bit && PseudoOp &&
N->getValueType(0) == MVT::i64) {
4488 CurDAG->SelectNodeTo(
N, PseudoOp, MVT::i64, MVT::Other,
4489 {CurDAG->getTargetConstant(PReg,
DL, MVT::i32),
4498 SDValue InChain =
N->getOperand(0);
4499 SDValue SysRegImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
4500 if (!ReadIs128Bit) {
4501 CurDAG->SelectNodeTo(
N, Opcode64Bit, MVT::i64, MVT::Other ,
4502 {SysRegImm, InChain});
4504 SDNode *MRRS = CurDAG->getMachineNode(
4506 {MVT::Untyped , MVT::Other },
4507 {SysRegImm, InChain});
4511 SDValue
Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64,
DL, MVT::i64,
4513 SDValue
Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64,
DL, MVT::i64,
4515 SDValue OutChain = SDValue(MRRS, 1);
4517 ReplaceUses(SDValue(
N, 0),
Lo);
4518 ReplaceUses(SDValue(
N, 1),
Hi);
4519 ReplaceUses(SDValue(
N, 2), OutChain);
4528bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *
N) {
4530 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
4533 bool WriteIs128Bit =
N->getOpcode() == AArch64ISD::MSRR;
4535 if (!WriteIs128Bit) {
4541 auto trySelectPState = [&](
auto PMapper,
unsigned State) {
4544 "Expected a constant integer expression.");
4545 unsigned Reg = PMapper->Encoding;
4546 uint64_t Immed =
N->getConstantOperandVal(2);
4547 CurDAG->SelectNodeTo(
4548 N, State, MVT::Other, CurDAG->getTargetConstant(
Reg,
DL, MVT::i32),
4549 CurDAG->getTargetConstant(Immed,
DL, MVT::i16),
N->getOperand(0));
4555 if (trySelectPState(
4556 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4557 AArch64::MSRpstateImm4))
4559 if (trySelectPState(
4560 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4561 AArch64::MSRpstateImm1))
4570 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4571 if (TheReg && TheReg->Writeable &&
4572 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4573 Imm = TheReg->Encoding;
4583 RegString->getString());
4584 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4585 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4586 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4587 N->getOperand(2).getValueType() == MVT::i64) {
4589 CurDAG->getCopyToReg(
N->getOperand(0),
DL, PReg,
N->getOperand(2));
4590 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4591 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE,
DL,
4592 MVT::Other, {RegOp,
Copy});
4593 ReplaceUses(SDValue(
N, 0), SDValue(FakeUse, 0));
4594 CurDAG->RemoveDeadNode(
N);
4602 if (!WriteIs128Bit) {
4603 CurDAG->SelectNodeTo(
N, AArch64::MSR, MVT::Other,
4604 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4605 N->getOperand(2), InChain);
4609 SDNode *Pair = CurDAG->getMachineNode(
4610 TargetOpcode::REG_SEQUENCE,
DL, MVT::Untyped ,
4611 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(),
DL,
4614 CurDAG->getTargetConstant(AArch64::sube64,
DL, MVT::i32),
4616 CurDAG->getTargetConstant(AArch64::subo64,
DL, MVT::i32)});
4618 CurDAG->SelectNodeTo(
N, AArch64::MSRR, MVT::Other,
4619 CurDAG->getTargetConstant(
Imm,
DL, MVT::i32),
4620 SDValue(Pair, 0), InChain);
4627bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
4632 if (Subtarget->hasLSE())
return false;
4634 if (MemTy == MVT::i8)
4635 Opcode = AArch64::CMP_SWAP_8;
4636 else if (MemTy == MVT::i16)
4637 Opcode = AArch64::CMP_SWAP_16;
4638 else if (MemTy == MVT::i32)
4639 Opcode = AArch64::CMP_SWAP_32;
4640 else if (MemTy == MVT::i64)
4641 Opcode = AArch64::CMP_SWAP_64;
4645 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4646 SDValue
Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
4648 SDNode *CmpSwap = CurDAG->getMachineNode(
4650 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other),
Ops);
4655 ReplaceUses(SDValue(
N, 0), SDValue(CmpSwap, 0));
4656 ReplaceUses(SDValue(
N, 1), SDValue(CmpSwap, 2));
4657 CurDAG->RemoveDeadNode(
N);
4663AArch64DAGToDAGISel::decodeMemoryHintFlags(MachineMemOperand *MMO)
const {
4664 int MemoryHint = -1;
4667 return AArch64MemoryHint::NONE;
4680bool AArch64DAGToDAGISel::isAtomicSTSHH_KEEP(SDNode *
N)
const {
4682 AArch64MemoryHint::STSHH_KEEP;
4685bool AArch64DAGToDAGISel::isAtomicSTSHH_STRM(SDNode *
N)
const {
4687 AArch64MemoryHint::STSHH_STRM;
4690bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue
N, MVT VT, SDValue &
Imm,
4691 SDValue &Shift,
bool Negate) {
4698 return SelectSVEAddSubImm(SDLoc(
N), Val, VT,
Imm, Shift, Negate);
4701bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc
DL, APInt Val, MVT VT,
4702 SDValue &
Imm, SDValue &Shift,
4710 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4717 if ((Val & ~0xff) == 0) {
4718 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4723 if ((Val & ~0xff00) == 0) {
4724 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4736bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(SDValue
N, MVT VT,
4737 SDValue &
Imm, SDValue &Shift,
4760 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4761 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4768 Shift = CurDAG->getTargetConstant(0,
DL, MVT::i32);
4769 Imm = CurDAG->getTargetConstant(Val,
DL, MVT::i32);
4773 if (Val <= 65280 && Val % 256 == 0) {
4774 Shift = CurDAG->getTargetConstant(8,
DL, MVT::i32);
4775 Imm = CurDAG->getTargetConstant(Val >> 8,
DL, MVT::i32);
4786bool AArch64DAGToDAGISel::SelectSVECpyDupImm(SDValue
N, MVT VT, SDValue &
Imm,
4796 int32_t ImmVal, ShiftVal;
4801 Shift = CurDAG->getTargetConstant(ShiftVal,
DL, MVT::i32);
4802 Imm = CurDAG->getTargetConstant(ImmVal,
DL, MVT::i32);
4806bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDValue
N, SDValue &
Imm) {
4808 return SelectSVESignedArithImm(SDLoc(
N), CNode->getAPIntValue(),
Imm);
4812bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc
DL, APInt Val,
4815 if (ImmVal >= -128 && ImmVal < 128) {
4816 Imm = CurDAG->getSignedTargetConstant(ImmVal,
DL, MVT::i32);
4822bool AArch64DAGToDAGISel::SelectSVEArithImm(SDValue
N, MVT VT, SDValue &
Imm) {
4824 uint64_t ImmVal = CNode->getZExtValue();
4834 ImmVal &= 0xFFFFFFFF;
4843 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4850bool AArch64DAGToDAGISel::SelectSVELogicalImm(SDValue
N, MVT VT, SDValue &
Imm,
4854 ImmVal = CI->getZExtValue();
4856 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4867 Imm = CurDAG->getTargetConstant(encoding, SDLoc(
N), MVT::i64);
4876bool AArch64DAGToDAGISel::SelectSVEShiftImm(SDValue
N,
uint64_t Low,
4880 uint64_t ImmVal = CN->getZExtValue();
4887 if (ImmVal >
High) {
4888 if (!AllowSaturation)
4893 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(
N), MVT::i32);
4900bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *
N) {
4908 SDValue IRG_SP =
N->getOperand(2);
4914 const TargetLowering *TLI = getTargetLowering();
4917 SDValue FiOp = CurDAG->getTargetFrameIndex(
4919 int TagOffset =
N->getConstantOperandVal(3);
4921 SDNode *
Out = CurDAG->getMachineNode(
4922 AArch64::TAGPstack,
DL, MVT::i64,
4923 {FiOp, CurDAG->getTargetConstant(0,
DL, MVT::i64),
N->
getOperand(2),
4924 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4925 ReplaceNode(
N, Out);
4929void AArch64DAGToDAGISel::SelectTagP(SDNode *
N) {
4931 "llvm.aarch64.tagp third argument must be an immediate");
4932 if (trySelectStackSlotTagP(
N))
4939 int TagOffset =
N->getConstantOperandVal(3);
4940 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP,
DL, MVT::i64,
4941 {
N->getOperand(1),
N->getOperand(2)});
4942 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr,
DL, MVT::i64,
4943 {SDValue(N1, 0),
N->getOperand(2)});
4944 SDNode *N3 = CurDAG->getMachineNode(
4945 AArch64::ADDG,
DL, MVT::i64,
4946 {SDValue(N2, 0), CurDAG->getTargetConstant(0,
DL, MVT::i64),
4947 CurDAG->getTargetConstant(TagOffset,
DL, MVT::i64)});
4951bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *
N) {
4955 if (
N->getConstantOperandVal(2) != 0)
4957 if (!
N->getOperand(0).isUndef())
4961 EVT VT =
N->getValueType(0);
4962 EVT InVT =
N->getOperand(1).getValueType();
4973 "Expected to insert into a packed scalable vector!");
4976 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
4977 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
4978 N->getOperand(1), RC));
4982bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *
N) {
4986 if (
N->getConstantOperandVal(1) != 0)
4990 EVT VT =
N->getValueType(0);
4991 EVT InVT =
N->getOperand(0).getValueType();
5002 "Expected to extract from a packed scalable vector!");
5005 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID,
DL, MVT::i64);
5006 ReplaceNode(
N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
DL, VT,
5007 N->getOperand(0), RC));
5011bool AArch64DAGToDAGISel::trySelectXAR(SDNode *
N) {
5014 SDValue N0 =
N->getOperand(0);
5017 EVT VT =
N->getValueType(0);
5030 (Subtarget->hasSVE2() ||
5031 (Subtarget->hasSME() && Subtarget->
isStreaming()))) {
5032 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
5035 if (N0.
getOpcode() != AArch64ISD::SHL_PRED ||
5039 auto *TLI =
static_cast<const AArch64TargetLowering *
>(getTargetLowering());
5040 if (!TLI->isAllActivePredicate(*CurDAG, N0.
getOperand(0)) ||
5041 !TLI->isAllActivePredicate(*CurDAG, N1.
getOperand(0)))
5048 bool IsXOROperand =
true;
5050 IsXOROperand =
false;
5056 APInt ShlAmt, ShrAmt;
5064 if (!IsXOROperand) {
5065 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
5066 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, VT, Zero);
5067 SDValue MOVIV = SDValue(MOV, 0);
5069 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5070 SDNode *SubRegToReg =
5071 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG,
DL, VT, MOVIV, ZSub);
5074 R2 = SDValue(SubRegToReg, 0);
5082 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5083 AArch64::XAR_ZZZI_D})) {
5084 CurDAG->SelectNodeTo(
N,
Opc, VT,
Ops);
5109 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5119 if (N0->
getOpcode() != AArch64ISD::VSHL ||
5127 bool IsXOROperand =
true;
5129 IsXOROperand =
false;
5132 R1 =
XOR.getOperand(0);
5133 R2 =
XOR.getOperand(1);
5139 SDValue
Imm = CurDAG->getTargetConstant(
5143 if (ShAmt + HsAmt != VTSizeInBits)
5146 if (!IsXOROperand) {
5147 SDValue
Zero = CurDAG->getTargetConstant(0,
DL, MVT::i64);
5149 CurDAG->getMachineNode(AArch64::MOVIv2d_ns,
DL, MVT::v2i64, Zero);
5150 SDValue MOVIV = SDValue(MOV, 0);
5158 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, SVT), 0);
5163 SDValue UndefQ = SDValue(
5164 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, QVT), 0);
5165 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5167 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5170 if (
R2.getValueType() == VT)
5171 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, QVT,
5176 SDValue SubReg = CurDAG->getTargetConstant(
5179 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
Undef,
5184 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG,
DL, SVT,
5190 SDNode *XAR =
nullptr;
5194 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5195 AArch64::XAR_ZZZI_D}))
5196 XAR = CurDAG->getMachineNode(
Opc,
DL, SVT,
Ops);
5198 XAR = CurDAG->getMachineNode(AArch64::XAR,
DL, SVT,
Ops);
5201 assert(XAR &&
"Unexpected NULL value for XAR instruction in DAG");
5207 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub,
DL, MVT::i32);
5208 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, QVT,
5209 SDValue(XAR, 0), ZSub);
5211 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub,
DL, MVT::i32);
5212 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5213 SDValue(Q, 0), DSub);
5215 SDValue SubReg = CurDAG->getTargetConstant(
5218 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG,
DL, VT,
5219 SDValue(XAR, 0), SubReg);
5222 ReplaceNode(
N, XAR);
5229 assert(VT == MVT::i32 || VT == MVT::i64);
5231 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5234void AArch64DAGToDAGISel::Select(SDNode *Node) {
5236 if (
Node->isMachineOpcode()) {
5238 Node->setNodeId(-1);
5243 EVT VT =
Node->getValueType(0);
5245 switch (
Node->getOpcode()) {
5250 if (SelectCMP_SWAP(Node))
5255 case AArch64ISD::MRRS:
5256 if (tryReadRegister(Node))
5261 case AArch64ISD::MSRR:
5262 if (tryWriteRegister(Node))
5269 if (tryIndexedLoad(Node))
5278 if (tryBitfieldExtractOp(Node))
5280 if (tryBitfieldInsertInZeroOp(Node))
5285 if (tryShiftAmountMod(Node))
5290 if (tryBitfieldExtractOpFromSExt(Node))
5295 if (tryBitfieldInsertOp(Node))
5297 if (trySelectXAR(Node))
5302 if (trySelectCastScalableToFixedLengthVector(Node))
5308 if (trySelectCastFixedLengthToScalableVector(Node))
5313 case AArch64ISD::CSEL:
5314 if (tryFoldCselToFMaxMin(Node))
5322 if (ConstNode->
isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5333 const TargetLowering *TLI = getTargetLowering();
5334 SDValue TFI = CurDAG->getTargetFrameIndex(
5337 SDValue
Ops[] = { TFI, CurDAG->getTargetConstant(0,
DL, MVT::i32),
5338 CurDAG->getTargetConstant(Shifter,
DL, MVT::i32) };
5339 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64,
Ops);
5343 unsigned IntNo =
Node->getConstantOperandVal(1);
5347 case Intrinsic::aarch64_gcsss: {
5349 SDValue Chain =
Node->getOperand(0);
5350 SDValue Val =
Node->getOperand(2);
5351 SDValue
Zero = CurDAG->getCopyFromReg(Chain,
DL, AArch64::XZR, MVT::i64);
5353 CurDAG->getMachineNode(AArch64::GCSSS1,
DL, MVT::Other, Val, Chain);
5354 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2,
DL, MVT::i64,
5355 MVT::Other, Zero, SDValue(SS1, 0));
5356 ReplaceNode(Node, SS2);
5359 case Intrinsic::aarch64_ldaxp:
5360 case Intrinsic::aarch64_ldxp: {
5362 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5363 SDValue MemAddr =
Node->getOperand(2);
5365 SDValue Chain =
Node->getOperand(0);
5367 SDNode *Ld = CurDAG->getMachineNode(
Op,
DL, MVT::i64, MVT::i64,
5368 MVT::Other, MemAddr, Chain);
5371 MachineMemOperand *MemOp =
5374 ReplaceNode(Node, Ld);
5377 case Intrinsic::aarch64_stlxp:
5378 case Intrinsic::aarch64_stxp: {
5380 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5382 SDValue Chain =
Node->getOperand(0);
5383 SDValue ValLo =
Node->getOperand(2);
5384 SDValue ValHi =
Node->getOperand(3);
5385 SDValue MemAddr =
Node->getOperand(4);
5388 SDValue
Ops[] = {ValLo, ValHi, MemAddr, Chain};
5390 SDNode *St = CurDAG->getMachineNode(
Op,
DL, MVT::i32, MVT::Other,
Ops);
5392 MachineMemOperand *MemOp =
5396 ReplaceNode(Node, St);
5399 case Intrinsic::aarch64_neon_ld1x2:
5400 if (VT == MVT::v8i8) {
5401 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5403 }
else if (VT == MVT::v16i8) {
5404 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5406 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5407 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5409 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5410 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5412 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5413 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5415 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5416 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5418 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5419 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5421 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5422 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5426 case Intrinsic::aarch64_neon_ld1x3:
5427 if (VT == MVT::v8i8) {
5428 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5430 }
else if (VT == MVT::v16i8) {
5431 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5433 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5434 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5436 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5437 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5439 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5440 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5442 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5443 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5445 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5446 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5448 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5449 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5453 case Intrinsic::aarch64_neon_ld1x4:
5454 if (VT == MVT::v8i8) {
5455 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5457 }
else if (VT == MVT::v16i8) {
5458 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5460 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5461 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5463 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5464 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5466 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5467 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5469 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5470 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5472 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5473 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5475 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5476 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5480 case Intrinsic::aarch64_neon_ld2:
5481 if (VT == MVT::v8i8) {
5482 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5484 }
else if (VT == MVT::v16i8) {
5485 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5487 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5488 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5490 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5491 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5493 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5494 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5496 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5497 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5499 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5500 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5502 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5503 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5507 case Intrinsic::aarch64_neon_ld3:
5508 if (VT == MVT::v8i8) {
5509 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5511 }
else if (VT == MVT::v16i8) {
5512 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5514 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5515 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5517 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5518 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5520 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5521 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5523 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5524 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5526 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5527 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5529 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5530 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5534 case Intrinsic::aarch64_neon_ld4:
5535 if (VT == MVT::v8i8) {
5536 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5538 }
else if (VT == MVT::v16i8) {
5539 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5541 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5542 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5544 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5545 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5547 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5548 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5550 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5551 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5553 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5554 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5556 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5557 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5561 case Intrinsic::aarch64_neon_ld2r:
5562 if (VT == MVT::v8i8) {
5563 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5565 }
else if (VT == MVT::v16i8) {
5566 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5568 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5569 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5571 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5572 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5574 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5575 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5577 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5578 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5580 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5581 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5583 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5584 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5588 case Intrinsic::aarch64_neon_ld3r:
5589 if (VT == MVT::v8i8) {
5590 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5592 }
else if (VT == MVT::v16i8) {
5593 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5595 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5596 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5598 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5599 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5601 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5602 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5604 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5605 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5607 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5608 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5610 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5611 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5615 case Intrinsic::aarch64_neon_ld4r:
5616 if (VT == MVT::v8i8) {
5617 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5619 }
else if (VT == MVT::v16i8) {
5620 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5622 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5623 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5625 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5626 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5628 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5629 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5631 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5632 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5634 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5635 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5637 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5638 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5642 case Intrinsic::aarch64_neon_ld2lane:
5643 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5644 SelectLoadLane(Node, 2, AArch64::LD2i8);
5646 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5647 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5648 SelectLoadLane(Node, 2, AArch64::LD2i16);
5650 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5652 SelectLoadLane(Node, 2, AArch64::LD2i32);
5654 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5656 SelectLoadLane(Node, 2, AArch64::LD2i64);
5660 case Intrinsic::aarch64_neon_ld3lane:
5661 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5662 SelectLoadLane(Node, 3, AArch64::LD3i8);
5664 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5665 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5666 SelectLoadLane(Node, 3, AArch64::LD3i16);
5668 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5670 SelectLoadLane(Node, 3, AArch64::LD3i32);
5672 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5674 SelectLoadLane(Node, 3, AArch64::LD3i64);
5678 case Intrinsic::aarch64_neon_ld4lane:
5679 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5680 SelectLoadLane(Node, 4, AArch64::LD4i8);
5682 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5683 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5684 SelectLoadLane(Node, 4, AArch64::LD4i16);
5686 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5688 SelectLoadLane(Node, 4, AArch64::LD4i32);
5690 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5692 SelectLoadLane(Node, 4, AArch64::LD4i64);
5696 case Intrinsic::aarch64_ld64b:
5697 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5699 case Intrinsic::aarch64_sve_ld2q_sret: {
5700 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q,
true);
5703 case Intrinsic::aarch64_sve_ld3q_sret: {
5704 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q,
true);
5707 case Intrinsic::aarch64_sve_ld4q_sret: {
5708 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q,
true);
5711 case Intrinsic::aarch64_sve_ld2_sret: {
5712 if (VT == MVT::nxv16i8) {
5713 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5716 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5717 VT == MVT::nxv8bf16) {
5718 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5721 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5722 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5725 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5726 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5732 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5733 if (VT == MVT::nxv16i8) {
5734 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5735 SelectContiguousMultiVectorLoad(
5736 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5737 else if (Subtarget->hasSVE2p1())
5738 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5743 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5744 VT == MVT::nxv8bf16) {
5745 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5746 SelectContiguousMultiVectorLoad(
5747 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5748 else if (Subtarget->hasSVE2p1())
5749 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5754 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5755 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5756 SelectContiguousMultiVectorLoad(
5757 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5758 else if (Subtarget->hasSVE2p1())
5759 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5764 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5765 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5766 SelectContiguousMultiVectorLoad(
5767 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5768 else if (Subtarget->hasSVE2p1())
5769 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5777 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5778 if (VT == MVT::nxv16i8) {
5779 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5780 SelectContiguousMultiVectorLoad(
5781 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5782 else if (Subtarget->hasSVE2p1())
5783 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5788 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5789 VT == MVT::nxv8bf16) {
5790 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5791 SelectContiguousMultiVectorLoad(
5792 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5793 else if (Subtarget->hasSVE2p1())
5794 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5799 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5800 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5801 SelectContiguousMultiVectorLoad(
5802 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5803 else if (Subtarget->hasSVE2p1())
5804 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5809 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5810 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5811 SelectContiguousMultiVectorLoad(
5812 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5813 else if (Subtarget->hasSVE2p1())
5814 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5822 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5823 if (VT == MVT::nxv16i8) {
5824 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5825 SelectContiguousMultiVectorLoad(Node, 2, 0,
5826 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5827 AArch64::LDNT1B_2Z_PSEUDO);
5828 else if (Subtarget->hasSVE2p1())
5829 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5830 AArch64::LDNT1B_2Z);
5834 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5835 VT == MVT::nxv8bf16) {
5836 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5837 SelectContiguousMultiVectorLoad(Node, 2, 1,
5838 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5839 AArch64::LDNT1H_2Z_PSEUDO);
5840 else if (Subtarget->hasSVE2p1())
5841 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5842 AArch64::LDNT1H_2Z);
5846 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5847 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5848 SelectContiguousMultiVectorLoad(Node, 2, 2,
5849 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5850 AArch64::LDNT1W_2Z_PSEUDO);
5851 else if (Subtarget->hasSVE2p1())
5852 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5853 AArch64::LDNT1W_2Z);
5857 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5858 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5859 SelectContiguousMultiVectorLoad(Node, 2, 3,
5860 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5861 AArch64::LDNT1D_2Z_PSEUDO);
5862 else if (Subtarget->hasSVE2p1())
5863 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5864 AArch64::LDNT1D_2Z);
5871 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5872 if (VT == MVT::nxv16i8) {
5873 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5874 SelectContiguousMultiVectorLoad(Node, 4, 0,
5875 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5876 AArch64::LDNT1B_4Z_PSEUDO);
5877 else if (Subtarget->hasSVE2p1())
5878 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5879 AArch64::LDNT1B_4Z);
5883 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5884 VT == MVT::nxv8bf16) {
5885 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5886 SelectContiguousMultiVectorLoad(Node, 4, 1,
5887 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5888 AArch64::LDNT1H_4Z_PSEUDO);
5889 else if (Subtarget->hasSVE2p1())
5890 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5891 AArch64::LDNT1H_4Z);
5895 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5896 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5897 SelectContiguousMultiVectorLoad(Node, 4, 2,
5898 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5899 AArch64::LDNT1W_4Z_PSEUDO);
5900 else if (Subtarget->hasSVE2p1())
5901 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5902 AArch64::LDNT1W_4Z);
5906 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5907 if (Subtarget->hasSME2() && Subtarget->
isStreaming())
5908 SelectContiguousMultiVectorLoad(Node, 4, 3,
5909 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5910 AArch64::LDNT1D_4Z_PSEUDO);
5911 else if (Subtarget->hasSVE2p1())
5912 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5913 AArch64::LDNT1D_4Z);
5920 case Intrinsic::aarch64_sve_ld3_sret: {
5921 if (VT == MVT::nxv16i8) {
5922 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5925 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5926 VT == MVT::nxv8bf16) {
5927 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5930 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5931 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5934 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5935 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5941 case Intrinsic::aarch64_sve_ld4_sret: {
5942 if (VT == MVT::nxv16i8) {
5943 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5946 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5947 VT == MVT::nxv8bf16) {
5948 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5951 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5952 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5955 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5956 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5962 case Intrinsic::aarch64_sme_read_hor_vg2: {
5963 if (VT == MVT::nxv16i8) {
5964 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5965 AArch64::MOVA_2ZMXI_H_B);
5967 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5968 VT == MVT::nxv8bf16) {
5969 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5970 AArch64::MOVA_2ZMXI_H_H);
5972 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5973 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5974 AArch64::MOVA_2ZMXI_H_S);
5976 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5977 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5978 AArch64::MOVA_2ZMXI_H_D);
5983 case Intrinsic::aarch64_sme_read_ver_vg2: {
5984 if (VT == MVT::nxv16i8) {
5985 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5986 AArch64::MOVA_2ZMXI_V_B);
5988 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5989 VT == MVT::nxv8bf16) {
5990 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5991 AArch64::MOVA_2ZMXI_V_H);
5993 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5994 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5995 AArch64::MOVA_2ZMXI_V_S);
5997 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5998 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5999 AArch64::MOVA_2ZMXI_V_D);
6004 case Intrinsic::aarch64_sme_read_hor_vg4: {
6005 if (VT == MVT::nxv16i8) {
6006 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
6007 AArch64::MOVA_4ZMXI_H_B);
6009 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6010 VT == MVT::nxv8bf16) {
6011 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
6012 AArch64::MOVA_4ZMXI_H_H);
6014 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6015 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
6016 AArch64::MOVA_4ZMXI_H_S);
6018 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6019 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
6020 AArch64::MOVA_4ZMXI_H_D);
6025 case Intrinsic::aarch64_sme_read_ver_vg4: {
6026 if (VT == MVT::nxv16i8) {
6027 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
6028 AArch64::MOVA_4ZMXI_V_B);
6030 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6031 VT == MVT::nxv8bf16) {
6032 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
6033 AArch64::MOVA_4ZMXI_V_H);
6035 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6036 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
6037 AArch64::MOVA_4ZMXI_V_S);
6039 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6040 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
6041 AArch64::MOVA_4ZMXI_V_D);
6046 case Intrinsic::aarch64_sme_read_vg1x2: {
6047 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
6048 AArch64::MOVA_VG2_2ZMXI);
6051 case Intrinsic::aarch64_sme_read_vg1x4: {
6052 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
6053 AArch64::MOVA_VG4_4ZMXI);
6056 case Intrinsic::aarch64_sme_readz_horiz_x2: {
6057 if (VT == MVT::nxv16i8) {
6058 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
6060 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6061 VT == MVT::nxv8bf16) {
6062 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
6064 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6065 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
6067 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6068 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
6073 case Intrinsic::aarch64_sme_readz_vert_x2: {
6074 if (VT == MVT::nxv16i8) {
6075 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
6077 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6078 VT == MVT::nxv8bf16) {
6079 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
6081 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6082 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
6084 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6085 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
6090 case Intrinsic::aarch64_sme_readz_horiz_x4: {
6091 if (VT == MVT::nxv16i8) {
6092 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
6094 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6095 VT == MVT::nxv8bf16) {
6096 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6098 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6099 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6101 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6102 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6107 case Intrinsic::aarch64_sme_readz_vert_x4: {
6108 if (VT == MVT::nxv16i8) {
6109 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6111 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6112 VT == MVT::nxv8bf16) {
6113 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6115 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6116 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6118 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6119 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6124 case Intrinsic::aarch64_sme_readz_x2: {
6125 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6129 case Intrinsic::aarch64_sme_readz_x4: {
6130 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6134 case Intrinsic::swift_async_context_addr: {
6136 SDValue Chain =
Node->getOperand(0);
6137 SDValue CopyFP = CurDAG->getCopyFromReg(Chain,
DL, AArch64::FP, MVT::i64);
6138 SDValue Res = SDValue(
6139 CurDAG->getMachineNode(AArch64::SUBXri,
DL, MVT::i64, CopyFP,
6140 CurDAG->getTargetConstant(8,
DL, MVT::i32),
6141 CurDAG->getTargetConstant(0,
DL, MVT::i32)),
6143 ReplaceUses(SDValue(Node, 0), Res);
6144 ReplaceUses(SDValue(Node, 1), CopyFP.
getValue(1));
6145 CurDAG->RemoveDeadNode(Node);
6147 auto &MF = CurDAG->getMachineFunction();
6148 MF.getFrameInfo().setFrameAddressIsTaken(
true);
6149 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
6152 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6154 Node->getValueType(0),
6155 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6156 AArch64::LUTI2_4ZTZI_S}))
6158 SelectMultiVectorLutiLane(Node, 4,
Opc, 3);
6161 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6163 Node->getValueType(0),
6164 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6166 SelectMultiVectorLutiLane(Node, 4,
Opc, 1);
6169 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6171 Node->getValueType(0),
6172 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6173 AArch64::LUTI2_2ZTZI_S}))
6175 SelectMultiVectorLutiLane(Node, 2,
Opc, 7);
6178 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6180 Node->getValueType(0),
6181 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6182 AArch64::LUTI4_2ZTZI_S}))
6184 SelectMultiVectorLutiLane(Node, 2,
Opc, 3);
6187 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6188 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6191 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6192 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6195 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6197 Node->getValueType(0),
6198 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6199 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6201 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6203 Node->getValueType(0),
6204 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6205 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6207 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6209 Node->getValueType(0),
6210 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6211 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6213 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6215 Node->getValueType(0),
6216 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6217 SelectCVTIntrinsicFP8(Node, 2,
Opc);
6219 case Intrinsic::ptrauth_resign_load_relative:
6220 SelectPtrauthResign(Node);
6225 unsigned IntNo =
Node->getConstantOperandVal(0);
6229 case Intrinsic::aarch64_tagp:
6233 case Intrinsic::ptrauth_auth:
6234 SelectPtrauthAuth(Node);
6237 case Intrinsic::ptrauth_resign:
6238 SelectPtrauthResign(Node);
6241 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6242 SelectPtrauthResignWithPC(Node);
6245 case Intrinsic::aarch64_neon_tbl2:
6246 SelectTable(Node, 2,
6247 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6250 case Intrinsic::aarch64_neon_tbl3:
6251 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6252 : AArch64::TBLv16i8Three,
6255 case Intrinsic::aarch64_neon_tbl4:
6256 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6257 : AArch64::TBLv16i8Four,
6260 case Intrinsic::aarch64_neon_tbx2:
6261 SelectTable(Node, 2,
6262 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6265 case Intrinsic::aarch64_neon_tbx3:
6266 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6267 : AArch64::TBXv16i8Three,
6270 case Intrinsic::aarch64_neon_tbx4:
6271 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6272 : AArch64::TBXv16i8Four,
6275 case Intrinsic::aarch64_sve_srshl_single_x2:
6277 Node->getValueType(0),
6278 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6279 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6280 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6282 case Intrinsic::aarch64_sve_srshl_single_x4:
6284 Node->getValueType(0),
6285 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6286 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6287 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6289 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6290 SelectMultiVectorLuti6LaneX4(Node, 2);
6292 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6293 SelectMultiVectorLuti6LaneX4(Node, 3);
6295 case Intrinsic::aarch64_sve_urshl_single_x2:
6297 Node->getValueType(0),
6298 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6299 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6300 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6302 case Intrinsic::aarch64_sve_urshl_single_x4:
6304 Node->getValueType(0),
6305 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6306 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6307 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6309 case Intrinsic::aarch64_sve_srshl_x2:
6311 Node->getValueType(0),
6312 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6313 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6314 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6316 case Intrinsic::aarch64_sve_srshl_x4:
6318 Node->getValueType(0),
6319 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6320 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6321 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6323 case Intrinsic::aarch64_sve_urshl_x2:
6325 Node->getValueType(0),
6326 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6327 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6328 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6330 case Intrinsic::aarch64_sve_urshl_x4:
6332 Node->getValueType(0),
6333 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6334 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6335 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6337 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6339 Node->getValueType(0),
6340 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6341 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6342 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6344 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6346 Node->getValueType(0),
6347 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6348 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6349 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6351 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6353 Node->getValueType(0),
6354 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6355 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6356 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6358 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6360 Node->getValueType(0),
6361 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6362 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6363 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6365 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6367 Node->getValueType(0),
6368 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6369 AArch64::FSCALE_2ZZ_D}))
6370 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6372 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6374 Node->getValueType(0),
6375 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6376 AArch64::FSCALE_4ZZ_D}))
6377 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6379 case Intrinsic::aarch64_sme_fp8_scale_x2:
6381 Node->getValueType(0),
6382 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6383 AArch64::FSCALE_2Z2Z_D}))
6384 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6386 case Intrinsic::aarch64_sme_fp8_scale_x4:
6388 Node->getValueType(0),
6389 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6390 AArch64::FSCALE_4Z4Z_D}))
6391 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6393 case Intrinsic::aarch64_sve_whilege_x2:
6395 Node->getValueType(0),
6396 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6397 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6398 SelectWhilePair(Node,
Op);
6400 case Intrinsic::aarch64_sve_whilegt_x2:
6402 Node->getValueType(0),
6403 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6404 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6405 SelectWhilePair(Node,
Op);
6407 case Intrinsic::aarch64_sve_whilehi_x2:
6409 Node->getValueType(0),
6410 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6411 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6412 SelectWhilePair(Node,
Op);
6414 case Intrinsic::aarch64_sve_whilehs_x2:
6416 Node->getValueType(0),
6417 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6418 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6419 SelectWhilePair(Node,
Op);
6421 case Intrinsic::aarch64_sve_whilele_x2:
6423 Node->getValueType(0),
6424 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6425 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6426 SelectWhilePair(Node,
Op);
6428 case Intrinsic::aarch64_sve_whilelo_x2:
6430 Node->getValueType(0),
6431 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6432 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6433 SelectWhilePair(Node,
Op);
6435 case Intrinsic::aarch64_sve_whilels_x2:
6437 Node->getValueType(0),
6438 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6439 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6440 SelectWhilePair(Node,
Op);
6442 case Intrinsic::aarch64_sve_whilelt_x2:
6444 Node->getValueType(0),
6445 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6446 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6447 SelectWhilePair(Node,
Op);
6449 case Intrinsic::aarch64_sve_smax_single_x2:
6451 Node->getValueType(0),
6452 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6453 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6454 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6456 case Intrinsic::aarch64_sve_umax_single_x2:
6458 Node->getValueType(0),
6459 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6460 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6461 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6463 case Intrinsic::aarch64_sve_fmax_single_x2:
6465 Node->getValueType(0),
6466 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6467 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6468 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6470 case Intrinsic::aarch64_sve_smax_single_x4:
6472 Node->getValueType(0),
6473 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6474 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6475 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6477 case Intrinsic::aarch64_sve_umax_single_x4:
6479 Node->getValueType(0),
6480 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6481 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6482 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6484 case Intrinsic::aarch64_sve_fmax_single_x4:
6486 Node->getValueType(0),
6487 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6488 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6489 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6491 case Intrinsic::aarch64_sve_smin_single_x2:
6493 Node->getValueType(0),
6494 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6495 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6496 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6498 case Intrinsic::aarch64_sve_umin_single_x2:
6500 Node->getValueType(0),
6501 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6502 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6503 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6505 case Intrinsic::aarch64_sve_fmin_single_x2:
6507 Node->getValueType(0),
6508 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6509 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6510 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6512 case Intrinsic::aarch64_sve_smin_single_x4:
6514 Node->getValueType(0),
6515 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6516 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6517 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6519 case Intrinsic::aarch64_sve_umin_single_x4:
6521 Node->getValueType(0),
6522 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6523 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6524 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6526 case Intrinsic::aarch64_sve_fmin_single_x4:
6528 Node->getValueType(0),
6529 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6530 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6531 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6533 case Intrinsic::aarch64_sve_smax_x2:
6535 Node->getValueType(0),
6536 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6537 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6538 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6540 case Intrinsic::aarch64_sve_umax_x2:
6542 Node->getValueType(0),
6543 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6544 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6545 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6547 case Intrinsic::aarch64_sve_fmax_x2:
6549 Node->getValueType(0),
6550 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6551 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6552 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6554 case Intrinsic::aarch64_sve_smax_x4:
6556 Node->getValueType(0),
6557 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6558 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6559 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6561 case Intrinsic::aarch64_sve_umax_x4:
6563 Node->getValueType(0),
6564 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6565 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6566 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6568 case Intrinsic::aarch64_sve_fmax_x4:
6570 Node->getValueType(0),
6571 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6572 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6573 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6575 case Intrinsic::aarch64_sme_famax_x2:
6577 Node->getValueType(0),
6578 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6579 AArch64::FAMAX_2Z2Z_D}))
6580 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6582 case Intrinsic::aarch64_sme_famax_x4:
6584 Node->getValueType(0),
6585 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6586 AArch64::FAMAX_4Z4Z_D}))
6587 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6589 case Intrinsic::aarch64_sme_famin_x2:
6591 Node->getValueType(0),
6592 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6593 AArch64::FAMIN_2Z2Z_D}))
6594 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6596 case Intrinsic::aarch64_sme_famin_x4:
6598 Node->getValueType(0),
6599 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6600 AArch64::FAMIN_4Z4Z_D}))
6601 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6603 case Intrinsic::aarch64_sve_smin_x2:
6605 Node->getValueType(0),
6606 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6607 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6608 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6610 case Intrinsic::aarch64_sve_umin_x2:
6612 Node->getValueType(0),
6613 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6614 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6615 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6617 case Intrinsic::aarch64_sve_fmin_x2:
6619 Node->getValueType(0),
6620 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6621 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6622 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6624 case Intrinsic::aarch64_sve_smin_x4:
6626 Node->getValueType(0),
6627 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6628 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6629 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6631 case Intrinsic::aarch64_sve_umin_x4:
6633 Node->getValueType(0),
6634 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6635 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6636 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6638 case Intrinsic::aarch64_sve_fmin_x4:
6640 Node->getValueType(0),
6641 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6642 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6643 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6645 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6647 Node->getValueType(0),
6648 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6649 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6650 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6652 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6654 Node->getValueType(0),
6655 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6656 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6657 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6659 case Intrinsic::aarch64_sve_fminnm_single_x2:
6661 Node->getValueType(0),
6662 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6663 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6664 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6666 case Intrinsic::aarch64_sve_fminnm_single_x4:
6668 Node->getValueType(0),
6669 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6670 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6671 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6673 case Intrinsic::aarch64_sve_fscale_single_x4:
6674 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::BFSCALE_4ZZ);
6676 case Intrinsic::aarch64_sve_fscale_single_x2:
6677 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::BFSCALE_2ZZ);
6679 case Intrinsic::aarch64_sve_fmul_single_x4:
6681 Node->getValueType(0),
6682 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6683 AArch64::FMUL_4ZZ_D}))
6684 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6686 case Intrinsic::aarch64_sve_fmul_single_x2:
6688 Node->getValueType(0),
6689 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6690 AArch64::FMUL_2ZZ_D}))
6691 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6693 case Intrinsic::aarch64_sve_fmaxnm_x2:
6695 Node->getValueType(0),
6696 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6697 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6698 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6700 case Intrinsic::aarch64_sve_fmaxnm_x4:
6702 Node->getValueType(0),
6703 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6704 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6705 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6707 case Intrinsic::aarch64_sve_fminnm_x2:
6709 Node->getValueType(0),
6710 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6711 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6712 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6714 case Intrinsic::aarch64_sve_fminnm_x4:
6716 Node->getValueType(0),
6717 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6718 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6719 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6721 case Intrinsic::aarch64_sve_aese_lane_x2:
6722 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESE_2ZZI_B);
6724 case Intrinsic::aarch64_sve_aesd_lane_x2:
6725 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESD_2ZZI_B);
6727 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6728 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESEMC_2ZZI_B);
6730 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6731 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::AESDIMC_2ZZI_B);
6733 case Intrinsic::aarch64_sve_aese_lane_x4:
6734 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESE_4ZZI_B);
6736 case Intrinsic::aarch64_sve_aesd_lane_x4:
6737 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESD_4ZZI_B);
6739 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6740 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESEMC_4ZZI_B);
6742 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6743 SelectDestructiveMultiIntrinsic(Node, 4,
false, AArch64::AESDIMC_4ZZI_B);
6745 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6746 SelectDestructiveMultiIntrinsic(Node, 2,
false, AArch64::PMLAL_2ZZZ_Q);
6748 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6752 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q,
DL, MVT::Untyped, Regs);
6753 SDValue SuperReg = SDValue(Res, 0);
6754 for (
unsigned I = 0;
I < 2;
I++)
6755 ReplaceUses(SDValue(Node,
I),
6756 CurDAG->getTargetExtractSubreg(AArch64::zsub0 +
I,
DL, VT,
6758 CurDAG->RemoveDeadNode(Node);
6761 case Intrinsic::aarch64_sve_fscale_x4:
6762 SelectDestructiveMultiIntrinsic(Node, 4,
true, AArch64::BFSCALE_4Z4Z);
6764 case Intrinsic::aarch64_sve_fscale_x2:
6765 SelectDestructiveMultiIntrinsic(Node, 2,
true, AArch64::BFSCALE_2Z2Z);
6767 case Intrinsic::aarch64_sve_fmul_x4:
6769 Node->getValueType(0),
6770 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6771 AArch64::FMUL_4Z4Z_D}))
6772 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op);
6774 case Intrinsic::aarch64_sve_fmul_x2:
6776 Node->getValueType(0),
6777 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6778 AArch64::FMUL_2Z2Z_D}))
6779 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op);
6781 case Intrinsic::aarch64_sve_fcvtzs_x2:
6782 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6784 case Intrinsic::aarch64_sve_scvtf_x2:
6785 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6787 case Intrinsic::aarch64_sve_fcvtzu_x2:
6788 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6790 case Intrinsic::aarch64_sve_ucvtf_x2:
6791 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6793 case Intrinsic::aarch64_sve_fcvtzs_x4:
6794 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6796 case Intrinsic::aarch64_sve_scvtf_x4:
6797 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6799 case Intrinsic::aarch64_sve_fcvtzu_x4:
6800 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6802 case Intrinsic::aarch64_sve_ucvtf_x4:
6803 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6805 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6806 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVT_2ZZ_H_S);
6808 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6809 SelectUnaryMultiIntrinsic(Node, 2,
false, AArch64::FCVTL_2ZZ_H_S);
6811 case Intrinsic::aarch64_sve_sclamp_single_x2:
6813 Node->getValueType(0),
6814 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6815 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6816 SelectClamp(Node, 2,
Op);
6818 case Intrinsic::aarch64_sve_uclamp_single_x2:
6820 Node->getValueType(0),
6821 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6822 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6823 SelectClamp(Node, 2,
Op);
6825 case Intrinsic::aarch64_sve_fclamp_single_x2:
6827 Node->getValueType(0),
6828 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6829 AArch64::FCLAMP_VG2_2Z2Z_D}))
6830 SelectClamp(Node, 2,
Op);
6832 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6833 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6835 case Intrinsic::aarch64_sve_sclamp_single_x4:
6837 Node->getValueType(0),
6838 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6839 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6840 SelectClamp(Node, 4,
Op);
6842 case Intrinsic::aarch64_sve_uclamp_single_x4:
6844 Node->getValueType(0),
6845 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6846 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6847 SelectClamp(Node, 4,
Op);
6849 case Intrinsic::aarch64_sve_fclamp_single_x4:
6851 Node->getValueType(0),
6852 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6853 AArch64::FCLAMP_VG4_4Z4Z_D}))
6854 SelectClamp(Node, 4,
Op);
6856 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6857 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6859 case Intrinsic::aarch64_sve_add_single_x2:
6861 Node->getValueType(0),
6862 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6863 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6864 SelectDestructiveMultiIntrinsic(Node, 2,
false,
Op);
6866 case Intrinsic::aarch64_sve_add_single_x4:
6868 Node->getValueType(0),
6869 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6870 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6871 SelectDestructiveMultiIntrinsic(Node, 4,
false,
Op);
6873 case Intrinsic::aarch64_sve_zip_x2:
6875 Node->getValueType(0),
6876 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6877 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6878 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6880 case Intrinsic::aarch64_sve_zipq_x2:
6881 SelectUnaryMultiIntrinsic(Node, 2,
false,
6882 AArch64::ZIP_VG2_2ZZZ_Q);
6884 case Intrinsic::aarch64_sve_zip_x4:
6886 Node->getValueType(0),
6887 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6888 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6889 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6891 case Intrinsic::aarch64_sve_zipq_x4:
6892 SelectUnaryMultiIntrinsic(Node, 4,
true,
6893 AArch64::ZIP_VG4_4Z4Z_Q);
6895 case Intrinsic::aarch64_sve_uzp_x2:
6897 Node->getValueType(0),
6898 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6899 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6900 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6902 case Intrinsic::aarch64_sve_uzpq_x2:
6903 SelectUnaryMultiIntrinsic(Node, 2,
false,
6904 AArch64::UZP_VG2_2ZZZ_Q);
6906 case Intrinsic::aarch64_sve_uzp_x4:
6908 Node->getValueType(0),
6909 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6910 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6911 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6913 case Intrinsic::aarch64_sve_uzpq_x4:
6914 SelectUnaryMultiIntrinsic(Node, 4,
true,
6915 AArch64::UZP_VG4_4Z4Z_Q);
6917 case Intrinsic::aarch64_sve_sel_x2:
6919 Node->getValueType(0),
6920 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6921 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6922 SelectDestructiveMultiIntrinsic(Node, 2,
true,
Op,
true);
6924 case Intrinsic::aarch64_sve_sel_x4:
6926 Node->getValueType(0),
6927 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6928 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6929 SelectDestructiveMultiIntrinsic(Node, 4,
true,
Op,
true);
6931 case Intrinsic::aarch64_sve_frinta_x2:
6932 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6934 case Intrinsic::aarch64_sve_frinta_x4:
6935 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6937 case Intrinsic::aarch64_sve_frintm_x2:
6938 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6940 case Intrinsic::aarch64_sve_frintm_x4:
6941 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6943 case Intrinsic::aarch64_sve_frintn_x2:
6944 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6946 case Intrinsic::aarch64_sve_frintn_x4:
6947 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6949 case Intrinsic::aarch64_sve_frintp_x2:
6950 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6952 case Intrinsic::aarch64_sve_frintp_x4:
6953 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6955 case Intrinsic::aarch64_sve_sunpk_x2:
6957 Node->getValueType(0),
6958 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6959 AArch64::SUNPK_VG2_2ZZ_D}))
6960 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6962 case Intrinsic::aarch64_sve_uunpk_x2:
6964 Node->getValueType(0),
6965 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6966 AArch64::UUNPK_VG2_2ZZ_D}))
6967 SelectUnaryMultiIntrinsic(Node, 2,
false,
Op);
6969 case Intrinsic::aarch64_sve_sunpk_x4:
6971 Node->getValueType(0),
6972 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6973 AArch64::SUNPK_VG4_4Z2Z_D}))
6974 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6976 case Intrinsic::aarch64_sve_uunpk_x4:
6978 Node->getValueType(0),
6979 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6980 AArch64::UUNPK_VG4_4Z2Z_D}))
6981 SelectUnaryMultiIntrinsic(Node, 4,
true,
Op);
6983 case Intrinsic::aarch64_sve_pext_x2: {
6985 Node->getValueType(0),
6986 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6987 AArch64::PEXT_2PCI_D}))
6988 SelectPExtPair(Node,
Op);
6995 unsigned IntNo =
Node->getConstantOperandVal(1);
6996 if (
Node->getNumOperands() >= 3)
6997 VT =
Node->getOperand(2)->getValueType(0);
7001 case Intrinsic::aarch64_neon_st1x2: {
7002 if (VT == MVT::v8i8) {
7003 SelectStore(Node, 2, AArch64::ST1Twov8b);
7005 }
else if (VT == MVT::v16i8) {
7006 SelectStore(Node, 2, AArch64::ST1Twov16b);
7008 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7009 VT == MVT::v4bf16) {
7010 SelectStore(Node, 2, AArch64::ST1Twov4h);
7012 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7013 VT == MVT::v8bf16) {
7014 SelectStore(Node, 2, AArch64::ST1Twov8h);
7016 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7017 SelectStore(Node, 2, AArch64::ST1Twov2s);
7019 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7020 SelectStore(Node, 2, AArch64::ST1Twov4s);
7022 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7023 SelectStore(Node, 2, AArch64::ST1Twov2d);
7025 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7026 SelectStore(Node, 2, AArch64::ST1Twov1d);
7031 case Intrinsic::aarch64_neon_st1x3: {
7032 if (VT == MVT::v8i8) {
7033 SelectStore(Node, 3, AArch64::ST1Threev8b);
7035 }
else if (VT == MVT::v16i8) {
7036 SelectStore(Node, 3, AArch64::ST1Threev16b);
7038 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7039 VT == MVT::v4bf16) {
7040 SelectStore(Node, 3, AArch64::ST1Threev4h);
7042 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7043 VT == MVT::v8bf16) {
7044 SelectStore(Node, 3, AArch64::ST1Threev8h);
7046 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7047 SelectStore(Node, 3, AArch64::ST1Threev2s);
7049 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7050 SelectStore(Node, 3, AArch64::ST1Threev4s);
7052 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7053 SelectStore(Node, 3, AArch64::ST1Threev2d);
7055 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7056 SelectStore(Node, 3, AArch64::ST1Threev1d);
7061 case Intrinsic::aarch64_neon_st1x4: {
7062 if (VT == MVT::v8i8) {
7063 SelectStore(Node, 4, AArch64::ST1Fourv8b);
7065 }
else if (VT == MVT::v16i8) {
7066 SelectStore(Node, 4, AArch64::ST1Fourv16b);
7068 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7069 VT == MVT::v4bf16) {
7070 SelectStore(Node, 4, AArch64::ST1Fourv4h);
7072 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7073 VT == MVT::v8bf16) {
7074 SelectStore(Node, 4, AArch64::ST1Fourv8h);
7076 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7077 SelectStore(Node, 4, AArch64::ST1Fourv2s);
7079 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7080 SelectStore(Node, 4, AArch64::ST1Fourv4s);
7082 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7083 SelectStore(Node, 4, AArch64::ST1Fourv2d);
7085 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7086 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7091 case Intrinsic::aarch64_neon_st2: {
7092 if (VT == MVT::v8i8) {
7093 SelectStore(Node, 2, AArch64::ST2Twov8b);
7095 }
else if (VT == MVT::v16i8) {
7096 SelectStore(Node, 2, AArch64::ST2Twov16b);
7098 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7099 VT == MVT::v4bf16) {
7100 SelectStore(Node, 2, AArch64::ST2Twov4h);
7102 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7103 VT == MVT::v8bf16) {
7104 SelectStore(Node, 2, AArch64::ST2Twov8h);
7106 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7107 SelectStore(Node, 2, AArch64::ST2Twov2s);
7109 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7110 SelectStore(Node, 2, AArch64::ST2Twov4s);
7112 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7113 SelectStore(Node, 2, AArch64::ST2Twov2d);
7115 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7116 SelectStore(Node, 2, AArch64::ST1Twov1d);
7121 case Intrinsic::aarch64_neon_st3: {
7122 if (VT == MVT::v8i8) {
7123 SelectStore(Node, 3, AArch64::ST3Threev8b);
7125 }
else if (VT == MVT::v16i8) {
7126 SelectStore(Node, 3, AArch64::ST3Threev16b);
7128 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7129 VT == MVT::v4bf16) {
7130 SelectStore(Node, 3, AArch64::ST3Threev4h);
7132 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7133 VT == MVT::v8bf16) {
7134 SelectStore(Node, 3, AArch64::ST3Threev8h);
7136 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7137 SelectStore(Node, 3, AArch64::ST3Threev2s);
7139 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7140 SelectStore(Node, 3, AArch64::ST3Threev4s);
7142 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7143 SelectStore(Node, 3, AArch64::ST3Threev2d);
7145 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7146 SelectStore(Node, 3, AArch64::ST1Threev1d);
7151 case Intrinsic::aarch64_neon_st4: {
7152 if (VT == MVT::v8i8) {
7153 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7155 }
else if (VT == MVT::v16i8) {
7156 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7158 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7159 VT == MVT::v4bf16) {
7160 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7162 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7163 VT == MVT::v8bf16) {
7164 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7166 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7167 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7169 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7170 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7172 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7173 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7175 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7176 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7181 case Intrinsic::aarch64_neon_st2lane: {
7182 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7183 SelectStoreLane(Node, 2, AArch64::ST2i8);
7185 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7186 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7187 SelectStoreLane(Node, 2, AArch64::ST2i16);
7189 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7191 SelectStoreLane(Node, 2, AArch64::ST2i32);
7193 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7195 SelectStoreLane(Node, 2, AArch64::ST2i64);
7200 case Intrinsic::aarch64_neon_st3lane: {
7201 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7202 SelectStoreLane(Node, 3, AArch64::ST3i8);
7204 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7205 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7206 SelectStoreLane(Node, 3, AArch64::ST3i16);
7208 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7210 SelectStoreLane(Node, 3, AArch64::ST3i32);
7212 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7214 SelectStoreLane(Node, 3, AArch64::ST3i64);
7219 case Intrinsic::aarch64_neon_st4lane: {
7220 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7221 SelectStoreLane(Node, 4, AArch64::ST4i8);
7223 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7224 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7225 SelectStoreLane(Node, 4, AArch64::ST4i16);
7227 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7229 SelectStoreLane(Node, 4, AArch64::ST4i32);
7231 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7233 SelectStoreLane(Node, 4, AArch64::ST4i64);
7238 case Intrinsic::aarch64_sve_st2q: {
7239 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7242 case Intrinsic::aarch64_sve_st3q: {
7243 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7246 case Intrinsic::aarch64_sve_st4q: {
7247 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7250 case Intrinsic::aarch64_sve_st2: {
7251 if (VT == MVT::nxv16i8) {
7252 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7254 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7255 VT == MVT::nxv8bf16) {
7256 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7258 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7259 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7261 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7262 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7267 case Intrinsic::aarch64_sve_st3: {
7268 if (VT == MVT::nxv16i8) {
7269 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7271 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7272 VT == MVT::nxv8bf16) {
7273 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7275 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7276 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7278 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7279 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7284 case Intrinsic::aarch64_sve_st4: {
7285 if (VT == MVT::nxv16i8) {
7286 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7288 }
else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7289 VT == MVT::nxv8bf16) {
7290 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7292 }
else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7293 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7295 }
else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7296 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7304 case AArch64ISD::LD2post: {
7305 if (VT == MVT::v8i8) {
7306 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7308 }
else if (VT == MVT::v16i8) {
7309 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7311 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7312 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7314 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7315 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7317 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7318 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7320 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7321 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7323 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7324 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7326 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7327 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7332 case AArch64ISD::LD3post: {
7333 if (VT == MVT::v8i8) {
7334 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7336 }
else if (VT == MVT::v16i8) {
7337 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7339 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7340 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7342 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7343 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7345 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7346 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7348 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7349 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7351 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7352 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7354 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7355 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7360 case AArch64ISD::LD4post: {
7361 if (VT == MVT::v8i8) {
7362 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7364 }
else if (VT == MVT::v16i8) {
7365 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7367 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7368 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7370 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7371 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7373 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7374 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7376 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7377 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7379 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7380 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7382 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7383 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7388 case AArch64ISD::LD1x2post: {
7389 if (VT == MVT::v8i8) {
7390 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7392 }
else if (VT == MVT::v16i8) {
7393 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7395 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7396 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7398 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7399 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7401 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7402 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7404 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7405 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7407 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7408 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7410 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7411 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7416 case AArch64ISD::LD1x3post: {
7417 if (VT == MVT::v8i8) {
7418 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7420 }
else if (VT == MVT::v16i8) {
7421 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7423 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7424 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7426 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7427 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7429 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7430 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7432 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7433 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7435 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7436 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7438 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7439 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7444 case AArch64ISD::LD1x4post: {
7445 if (VT == MVT::v8i8) {
7446 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7448 }
else if (VT == MVT::v16i8) {
7449 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7451 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7452 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7454 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7455 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7457 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7458 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7460 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7461 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7463 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7464 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7466 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7467 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7472 case AArch64ISD::LD1DUPpost: {
7473 if (VT == MVT::v8i8) {
7474 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7476 }
else if (VT == MVT::v16i8) {
7477 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7479 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7480 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7482 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7483 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7485 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7486 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7488 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7489 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7491 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7492 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7494 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7495 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7500 case AArch64ISD::LD2DUPpost: {
7501 if (VT == MVT::v8i8) {
7502 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7504 }
else if (VT == MVT::v16i8) {
7505 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7507 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7508 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7510 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7511 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7513 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7514 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7516 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7517 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7519 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7520 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7522 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7523 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7528 case AArch64ISD::LD3DUPpost: {
7529 if (VT == MVT::v8i8) {
7530 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7532 }
else if (VT == MVT::v16i8) {
7533 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7535 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7536 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7538 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7539 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7541 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7542 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7544 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7545 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7547 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7548 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7550 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7551 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7556 case AArch64ISD::LD4DUPpost: {
7557 if (VT == MVT::v8i8) {
7558 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7560 }
else if (VT == MVT::v16i8) {
7561 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7563 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7564 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7566 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7567 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7569 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7570 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7572 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7573 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7575 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7576 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7578 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7579 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7584 case AArch64ISD::LD1LANEpost: {
7585 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7586 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7588 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7589 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7590 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7592 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7594 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7596 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7598 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7603 case AArch64ISD::LD2LANEpost: {
7604 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7605 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7607 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7608 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7609 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7611 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7613 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7615 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7617 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7622 case AArch64ISD::LD3LANEpost: {
7623 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7624 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7626 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7627 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7628 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7630 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7632 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7634 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7636 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7641 case AArch64ISD::LD4LANEpost: {
7642 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7643 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7645 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7646 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7647 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7649 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7651 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7653 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7655 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7660 case AArch64ISD::ST2post: {
7661 VT =
Node->getOperand(1).getValueType();
7662 if (VT == MVT::v8i8) {
7663 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7665 }
else if (VT == MVT::v16i8) {
7666 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7668 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7669 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7671 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7672 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7674 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7675 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7677 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7678 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7680 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7681 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7683 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7684 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7689 case AArch64ISD::ST3post: {
7690 VT =
Node->getOperand(1).getValueType();
7691 if (VT == MVT::v8i8) {
7692 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7694 }
else if (VT == MVT::v16i8) {
7695 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7697 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7698 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7700 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7701 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7703 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7704 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7706 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7707 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7709 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7710 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7712 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7713 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7718 case AArch64ISD::ST4post: {
7719 VT =
Node->getOperand(1).getValueType();
7720 if (VT == MVT::v8i8) {
7721 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7723 }
else if (VT == MVT::v16i8) {
7724 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7726 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7727 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7729 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7730 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7732 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7733 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7735 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7736 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7738 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7739 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7741 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7742 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7747 case AArch64ISD::ST1x2post: {
7748 VT =
Node->getOperand(1).getValueType();
7749 if (VT == MVT::v8i8) {
7750 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7752 }
else if (VT == MVT::v16i8) {
7753 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7755 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7756 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7758 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7759 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7761 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7762 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7764 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7765 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7767 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7768 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7770 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7771 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7776 case AArch64ISD::ST1x3post: {
7777 VT =
Node->getOperand(1).getValueType();
7778 if (VT == MVT::v8i8) {
7779 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7781 }
else if (VT == MVT::v16i8) {
7782 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7784 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7785 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7787 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7788 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7790 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7791 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7793 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7794 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7796 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7797 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7799 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7800 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7805 case AArch64ISD::ST1x4post: {
7806 VT =
Node->getOperand(1).getValueType();
7807 if (VT == MVT::v8i8) {
7808 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7810 }
else if (VT == MVT::v16i8) {
7811 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7813 }
else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7814 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7816 }
else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7817 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7819 }
else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7820 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7822 }
else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7823 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7825 }
else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7826 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7828 }
else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7829 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7834 case AArch64ISD::ST2LANEpost: {
7835 VT =
Node->getOperand(1).getValueType();
7836 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7837 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7839 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7840 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7841 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7843 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7845 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7847 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7849 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7854 case AArch64ISD::ST3LANEpost: {
7855 VT =
Node->getOperand(1).getValueType();
7856 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7857 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7859 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7860 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7861 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7863 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7865 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7867 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7869 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7874 case AArch64ISD::ST4LANEpost: {
7875 VT =
Node->getOperand(1).getValueType();
7876 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7877 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7879 }
else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7880 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7881 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7883 }
else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7885 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7887 }
else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7889 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7904 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7916 assert(NumVec > 0 && NumVec < 5 &&
"Invalid number of vectors.");
7920 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7921 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7943 return MemIntr->getMemoryVT();
7950 DataVT =
Load->getValueType(0);
7952 DataVT =
Load->getValueType(0);
7954 DataVT =
Store->getValue().getValueType();
7956 DataVT =
Store->getValue().getValueType();
7963 const unsigned Opcode = Root->
getOpcode();
7967 case AArch64ISD::LD1_MERGE_ZERO:
7968 case AArch64ISD::LD1S_MERGE_ZERO:
7969 case AArch64ISD::LDNF1_MERGE_ZERO:
7970 case AArch64ISD::LDNF1S_MERGE_ZERO:
7972 case AArch64ISD::ST1_PRED:
7984 case Intrinsic::aarch64_sme_ldr:
7985 case Intrinsic::aarch64_sme_str:
7986 return MVT::nxv16i8;
7987 case Intrinsic::aarch64_sve_prf:
7992 case Intrinsic::aarch64_sve_ld2_sret:
7993 case Intrinsic::aarch64_sve_ld2q_sret:
7996 case Intrinsic::aarch64_sve_st2q:
7999 case Intrinsic::aarch64_sve_ld3_sret:
8000 case Intrinsic::aarch64_sve_ld3q_sret:
8003 case Intrinsic::aarch64_sve_st3q:
8006 case Intrinsic::aarch64_sve_ld4_sret:
8007 case Intrinsic::aarch64_sve_ld4q_sret:
8010 case Intrinsic::aarch64_sve_st4q:
8013 case Intrinsic::aarch64_sve_ld1_pn_x2:
8014 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
8017 case Intrinsic::aarch64_sve_ld1_pn_x4:
8018 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
8021 case Intrinsic::aarch64_sve_st1_pn_x2:
8022 case Intrinsic::aarch64_sve_stnt1_pn_x2:
8025 case Intrinsic::aarch64_sve_st1_pn_x4:
8026 case Intrinsic::aarch64_sve_stnt1_pn_x4:
8029 case Intrinsic::aarch64_sve_ld1udq:
8030 case Intrinsic::aarch64_sve_st1dq:
8031 return EVT(MVT::nxv1i64);
8032 case Intrinsic::aarch64_sve_ld1uwq:
8033 case Intrinsic::aarch64_sve_st1wq:
8034 return EVT(MVT::nxv1i32);
8041template <
int64_t Min,
int64_t Max>
8042bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue
N,
8046 const DataLayout &
DL = CurDAG->getDataLayout();
8047 const MachineFrameInfo &MFI = MF->getFrameInfo();
8055 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8068 SDValue VScale =
N.getOperand(1);
8069 int64_t MulImm = std::numeric_limits<int64_t>::max();
8073 int64_t ByteOffset =
C->getSExtValue();
8074 const auto KnownVScale =
8077 if (!KnownVScale || ByteOffset % KnownVScale != 0)
8080 MulImm = ByteOffset / KnownVScale;
8087 if ((MulImm % MemWidthBytes) != 0)
8090 int64_t
Offset = MulImm / MemWidthBytes;
8094 Base =
N.getOperand(0);
8103 OffImm = CurDAG->getTargetConstant(
Offset, SDLoc(
N), MVT::i64);
8109bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(SDValue
N,
unsigned Scale,
8116 const SDValue
LHS =
N.getOperand(0);
8117 const SDValue
RHS =
N.getOperand(1);
8128 int64_t ImmOff =
C->getSExtValue();
8129 unsigned Size = 1 << Scale;
8138 Offset = CurDAG->getTargetConstant(ImmOff >> Scale,
DL, MVT::i64);
8140 SDNode *
MI = CurDAG->getMachineNode(AArch64::MOVi64imm,
DL, MVT::i64,
Ops);
8149 const SDValue ShiftRHS =
RHS.getOperand(1);
8151 if (
C->getZExtValue() == Scale) {
8160bool AArch64DAGToDAGISel::SelectAllActivePredicate(SDValue
N) {
8161 const AArch64TargetLowering *TLI =
8162 static_cast<const AArch64TargetLowering *
>(getTargetLowering());
8167bool AArch64DAGToDAGISel::SelectAnyPredicate(SDValue
N) {
8168 return N.getValueType().isScalableVectorOf(MVT::i1);
8171bool AArch64DAGToDAGISel::SelectSMETileSlice(SDValue
N,
unsigned MaxSize,
8174 auto MatchConstantOffset = [&](SDValue CN) -> SDValue {
8176 int64_t ImmOff =
C->getSExtValue();
8177 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8178 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(
N), MVT::i64);
8183 if (SDValue
C = MatchConstantOffset(
N)) {
8190 if (CurDAG->isBaseWithConstantOffset(
N)) {
8191 if (SDValue
C = MatchConstantOffset(
N.getOperand(1))) {
8192 Base =
N.getOperand(0);
8200 Offset = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i64);
8204bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *
P, SDValue
N,
8242 if (CN->getAPIntValue().uge(LowerBound) &&
8243 CN->getAPIntValue().ult(UpperBound)) {
8245 Imm = CurDAG->getTargetConstant(CN->getZExtValue(),
DL,
N.getValueType());
8253template <
bool MatchCBB>
8254bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue
N, SDValue &
Reg,
8260 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8262 Reg =
N.getOperand(0);
8264 SDLoc(
N), MVT::i32);
8272 Reg =
N.getOperand(0);
8292bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *
N) {
8293 EVT VT =
N->getValueType(0);
8299 SDValue TVal =
N->getOperand(0);
8300 SDValue FVal =
N->getOperand(1);
8301 SDValue CCVal =
N->getOperand(2);
8302 SDValue
Cmp =
N->getOperand(3);
8304 if (
Cmp.getOpcode() != AArch64ISD::FCMP)
8311 SDValue CmpLHS =
Cmp.getOperand(0);
8312 SDValue CmpRHS =
Cmp.getOperand(1);
8313 unsigned CondCode = CC->getZExtValue();
8316 auto getOpc = [](EVT VT,
bool isMax) ->
unsigned {
8318 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8319 else if (VT == MVT::f32)
8320 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8321 else if (VT == MVT::f64)
8322 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8330 if (TVal == CmpLHS && FVal == CmpRHS)
8335 if (TVal == CmpLHS && FVal == CmpRHS)
8344 unsigned Opc = getOpc(VT, isMax);
8350 if (!CFP || CFP->getValueAPF().isNaN())
8355 if (CFP->isZero() && !
N->getFlags().hasNoSignedZeros())
8361 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8364 CurDAG->SelectNodeTo(
N,
Opc, VT, CmpLHS, CmpRHS);
8368void AArch64DAGToDAGISel::PreprocessISelDAG() {
8369 bool MadeChange =
false;
8375 switch (
N.getOpcode()) {
8377 EVT ScalarTy =
N.getValueType(0).getVectorElementType();
8378 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8379 ScalarTy ==
N.getOperand(0).getValueType())
8384 case AArch64ISD::VSHL: {
8387 EVT VT =
N.getValueType(0);
8388 SDValue
A,
B,
C =
N.getOperand(1);
8394 if (
B.getOpcode() ==
A.getOpcode())
8397 SDValue
SHL = CurDAG->getNode(AArch64ISD::VSHL,
DL, VT,
A,
C);
8407 LLVM_DEBUG(
dbgs() <<
"AArch64 DAG preprocessing replacing:\nOld: ");
8413 CurDAG->ReplaceAllUsesOfValueWith(SDValue(&
N, 0), Result);
8419 CurDAG->RemoveDeadNodes();
static std::optional< APInt > GetNEONSplatValue(SDValue N, const AArch64Subtarget *Subtarget)
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static SDValue addBitcastHints(SelectionDAG &DAG, SDNode &N)
addBitcastHints - This method adds bitcast hints to the operands of a node to help instruction select...
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static bool checkCVTFixedPointOperandWithFBitsForVectors(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static SDValue getZeroRegister(SelectionDAG &DAG, SDLoc DL, EVT VT)
Returns a copy from WZR or XZR.
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static APInt DecodeFMOVImm(uint64_t Imm, unsigned RegWidth)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static std::optional< APInt > DecodeNEONSplat(SDValue N, const AArch64Subtarget *Subtarget)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec)
Builds an integer vector type large enough to hold NumVec instances of VecVT.
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Contains matchers for matching SelectionDAG nodes and values.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64InstrInfo * getInstrInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
bool isLittleEndian() const
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N) const
Register matchRegisterName(StringRef RegName) const
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static const fltSemantics & IEEEhalf()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
void flipAllBits()
Toggle every bit to its opposite value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
unsigned getID() const
getID() - Return the register class ID number.
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
bool equalsStr(StringRef Str) const
uint64_t getScalarSizeInBits() const
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static MVT getVectorVT(MVT VT, unsigned NumElements)
bool hasScalableStackID(int ObjectIdx) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
A description of a memory reference used in the backend.
const MDNode * getMemCacheHint() const
Return the cache hint metadata for the memory reference.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
LLVM Value Representation.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t parseGenericRegister(StringRef Name)
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t decodeAdvSIMDModImmType12(uint8_t Imm)
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static uint64_t decodeAdvSIMDModImmType11(uint8_t Imm)
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static uint64_t decodeAdvSIMDModImmType10(uint8_t Imm)
static bool isSVELogicalImm(unsigned SizeInBits, uint64_t ImmVal, uint64_t &Encoding)
constexpr unsigned getArithImmedShift(const uint64_t C)
getArithImmedShift - assumes C is a legal immediate for arithmetic instructions and
static bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static bool isSignExtendShiftType(AArch64_AM::ShiftExtendType Type)
isSignExtendShiftType - Returns true if Type is sign extending.
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static constexpr unsigned SVEBitsPerBlock
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ POISON
POISON - A poison node.
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_SExt(const Opnd &Op)
bool sd_match(SDValue N, Pattern &&P)
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
NUses_match< 1, Value_match > m_OneUse()
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
AArch64MemoryHint toAArch64MemoryHint(Int I)
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.