32#include "llvm/IR/IntrinsicsARM.h"
42#define DEBUG_TYPE "arm-isel"
43#define PASS_NAME "ARM Instruction Selection"
47 cl::desc(
"Disable isel of shifter-op"),
62 ARMDAGToDAGISel() =
delete;
78 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &dl) {
79 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
88 bool hasNoVMLxHazardUse(
SDNode *
N)
const;
89 bool isShifterOpProfitable(
const SDValue &Shift,
93 bool CheckProfitability =
true);
95 SDValue &
B,
bool CheckProfitability =
true);
99 return SelectRegShifterOperand(
N,
A,
B,
C,
false);
103 return SelectImmShifterOperand(
N,
A,
B,
false);
108 return SelectImmShifterOperand(
N,
A,
B,
false);
119 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
154 template <
unsigned Shift>
159 template <
unsigned Shift>
165 template <
unsigned Shift>
169 template <
unsigned Shift>
175 template<
int Min,
int Max>
178 inline bool is_so_imm(
unsigned Imm)
const {
182 inline bool is_so_imm_not(
unsigned Imm)
const {
186 inline bool is_t2_so_imm(
unsigned Imm)
const {
190 inline bool is_t2_so_imm_not(
unsigned Imm)
const {
195#include "ARMGenDAGISel.inc"
201 bool tryARMIndexedLoad(
SDNode *
N);
202 bool tryT1IndexedLoad(
SDNode *
N);
203 bool tryT2IndexedLoad(
SDNode *
N);
204 bool tryMVEIndexedLoad(
SDNode *
N);
215 void SelectVLD(
SDNode *
N,
bool isUpdating,
unsigned NumVecs,
223 void SelectVST(
SDNode *
N,
bool isUpdating,
unsigned NumVecs,
230 void SelectVLDSTLane(
SDNode *
N,
bool IsLoad,
bool isUpdating,
231 unsigned NumVecs,
const uint16_t *DOpcodes,
235 template <
typename SDValueVector>
236 void AddMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
238 template <
typename SDValueVector>
239 void AddMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
242 template <
typename SDValueVector>
243 void AddEmptyMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc);
244 template <
typename SDValueVector>
245 void AddEmptyMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
EVT InactiveTy);
252 bool HasSaturationOperand);
272 size_t Stride,
size_t TySize);
288 void SelectMVE_VLD(
SDNode *
N,
unsigned NumVecs,
289 const uint16_t *
const *Opcodes,
bool HasWriteback);
308 void SelectVLDDup(
SDNode *
N,
bool IsIntrinsic,
bool isUpdating,
309 unsigned NumVecs,
const uint16_t *DOpcodes,
310 const uint16_t *QOpcodes0 =
nullptr,
311 const uint16_t *QOpcodes1 =
nullptr);
316 bool tryInsertVectorElt(
SDNode *
N);
321 bool tryReadRegister(
SDNode *
N);
322 bool tryWriteRegister(
SDNode *
N);
326 void SelectCMPZ(
SDNode *
N,
bool &SwitchEQNEToPLMI);
328 void SelectCMP_SWAP(
SDNode *
N);
334 std::vector<SDValue> &OutOps)
override;
356 bool canExtractShiftFromMul(
const SDValue &
N,
unsigned MaxShift,
357 unsigned &PowerOfTwo,
SDValue &NewMulConst)
const;
369 ID,
std::make_unique<ARMDAGToDAGISel>(tm, OptLevel)) {}
373char ARMDAGToDAGISelLegacy::ID = 0;
380 if (
N->getOpcode() ==
ISD::Constant &&
N->getValueType(0) == MVT::i32) {
381 Imm =
N->getAsZExtVal();
397 return N->getOpcode() == Opc &&
406 int RangeMin,
int RangeMax,
407 int &ScaledConstant) {
408 assert(Scale > 0 &&
"Invalid scale!");
415 ScaledConstant = (int)
C->getZExtValue();
416 if ((ScaledConstant % Scale) != 0)
419 ScaledConstant /= Scale;
420 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
423void ARMDAGToDAGISel::PreprocessISelDAG() {
424 if (!Subtarget->hasV6T2Ops())
427 bool isThumb2 = Subtarget->isThumb();
444 unsigned And_imm = 0;
454 if (TZ != 1 && TZ != 2)
466 if (And_imm & (And_imm + 1))
471 unsigned Srl_imm = 0;
482 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
485 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
486 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
493 CurDAG->getConstant(Srl_imm + TZ,
SDLoc(Srl),
497 CurDAG->getConstant(And_imm,
SDLoc(Srl), MVT::i32));
499 N1, CurDAG->getConstant(TZ,
SDLoc(Srl), MVT::i32));
500 CurDAG->UpdateNodeOperands(&
N, N0, N1);
507bool ARMDAGToDAGISel::hasNoVMLxHazardUse(
SDNode *
N)
const {
508 if (OptLevel == CodeGenOptLevel::None)
511 if (!Subtarget->hasVMLxHazards())
520 if (
Use->isMachineOpcode()) {
522 CurDAG->getSubtarget().getInstrInfo());
528 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
543 return TII->isFpMLxInstruction(Opcode);
549bool ARMDAGToDAGISel::isShifterOpProfitable(
const SDValue &Shift,
558 (ShAmt == 2 || (Subtarget->
isSwift() && ShAmt == 1));
561bool ARMDAGToDAGISel::canExtractShiftFromMul(
const SDValue &
N,
563 unsigned &PowerOfTwo,
570 if (!
N.hasOneUse())
return false;
573 if (!MulConst)
return false;
576 if (!MulConst->
hasOneUse())
return false;
578 if (MulConstVal == 0)
return false;
581 PowerOfTwo = MaxShift;
582 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
584 if (PowerOfTwo == 0)
return false;
588 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
589 NewMulConst = CurDAG->getConstant(NewMulConstVal,
SDLoc(
N), MVT::i32);
592 return NewCost < OldCost;
596 CurDAG->RepositionNode(
N.getNode()->getIterator(),
M.getNode());
600bool ARMDAGToDAGISel::SelectImmShifterOperand(
SDValue N,
603 bool CheckProfitability) {
610 unsigned PowerOfTwo = 0;
612 if (canExtractShiftFromMul(
N, 31, PowerOfTwo, NewMulConst)) {
615 replaceDAGValue(
N.getOperand(1), NewMulConst);
617 Opc = CurDAG->getTargetConstant(
629 BaseReg =
N.getOperand(0);
630 unsigned ShImmVal = 0;
632 if (!RHS)
return false;
633 ShImmVal =
RHS->getZExtValue() & 31;
639bool ARMDAGToDAGISel::SelectRegShifterOperand(
SDValue N,
643 bool CheckProfitability) {
653 BaseReg =
N.getOperand(0);
654 unsigned ShImmVal = 0;
656 if (RHS)
return false;
658 ShReg =
N.getOperand(1);
659 if (CheckProfitability && !isShifterOpProfitable(
N, ShOpcVal, ShImmVal))
671 return CurDAG->haveNoCommonBitsSet(
N, Parent->
getOperand(1));
675bool ARMDAGToDAGISel::SelectAddrModeImm12(
SDValue N,
682 !CurDAG->isBaseWithConstantOffset(
N)) {
685 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
686 Base = CurDAG->getTargetFrameIndex(
687 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
688 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
696 Base =
N.getOperand(0);
699 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
704 int RHSC = (int)
RHS->getSExtValue();
708 if (RHSC > -0x1000 && RHSC < 0x1000) {
709 Base =
N.getOperand(0);
711 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
712 Base = CurDAG->getTargetFrameIndex(
713 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
715 OffImm = CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
723 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
735 int RHSC = (int)
RHS->getZExtValue();
744 unsigned ShAmt =
Log2_32(RHSC);
757 !CurDAG->isBaseWithConstantOffset(
N))
764 -0x1000+1, 0x1000, RHSC))
774 Base =
N.getOperand(0);
781 dyn_cast<ConstantSDNode>(
N.getOperand(1).getOperand(1))) {
782 ShAmt = Sh->getZExtValue();
783 if (isShifterOpProfitable(
Offset, ShOpcVal, ShAmt))
784 Offset =
N.getOperand(1).getOperand(0);
797 N.getOperand(0).hasOneUse())) {
803 dyn_cast<ConstantSDNode>(
N.getOperand(0).getOperand(1))) {
804 ShAmt = Sh->getZExtValue();
805 if (isShifterOpProfitable(
N.getOperand(0), ShOpcVal, ShAmt)) {
806 Offset =
N.getOperand(0).getOperand(0);
807 Base =
N.getOperand(1);
821 unsigned PowerOfTwo = 0;
823 if (canExtractShiftFromMul(
Offset, 31, PowerOfTwo, NewMulConst)) {
825 replaceDAGValue(
Offset.getOperand(1), NewMulConst);
826 Offset = Handle.getValue();
839 unsigned Opcode =
Op->getOpcode();
841 ? cast<LoadSDNode>(
Op)->getAddressingMode()
842 : cast<StoreSDNode>(
Op)->getAddressingMode();
856 ShAmt = Sh->getZExtValue();
857 if (isShifterOpProfitable(
N, ShOpcVal, ShAmt))
875 unsigned Opcode =
Op->getOpcode();
877 ? cast<LoadSDNode>(
Op)->getAddressingMode()
878 : cast<StoreSDNode>(
Op)->getAddressingMode();
884 Offset = CurDAG->getRegister(0, MVT::i32);
886 CurDAG->getSignedConstant(Val,
SDLoc(
Op), MVT::i32,
true);
896 unsigned Opcode =
Op->getOpcode();
898 ? cast<LoadSDNode>(
Op)->getAddressingMode()
899 : cast<StoreSDNode>(
Op)->getAddressingMode();
904 Offset = CurDAG->getRegister(0, MVT::i32);
919bool ARMDAGToDAGISel::SelectAddrMode3(
SDValue N,
924 Base =
N.getOperand(0);
931 if (!CurDAG->isBaseWithConstantOffset(
N)) {
934 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
935 Base = CurDAG->getTargetFrameIndex(
936 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
938 Offset = CurDAG->getRegister(0, MVT::i32);
947 -256 + 1, 256, RHSC)) {
948 Base =
N.getOperand(0);
950 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
951 Base = CurDAG->getTargetFrameIndex(
952 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
954 Offset = CurDAG->getRegister(0, MVT::i32);
966 Base =
N.getOperand(0);
975 unsigned Opcode =
Op->getOpcode();
977 ? cast<LoadSDNode>(
Op)->getAddressingMode()
978 : cast<StoreSDNode>(
Op)->getAddressingMode();
983 Offset = CurDAG->getRegister(0, MVT::i32);
997 if (!CurDAG->isBaseWithConstantOffset(
N)) {
1000 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1001 Base = CurDAG->getTargetFrameIndex(
1002 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1007 Base =
N.getOperand(0);
1016 const int Scale =
FP16 ? 2 : 4;
1019 Base =
N.getOperand(0);
1021 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1022 Base = CurDAG->getTargetFrameIndex(
1023 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1054bool ARMDAGToDAGISel::SelectAddrMode5(
SDValue N,
1059bool ARMDAGToDAGISel::SelectAddrMode5FP16(
SDValue N,
1068 unsigned Alignment = 0;
1070 MemSDNode *MemN = cast<MemSDNode>(Parent);
1072 if (isa<LSBaseSDNode>(MemN) ||
1080 if (MMOAlign.
value() >= MemSize && MemSize > 1)
1081 Alignment = MemSize;
1089 Align = CurDAG->getTargetConstant(Alignment,
SDLoc(
N), MVT::i32);
1102 Offset = CurDAG->getRegister(0, MVT::i32);
1107bool ARMDAGToDAGISel::SelectAddrModePC(
SDValue N,
1132 if (
auto C = dyn_cast<ConstantSDNode>(
N.getOperand(1)))
1133 return C->getSExtValue() < 0 &&
C->getSExtValue() >= -255;
1140 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N)) {
1148 Base =
N.getOperand(0);
1157 return SelectThumbAddrModeRRSext(
N,
Base,
Offset);
1161ARMDAGToDAGISel::SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
1165 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1169 if (!CurDAG->isBaseWithConstantOffset(
N)) {
1177 Base =
N.getOperand(0);
1182 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1189 Base =
N.getOperand(0);
1191 CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
true);
1202 return SelectThumbAddrModeImm5S(
N, 4,
Base, OffImm);
1208 return SelectThumbAddrModeImm5S(
N, 2,
Base, OffImm);
1214 return SelectThumbAddrModeImm5S(
N, 1,
Base, OffImm);
1217bool ARMDAGToDAGISel::SelectThumbAddrModeSP(
SDValue N,
1220 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1226 Base = CurDAG->getTargetFrameIndex(
1227 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1228 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1232 if (!CurDAG->isBaseWithConstantOffset(
N))
1239 Base =
N.getOperand(0);
1240 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1251 Base = CurDAG->getTargetFrameIndex(
1252 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1253 OffImm = CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
1264template <
unsigned Shift>
1267 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1271 Base =
N.getOperand(0);
1274 OffImm = CurDAG->getSignedConstant(RHSC * (1 << Shift),
SDLoc(
N),
1282 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1292bool ARMDAGToDAGISel::SelectT2AddrModeImm12(
SDValue N,
1298 !CurDAG->isBaseWithConstantOffset(
N)) {
1301 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1302 Base = CurDAG->getTargetFrameIndex(
1303 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1304 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1312 Base =
N.getOperand(0);
1317 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1321 if (
ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(
N.getOperand(1))) {
1322 if (SelectT2AddrModeImm8(
N,
Base, OffImm))
1326 int RHSC = (int)
RHS->getZExtValue();
1330 if (RHSC >= 0 && RHSC < 0x1000) {
1331 Base =
N.getOperand(0);
1333 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1334 Base = CurDAG->getTargetFrameIndex(
1335 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1337 OffImm = CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
1345 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1349template <
unsigned Shift>
1352 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1355 Base =
N.getOperand(0);
1357 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1358 Base = CurDAG->getTargetFrameIndex(
1359 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1365 CurDAG->getSignedConstant(RHSC * (1 << Shift),
SDLoc(
N), MVT::i32,
1373 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1377bool ARMDAGToDAGISel::SelectT2AddrModeImm8(
SDValue N,
1381 !CurDAG->isBaseWithConstantOffset(
N))
1384 if (
ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(
N.getOperand(1))) {
1385 int RHSC = (int)
RHS->getSExtValue();
1389 if ((RHSC >= -255) && (RHSC < 0)) {
1390 Base =
N.getOperand(0);
1392 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1393 Base = CurDAG->getTargetFrameIndex(
1394 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1396 OffImm = CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
1407 unsigned Opcode =
Op->getOpcode();
1409 ? cast<LoadSDNode>(
Op)->getAddressingMode()
1410 : cast<StoreSDNode>(
Op)->getAddressingMode();
1414 ? CurDAG->getSignedConstant(RHSC,
SDLoc(
N), MVT::i32,
1416 : CurDAG->getSignedConstant(-RHSC,
SDLoc(
N), MVT::i32,
1424template <
unsigned Shift>
1427 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1431 Base =
N.getOperand(0);
1433 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1434 Base = CurDAG->getTargetFrameIndex(
1435 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1440 OffImm = CurDAG->getSignedConstant(RHSC * (1 << Shift),
SDLoc(
N),
1448 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1452template <
unsigned Shift>
1455 return SelectT2AddrModeImm7Offset(
Op,
N, OffImm, Shift);
1461 unsigned Opcode =
Op->getOpcode();
1465 AM = cast<LoadSDNode>(
Op)->getAddressingMode();
1468 AM = cast<StoreSDNode>(
Op)->getAddressingMode();
1471 AM = cast<MaskedLoadSDNode>(
Op)->getAddressingMode();
1474 AM = cast<MaskedStoreSDNode>(
Op)->getAddressingMode();
1484 ? CurDAG->getSignedConstant(RHSC * (1 << Shift),
SDLoc(
N),
1486 : CurDAG->getSignedConstant(-RHSC * (1 << Shift),
SDLoc(
N),
1493template <
int Min,
int Max>
1494bool ARMDAGToDAGISel::SelectImmediateInRange(
SDValue N,
SDValue &OffImm) {
1498 CurDAG->getSignedConstant(Val,
SDLoc(
N), MVT::i32,
true);
1504bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(
SDValue N,
1508 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N))
1512 if (
ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(
N.getOperand(1))) {
1513 int RHSC = (int)
RHS->getZExtValue();
1514 if (RHSC >= 0 && RHSC < 0x1000)
1516 else if (RHSC < 0 && RHSC >= -255)
1522 Base =
N.getOperand(0);
1523 OffReg =
N.getOperand(1);
1537 ShAmt = Sh->getZExtValue();
1538 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1549 unsigned PowerOfTwo = 0;
1551 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1553 replaceDAGValue(OffReg.
getOperand(1), NewMulConst);
1559 ShImm = CurDAG->getTargetConstant(ShAmt,
SDLoc(
N), MVT::i32);
1569 OffImm = CurDAG->getTargetConstant(0,
SDLoc(
N), MVT::i32);
1571 if (
N.getOpcode() !=
ISD::ADD || !CurDAG->isBaseWithConstantOffset(
N))
1579 if (RHSC > 1020 || RHSC % 4 != 0)
1582 Base =
N.getOperand(0);
1584 int FI = cast<FrameIndexSDNode>(
Base)->getIndex();
1585 Base = CurDAG->getTargetFrameIndex(
1586 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1589 OffImm = CurDAG->getTargetConstant(RHSC/4,
SDLoc(
N), MVT::i32);
1600void ARMDAGToDAGISel::transferMemOperands(
SDNode *
N,
SDNode *Result) {
1602 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Result), {
MemOp});
1605bool ARMDAGToDAGISel::tryARMIndexedLoad(
SDNode *
N) {
1611 EVT LoadedVT =
LD->getMemoryVT();
1614 unsigned Opcode = 0;
1616 if (LoadedVT == MVT::i32 && isPre &&
1617 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1618 Opcode = ARM::LDR_PRE_IMM;
1620 }
else if (LoadedVT == MVT::i32 && !isPre &&
1621 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1622 Opcode = ARM::LDR_POST_IMM;
1624 }
else if (LoadedVT == MVT::i32 &&
1625 SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1626 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1629 }
else if (LoadedVT == MVT::i16 &&
1630 SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1633 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1634 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
1635 }
else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
1637 if (SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1639 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1643 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1645 Opcode = ARM::LDRB_PRE_IMM;
1646 }
else if (!isPre &&
1647 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1649 Opcode = ARM::LDRB_POST_IMM;
1650 }
else if (SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1652 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1658 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1662 CurDAG->getRegister(0, MVT::i32), Chain };
1663 SDNode *
New = CurDAG->getMachineNode(Opcode,
SDLoc(
N), MVT::i32, MVT::i32,
1665 transferMemOperands(
N, New);
1666 ReplaceNode(
N, New);
1672 CurDAG->getRegister(0, MVT::i32), Chain };
1673 SDNode *
New = CurDAG->getMachineNode(Opcode,
SDLoc(
N), MVT::i32, MVT::i32,
1675 transferMemOperands(
N, New);
1676 ReplaceNode(
N, New);
1684bool ARMDAGToDAGISel::tryT1IndexedLoad(
SDNode *
N) {
1686 EVT LoadedVT =
LD->getMemoryVT();
1692 auto *COffs = dyn_cast<ConstantSDNode>(
LD->getOffset());
1693 if (!COffs || COffs->getZExtValue() != 4)
1703 CurDAG->getRegister(0, MVT::i32), Chain };
1704 SDNode *
New = CurDAG->getMachineNode(ARM::tLDR_postidx,
SDLoc(
N), MVT::i32,
1705 MVT::i32, MVT::Other, Ops);
1706 transferMemOperands(
N, New);
1707 ReplaceNode(
N, New);
1711bool ARMDAGToDAGISel::tryT2IndexedLoad(
SDNode *
N) {
1717 EVT LoadedVT =
LD->getMemoryVT();
1721 unsigned Opcode = 0;
1723 if (SelectT2AddrModeImm8Offset(
N,
LD->getOffset(),
Offset)) {
1726 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1730 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1732 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1737 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1739 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1751 CurDAG->getRegister(0, MVT::i32), Chain };
1752 SDNode *
New = CurDAG->getMachineNode(Opcode,
SDLoc(
N), MVT::i32, MVT::i32,
1754 transferMemOperands(
N, New);
1755 ReplaceNode(
N, New);
1762bool ARMDAGToDAGISel::tryMVEIndexedLoad(
SDNode *
N) {
1764 unsigned Opcode = 0;
1765 bool isSExtLd, isPre;
1775 LoadedVT =
LD->getMemoryVT();
1779 Chain =
LD->getChain();
1782 Alignment =
LD->getAlign();
1786 PredReg = CurDAG->getRegister(0, MVT::i32);
1791 LoadedVT =
LD->getMemoryVT();
1795 Chain =
LD->getChain();
1798 Alignment =
LD->getAlign();
1802 PredReg =
LD->getMask();
1809 bool CanChangeType = Subtarget->
isLittle() && !isa<MaskedLoadSDNode>(
N);
1812 if (Alignment >=
Align(2) && LoadedVT == MVT::v4i16 &&
1813 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1)) {
1815 Opcode = isPre ? ARM::MVE_VLDRHS32_pre : ARM::MVE_VLDRHS32_post;
1817 Opcode = isPre ? ARM::MVE_VLDRHU32_pre : ARM::MVE_VLDRHU32_post;
1818 }
else if (LoadedVT == MVT::v8i8 &&
1819 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1821 Opcode = isPre ? ARM::MVE_VLDRBS16_pre : ARM::MVE_VLDRBS16_post;
1823 Opcode = isPre ? ARM::MVE_VLDRBU16_pre : ARM::MVE_VLDRBU16_post;
1824 }
else if (LoadedVT == MVT::v4i8 &&
1825 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1827 Opcode = isPre ? ARM::MVE_VLDRBS32_pre : ARM::MVE_VLDRBS32_post;
1829 Opcode = isPre ? ARM::MVE_VLDRBU32_pre : ARM::MVE_VLDRBU32_post;
1830 }
else if (Alignment >=
Align(4) &&
1831 (CanChangeType || LoadedVT == MVT::v4i32 ||
1832 LoadedVT == MVT::v4f32) &&
1833 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 2))
1834 Opcode = isPre ? ARM::MVE_VLDRWU32_pre : ARM::MVE_VLDRWU32_post;
1835 else if (Alignment >=
Align(2) &&
1836 (CanChangeType || LoadedVT == MVT::v8i16 ||
1837 LoadedVT == MVT::v8f16) &&
1838 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1))
1839 Opcode = isPre ? ARM::MVE_VLDRHU16_pre : ARM::MVE_VLDRHU16_post;
1840 else if ((CanChangeType || LoadedVT == MVT::v16i8) &&
1841 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0))
1842 Opcode = isPre ? ARM::MVE_VLDRBU8_pre : ARM::MVE_VLDRBU8_post;
1848 CurDAG->getTargetConstant(Pred,
SDLoc(
N), MVT::i32),
1850 CurDAG->getRegister(0, MVT::i32),
1853 N->getValueType(0), MVT::Other, Ops);
1854 transferMemOperands(
N, New);
1858 CurDAG->RemoveDeadNode(
N);
1866 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1867 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1868 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
1869 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1870 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1877 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1878 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1879 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1880 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1881 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1887 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1889 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1890 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1891 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1892 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1898 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1900 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1901 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1902 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1903 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1911 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1912 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1913 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1914 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1915 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
1916 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1917 V2, SubReg2, V3, SubReg3 };
1918 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1925 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1927 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1928 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1929 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1930 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
1931 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1932 V2, SubReg2, V3, SubReg3 };
1933 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1940 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1942 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1943 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1944 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1945 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
1946 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1947 V2, SubReg2, V3, SubReg3 };
1948 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1955 unsigned NumVecs,
bool is64BitVector) {
1956 unsigned NumRegs = NumVecs;
1957 if (!is64BitVector && NumVecs < 3)
1960 unsigned Alignment =
Align->getAsZExtVal();
1961 if (Alignment >= 32 && NumRegs == 4)
1963 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1965 else if (Alignment >= 8)
1970 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
1976 default:
return false;
1977 case ARM::VLD1d8wb_fixed :
return true;
1978 case ARM::VLD1d16wb_fixed :
return true;
1979 case ARM::VLD1d64Qwb_fixed :
return true;
1980 case ARM::VLD1d32wb_fixed :
return true;
1981 case ARM::VLD1d64wb_fixed :
return true;
1982 case ARM::VLD1d8TPseudoWB_fixed :
return true;
1983 case ARM::VLD1d16TPseudoWB_fixed :
return true;
1984 case ARM::VLD1d32TPseudoWB_fixed :
return true;
1985 case ARM::VLD1d64TPseudoWB_fixed :
return true;
1986 case ARM::VLD1d8QPseudoWB_fixed :
return true;
1987 case ARM::VLD1d16QPseudoWB_fixed :
return true;
1988 case ARM::VLD1d32QPseudoWB_fixed :
return true;
1989 case ARM::VLD1d64QPseudoWB_fixed :
return true;
1990 case ARM::VLD1q8wb_fixed :
return true;
1991 case ARM::VLD1q16wb_fixed :
return true;
1992 case ARM::VLD1q32wb_fixed :
return true;
1993 case ARM::VLD1q64wb_fixed :
return true;
1994 case ARM::VLD1DUPd8wb_fixed :
return true;
1995 case ARM::VLD1DUPd16wb_fixed :
return true;
1996 case ARM::VLD1DUPd32wb_fixed :
return true;
1997 case ARM::VLD1DUPq8wb_fixed :
return true;
1998 case ARM::VLD1DUPq16wb_fixed :
return true;
1999 case ARM::VLD1DUPq32wb_fixed :
return true;
2000 case ARM::VLD2d8wb_fixed :
return true;
2001 case ARM::VLD2d16wb_fixed :
return true;
2002 case ARM::VLD2d32wb_fixed :
return true;
2003 case ARM::VLD2q8PseudoWB_fixed :
return true;
2004 case ARM::VLD2q16PseudoWB_fixed :
return true;
2005 case ARM::VLD2q32PseudoWB_fixed :
return true;
2006 case ARM::VLD2DUPd8wb_fixed :
return true;
2007 case ARM::VLD2DUPd16wb_fixed :
return true;
2008 case ARM::VLD2DUPd32wb_fixed :
return true;
2009 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return true;
2010 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return true;
2011 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return true;
2018 default:
return false;
2019 case ARM::VST1d8wb_fixed :
return true;
2020 case ARM::VST1d16wb_fixed :
return true;
2021 case ARM::VST1d32wb_fixed :
return true;
2022 case ARM::VST1d64wb_fixed :
return true;
2023 case ARM::VST1q8wb_fixed :
return true;
2024 case ARM::VST1q16wb_fixed :
return true;
2025 case ARM::VST1q32wb_fixed :
return true;
2026 case ARM::VST1q64wb_fixed :
return true;
2027 case ARM::VST1d8TPseudoWB_fixed :
return true;
2028 case ARM::VST1d16TPseudoWB_fixed :
return true;
2029 case ARM::VST1d32TPseudoWB_fixed :
return true;
2030 case ARM::VST1d64TPseudoWB_fixed :
return true;
2031 case ARM::VST1d8QPseudoWB_fixed :
return true;
2032 case ARM::VST1d16QPseudoWB_fixed :
return true;
2033 case ARM::VST1d32QPseudoWB_fixed :
return true;
2034 case ARM::VST1d64QPseudoWB_fixed :
return true;
2035 case ARM::VST2d8wb_fixed :
return true;
2036 case ARM::VST2d16wb_fixed :
return true;
2037 case ARM::VST2d32wb_fixed :
return true;
2038 case ARM::VST2q8PseudoWB_fixed :
return true;
2039 case ARM::VST2q16PseudoWB_fixed :
return true;
2040 case ARM::VST2q32PseudoWB_fixed :
return true;
2048 &&
"Incorrect fixed stride updating instruction.");
2051 case ARM::VLD1d8wb_fixed:
return ARM::VLD1d8wb_register;
2052 case ARM::VLD1d16wb_fixed:
return ARM::VLD1d16wb_register;
2053 case ARM::VLD1d32wb_fixed:
return ARM::VLD1d32wb_register;
2054 case ARM::VLD1d64wb_fixed:
return ARM::VLD1d64wb_register;
2055 case ARM::VLD1q8wb_fixed:
return ARM::VLD1q8wb_register;
2056 case ARM::VLD1q16wb_fixed:
return ARM::VLD1q16wb_register;
2057 case ARM::VLD1q32wb_fixed:
return ARM::VLD1q32wb_register;
2058 case ARM::VLD1q64wb_fixed:
return ARM::VLD1q64wb_register;
2059 case ARM::VLD1d64Twb_fixed:
return ARM::VLD1d64Twb_register;
2060 case ARM::VLD1d64Qwb_fixed:
return ARM::VLD1d64Qwb_register;
2061 case ARM::VLD1d8TPseudoWB_fixed:
return ARM::VLD1d8TPseudoWB_register;
2062 case ARM::VLD1d16TPseudoWB_fixed:
return ARM::VLD1d16TPseudoWB_register;
2063 case ARM::VLD1d32TPseudoWB_fixed:
return ARM::VLD1d32TPseudoWB_register;
2064 case ARM::VLD1d64TPseudoWB_fixed:
return ARM::VLD1d64TPseudoWB_register;
2065 case ARM::VLD1d8QPseudoWB_fixed:
return ARM::VLD1d8QPseudoWB_register;
2066 case ARM::VLD1d16QPseudoWB_fixed:
return ARM::VLD1d16QPseudoWB_register;
2067 case ARM::VLD1d32QPseudoWB_fixed:
return ARM::VLD1d32QPseudoWB_register;
2068 case ARM::VLD1d64QPseudoWB_fixed:
return ARM::VLD1d64QPseudoWB_register;
2069 case ARM::VLD1DUPd8wb_fixed :
return ARM::VLD1DUPd8wb_register;
2070 case ARM::VLD1DUPd16wb_fixed :
return ARM::VLD1DUPd16wb_register;
2071 case ARM::VLD1DUPd32wb_fixed :
return ARM::VLD1DUPd32wb_register;
2072 case ARM::VLD1DUPq8wb_fixed :
return ARM::VLD1DUPq8wb_register;
2073 case ARM::VLD1DUPq16wb_fixed :
return ARM::VLD1DUPq16wb_register;
2074 case ARM::VLD1DUPq32wb_fixed :
return ARM::VLD1DUPq32wb_register;
2075 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return ARM::VLD2DUPq8OddPseudoWB_register;
2076 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return ARM::VLD2DUPq16OddPseudoWB_register;
2077 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return ARM::VLD2DUPq32OddPseudoWB_register;
2079 case ARM::VST1d8wb_fixed:
return ARM::VST1d8wb_register;
2080 case ARM::VST1d16wb_fixed:
return ARM::VST1d16wb_register;
2081 case ARM::VST1d32wb_fixed:
return ARM::VST1d32wb_register;
2082 case ARM::VST1d64wb_fixed:
return ARM::VST1d64wb_register;
2083 case ARM::VST1q8wb_fixed:
return ARM::VST1q8wb_register;
2084 case ARM::VST1q16wb_fixed:
return ARM::VST1q16wb_register;
2085 case ARM::VST1q32wb_fixed:
return ARM::VST1q32wb_register;
2086 case ARM::VST1q64wb_fixed:
return ARM::VST1q64wb_register;
2087 case ARM::VST1d8TPseudoWB_fixed:
return ARM::VST1d8TPseudoWB_register;
2088 case ARM::VST1d16TPseudoWB_fixed:
return ARM::VST1d16TPseudoWB_register;
2089 case ARM::VST1d32TPseudoWB_fixed:
return ARM::VST1d32TPseudoWB_register;
2090 case ARM::VST1d64TPseudoWB_fixed:
return ARM::VST1d64TPseudoWB_register;
2091 case ARM::VST1d8QPseudoWB_fixed:
return ARM::VST1d8QPseudoWB_register;
2092 case ARM::VST1d16QPseudoWB_fixed:
return ARM::VST1d16QPseudoWB_register;
2093 case ARM::VST1d32QPseudoWB_fixed:
return ARM::VST1d32QPseudoWB_register;
2094 case ARM::VST1d64QPseudoWB_fixed:
return ARM::VST1d64QPseudoWB_register;
2096 case ARM::VLD2d8wb_fixed:
return ARM::VLD2d8wb_register;
2097 case ARM::VLD2d16wb_fixed:
return ARM::VLD2d16wb_register;
2098 case ARM::VLD2d32wb_fixed:
return ARM::VLD2d32wb_register;
2099 case ARM::VLD2q8PseudoWB_fixed:
return ARM::VLD2q8PseudoWB_register;
2100 case ARM::VLD2q16PseudoWB_fixed:
return ARM::VLD2q16PseudoWB_register;
2101 case ARM::VLD2q32PseudoWB_fixed:
return ARM::VLD2q32PseudoWB_register;
2103 case ARM::VST2d8wb_fixed:
return ARM::VST2d8wb_register;
2104 case ARM::VST2d16wb_fixed:
return ARM::VST2d16wb_register;
2105 case ARM::VST2d32wb_fixed:
return ARM::VST2d32wb_register;
2106 case ARM::VST2q8PseudoWB_fixed:
return ARM::VST2q8PseudoWB_register;
2107 case ARM::VST2q16PseudoWB_fixed:
return ARM::VST2q16PseudoWB_register;
2108 case ARM::VST2q32PseudoWB_fixed:
return ARM::VST2q32PseudoWB_register;
2110 case ARM::VLD2DUPd8wb_fixed:
return ARM::VLD2DUPd8wb_register;
2111 case ARM::VLD2DUPd16wb_fixed:
return ARM::VLD2DUPd16wb_register;
2112 case ARM::VLD2DUPd32wb_fixed:
return ARM::VLD2DUPd32wb_register;
2121 auto C = dyn_cast<ConstantSDNode>(Inc);
2125void ARMDAGToDAGISel::SelectVLD(
SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2129 assert(Subtarget->hasNEON());
2130 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLD NumVecs out-of-range");
2134 bool IsIntrinsic = !isUpdating;
2136 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2137 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr,
Align))
2141 EVT VT =
N->getValueType(0);
2143 Align = GetVLDSTAlign(
Align, dl, NumVecs, is64BitVector);
2171 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2176 std::vector<EVT> ResTys;
2177 ResTys.push_back(ResTy);
2179 ResTys.push_back(MVT::i32);
2180 ResTys.push_back(MVT::Other);
2183 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2188 if (is64BitVector || NumVecs <= 2) {
2189 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2194 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2210 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2220 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
2221 const SDValue OpsA[] = { MemAddr,
Align, Reg0, ImplDef, Pred, Reg0, Chain };
2223 ResTy, AddrTy, MVT::Other, OpsA);
2230 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2232 "only constant post-increment update allowed for VLD3/4");
2240 VLd = CurDAG->getMachineNode(QOpcodes1[
OpcodeIndex], dl, ResTys, Ops);
2245 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLd), {
MemOp});
2248 ReplaceNode(
N, VLd);
2254 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2255 ARM::qsub_3 == ARM::qsub_0 + 3,
2256 "Unexpected subreg numbering");
2257 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
2258 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2260 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2264 CurDAG->RemoveDeadNode(
N);
2267void ARMDAGToDAGISel::SelectVST(
SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2271 assert(Subtarget->hasNEON());
2272 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VST NumVecs out-of-range");
2276 bool IsIntrinsic = !isUpdating;
2278 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2279 unsigned Vec0Idx = 3;
2280 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr,
Align))
2286 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2288 Align = GetVLDSTAlign(
Align, dl, NumVecs, is64BitVector);
2312 std::vector<EVT> ResTys;
2314 ResTys.push_back(MVT::i32);
2315 ResTys.push_back(MVT::Other);
2318 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2322 if (is64BitVector || NumVecs <= 2) {
2325 SrcReg =
N->getOperand(Vec0Idx);
2326 }
else if (is64BitVector) {
2328 SDValue V0 =
N->getOperand(Vec0Idx + 0);
2329 SDValue V1 =
N->getOperand(Vec0Idx + 1);
2331 SrcReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2337 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
2338 :
N->getOperand(Vec0Idx + 3);
2339 SrcReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2343 SDValue Q0 =
N->getOperand(Vec0Idx);
2344 SDValue Q1 =
N->getOperand(Vec0Idx + 1);
2345 SrcReg =
SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
2348 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2353 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2371 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2374 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VSt), {
MemOp});
2376 ReplaceNode(
N, VSt);
2384 SDValue V0 =
N->getOperand(Vec0Idx + 0);
2385 SDValue V1 =
N->getOperand(Vec0Idx + 1);
2388 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2389 :
N->getOperand(Vec0Idx + 3);
2390 SDValue RegSeq =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2394 const SDValue OpsA[] = { MemAddr,
Align, Reg0, RegSeq, Pred, Reg0, Chain };
2398 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VStA), {
MemOp});
2405 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2407 "only constant post-increment update allowed for VST3/4");
2417 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VStB), {
MemOp});
2418 ReplaceNode(
N, VStB);
2421void ARMDAGToDAGISel::SelectVLDSTLane(
SDNode *
N,
bool IsLoad,
bool isUpdating,
2425 assert(Subtarget->hasNEON());
2426 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDSTLane NumVecs out-of-range");
2430 bool IsIntrinsic = !isUpdating;
2432 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2433 unsigned Vec0Idx = 3;
2434 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr,
Align))
2440 unsigned Lane =
N->getConstantOperandVal(Vec0Idx + NumVecs);
2441 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2444 unsigned Alignment = 0;
2446 Alignment =
Align->getAsZExtVal();
2448 if (Alignment > NumBytes)
2449 Alignment = NumBytes;
2450 if (Alignment < 8 && Alignment < NumBytes)
2453 Alignment = (Alignment & -Alignment);
2457 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
2477 std::vector<EVT> ResTys;
2479 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2483 MVT::i64, ResTyElts));
2486 ResTys.push_back(MVT::i32);
2487 ResTys.push_back(MVT::Other);
2490 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2496 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2499 Ops.
push_back(IsImmUpdate ? Reg0 : Inc);
2503 SDValue V0 =
N->getOperand(Vec0Idx + 0);
2504 SDValue V1 =
N->getOperand(Vec0Idx + 1);
2507 SuperReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2509 SuperReg =
SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
2513 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2514 :
N->getOperand(Vec0Idx + 3);
2516 SuperReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2518 SuperReg =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2526 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2528 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2529 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLdLn), {
MemOp});
2531 ReplaceNode(
N, VLdLn);
2537 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2538 ARM::qsub_3 == ARM::qsub_0 + 3,
2539 "Unexpected subreg numbering");
2540 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2541 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2543 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2547 CurDAG->RemoveDeadNode(
N);
2550template <
typename SDValueVector>
2551void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
2553 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2554 Ops.push_back(PredicateMask);
2555 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2558template <
typename SDValueVector>
2559void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
2562 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2563 Ops.push_back(PredicateMask);
2564 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2565 Ops.push_back(Inactive);
2568template <
typename SDValueVector>
2569void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc) {
2570 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2571 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2572 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2575template <
typename SDValueVector>
2576void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops,
SDLoc Loc,
2578 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2579 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2580 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2582 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, InactiveTy), 0));
2591 switch (
N->getValueType(1).getVectorElementType().getSizeInBits()) {
2593 Opcode = Opcodes[0];
2596 Opcode = Opcodes[1];
2604 int32_t ImmValue =
N->getConstantOperandVal(3);
2605 Ops.
push_back(getI32Imm(ImmValue, Loc));
2608 AddMVEPredicateToOps(Ops, Loc,
N->getOperand(4));
2610 AddEmptyMVEPredicateToOps(Ops, Loc);
2623 transferMemOperands(
N, New);
2624 CurDAG->RemoveDeadNode(
N);
2629 bool HasSaturationOperand) {
2639 int32_t ImmValue =
N->getConstantOperandVal(3);
2640 Ops.
push_back(getI32Imm(ImmValue, Loc));
2646 if (HasSaturationOperand) {
2647 int32_t SatOp =
N->getConstantOperandVal(4);
2648 int SatBit = (SatOp == 64 ? 0 : 1);
2655 Ops.
push_back(CurDAG->getRegister(0, MVT::i32));
2657 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(Ops));
2660void ARMDAGToDAGISel::SelectMVE_VADCSBC(
SDNode *
N,
uint16_t OpcodeWithCarry,
2671 Ops.
push_back(
N->getOperand(FirstInputOp + 1));
2672 SDValue CarryIn =
N->getOperand(FirstInputOp + 2);
2673 ConstantSDNode *CarryInConstant = dyn_cast<ConstantSDNode>(CarryIn);
2676 if (CarryInConstant &&
2677 (CarryInConstant->
getZExtValue() & CarryMask) == CarryExpected) {
2678 Opcode = OpcodeWithNoCarry;
2681 Opcode = OpcodeWithCarry;
2685 AddMVEPredicateToOps(Ops, Loc,
2686 N->getOperand(FirstInputOp + 3),
2687 N->getOperand(FirstInputOp - 1));
2689 AddEmptyMVEPredicateToOps(Ops, Loc,
N->getValueType(0));
2691 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(Ops));
2702 int32_t ImmValue =
N->getConstantOperandVal(3);
2703 Ops.
push_back(getI32Imm(ImmValue, Loc));
2706 AddMVEPredicateToOps(Ops, Loc,
N->getOperand(4));
2708 AddEmptyMVEPredicateToOps(Ops, Loc);
2710 CurDAG->SelectNodeTo(
N, ARM::MVE_VSHLC,
N->getVTList(),
ArrayRef(Ops));
2714 assert(isa<ConstantSDNode>(SDVal) &&
"expected a compile-time constant");
2724 size_t Stride,
size_t TySize) {
2725 assert(TySize < Stride &&
"Invalid TySize");
2731 "Unsigned versions of vmlsldav[a]/vrmlsldavh[a] do not exist");
2733 "Unsigned versions of vmlaldav[a]x/vrmlaldavh[a]x do not exist");
2736 auto OpIsZero = [
N](
size_t OpNo) {
2742 bool IsAccum = !(OpIsZero(4) && OpIsZero(5));
2744 const uint16_t *Opcodes = IsUnsigned ? OpcodesU : OpcodesS;
2746 Opcodes += 4 * Stride;
2748 Opcodes += 2 * Stride;
2765 AddMVEPredicateToOps(Ops, Loc,
N->getOperand(8));
2767 AddEmptyMVEPredicateToOps(Ops, Loc);
2769 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(Ops));
2775 EVT VecTy =
N->getOperand(6).getValueType();
2788 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 2, SizeIndex);
2795 N->getOperand(6).getValueType().getVectorElementType().getSizeInBits() ==
2797 "bad vector element size");
2798 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 1, 0);
2801void ARMDAGToDAGISel::SelectMVE_VLD(
SDNode *
N,
unsigned NumVecs,
2803 bool HasWriteback) {
2804 EVT VT =
N->getValueType(0);
2810 OurOpcodes = Opcodes[0];
2813 OurOpcodes = Opcodes[1];
2816 OurOpcodes = Opcodes[2];
2824 unsigned PtrOperand = HasWriteback ? 1 : 2;
2827 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, DataTy), 0);
2830 for (
unsigned Stage = 0; Stage < NumVecs - 1; ++Stage) {
2831 SDValue Ops[] = {Data,
N->getOperand(PtrOperand), Chain};
2833 CurDAG->getMachineNode(OurOpcodes[Stage], Loc, ResultTys, Ops);
2840 ResultTys = {DataTy, MVT::i32, MVT::Other};
2841 SDValue Ops[] = {Data,
N->getOperand(PtrOperand), Chain};
2843 CurDAG->getMachineNode(OurOpcodes[NumVecs - 1], Loc, ResultTys, Ops);
2847 for (i = 0; i < NumVecs; i++)
2849 CurDAG->getTargetExtractSubreg(ARM::qsub_0 + i, Loc, VT,
2854 CurDAG->RemoveDeadNode(
N);
2857void ARMDAGToDAGISel::SelectMVE_VxDUP(
SDNode *
N,
const uint16_t *Opcodes,
2859 EVT VT =
N->getValueType(0);
2865 Opcode = Opcodes[0];
2868 Opcode = Opcodes[1];
2871 Opcode = Opcodes[2];
2882 Inactive =
N->getOperand(OpIdx++);
2888 SDValue ImmOp =
N->getOperand(OpIdx++);
2890 Ops.
push_back(getI32Imm(ImmValue, Loc));
2893 AddMVEPredicateToOps(Ops, Loc,
N->getOperand(OpIdx), Inactive);
2895 AddEmptyMVEPredicateToOps(Ops, Loc,
N->getValueType(0));
2897 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(Ops));
2901 size_t NumExtraOps,
bool HasAccum) {
2902 bool IsBigEndian = CurDAG->getDataLayout().isBigEndian();
2909 SDValue ImmCorpoc =
N->getOperand(OpIdx++);
2911 Ops.
push_back(getI32Imm(ImmCoprocVal, Loc));
2916 SDValue AccLo =
N->getOperand(OpIdx++);
2917 SDValue AccHi =
N->getOperand(OpIdx++);
2924 for (
size_t I = 0;
I < NumExtraOps;
I++)
2935 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2941 SDNode *InstrNode = CurDAG->getMachineNode(Opcode, Loc, MVT::Untyped, Ops);
2948 uint16_t SubRegs[2] = {ARM::gsub_0, ARM::gsub_1};
2952 for (
size_t ResIdx = 0; ResIdx < 2; ResIdx++) {
2953 if (
SDValue(
N, ResIdx).use_empty())
2955 SDValue SubReg = CurDAG->getTargetExtractSubreg(SubRegs[ResIdx], Loc,
2956 MVT::i32, ResultPair);
2960 CurDAG->RemoveDeadNode(
N);
2963void ARMDAGToDAGISel::SelectVLDDup(
SDNode *
N,
bool IsIntrinsic,
2964 bool isUpdating,
unsigned NumVecs,
2968 assert(Subtarget->hasNEON());
2969 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLDDup NumVecs out-of-range");
2973 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2974 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr,
Align))
2978 EVT VT =
N->getValueType(0);
2981 unsigned Alignment = 0;
2983 Alignment =
Align->getAsZExtVal();
2985 if (Alignment > NumBytes)
2986 Alignment = NumBytes;
2987 if (Alignment < 8 && Alignment < NumBytes)
2990 Alignment = (Alignment & -Alignment);
2994 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
3016 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
3021 std::vector<EVT> ResTys;
3022 ResTys.push_back(ResTy);
3024 ResTys.push_back(MVT::i32);
3025 ResTys.push_back(MVT::Other);
3028 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3033 unsigned Opc = is64BitVector ? DOpcodes[
OpcodeIndex]
3049 if (is64BitVector || NumVecs == 1) {
3053 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
3054 const SDValue OpsA[] = {MemAddr,
Align, ImplDef, Pred, Reg0, Chain};
3065 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
3069 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLdDup), {
MemOp});
3076 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7,
"Unexpected subreg numbering");
3077 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
3078 for (
unsigned Vec = 0; Vec != NumVecs; ++Vec) {
3080 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
3086 CurDAG->RemoveDeadNode(
N);
3089bool ARMDAGToDAGISel::tryInsertVectorElt(
SDNode *
N) {
3090 if (!Subtarget->hasMVEIntegerOps())
3104 (VT != MVT::v8f16 && VT != MVT::v8i16) || (Ins2.
getValueType() != VT))
3109 if (Lane2 % 2 != 0 || Lane1 != Lane2 + 1)
3136 ExtractLane1 == ExtractLane2 + 1) {
3137 SDValue NewExt = CurDAG->getTargetExtractSubreg(
3138 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val1.
getOperand(0));
3139 SDValue NewIns = CurDAG->getTargetInsertSubreg(
3140 ARM::ssub_0 + Lane2 / 2, dl, VT, Ins2.
getOperand(0),
3142 ReplaceUses(Ins1, NewIns);
3148 if (VT == MVT::v8i16 && Subtarget->hasFullFP16()) {
3149 SDValue Inp1 = CurDAG->getTargetExtractSubreg(
3150 ARM::ssub_0 + ExtractLane1 / 2, dl, MVT::f32, Val1.
getOperand(0));
3151 SDValue Inp2 = CurDAG->getTargetExtractSubreg(
3152 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val2.
getOperand(0));
3153 if (ExtractLane1 % 2 != 0)
3154 Inp1 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp1), 0);
3155 if (ExtractLane2 % 2 != 0)
3156 Inp2 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp2), 0);
3157 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Inp2, Inp1);
3159 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3161 ReplaceUses(Ins1, NewIns);
3168 if (VT == MVT::v8f16 && Subtarget->hasFullFP16()) {
3169 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Val2, Val1);
3171 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3173 ReplaceUses(Ins1, NewIns);
3180bool ARMDAGToDAGISel::transformFixedFloatingPointConversion(
SDNode *
N,
3183 bool FixedToFloat) {
3184 auto Type =
N->getValueType(0);
3186 if (ScalarBits > 32)
3192 if (ScalarBits == 16 && !FMulFlags.
hasNoInfs() && IsUnsigned)
3217 if (!isa<ConstantSDNode>(ImmNode.
getOperand(0)))
3223 APFloat(ScalarBits == 32 ? APFloat::IEEEsingle() : APFloat::IEEEhalf(),
3224 APInt(ScalarBits, Imm));
3241 if (!ImmAPF.getExactInverse(&ToConvert))
3244 APSInt Converted(64,
false);
3248 if (!IsExact || !Converted.isPowerOf2())
3251 unsigned FracBits = Converted.logBase2();
3252 if (FracBits > ScalarBits)
3256 VecVal, CurDAG->getConstant(FracBits,
SDLoc(
N), MVT::i32)};
3257 AddEmptyMVEPredicateToOps(Ops,
SDLoc(
N),
Type);
3259 unsigned int Opcode;
3260 switch (ScalarBits) {
3263 Opcode = IsUnsigned ? ARM::MVE_VCVTf16u16_fix : ARM::MVE_VCVTf16s16_fix;
3265 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3269 Opcode = IsUnsigned ? ARM::MVE_VCVTf32u32_fix : ARM::MVE_VCVTf32s32_fix;
3271 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3278 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
SDLoc(
N),
Type, Ops));
3282bool ARMDAGToDAGISel::tryFP_TO_INT(
SDNode *
N,
SDLoc dl) {
3284 if (!Subtarget->hasMVEFloatOps())
3287 if (!
Type.isVector())
3298 if (
Node->getOperand(0) !=
Node->getOperand(1))
3303 if (ScalarBits == 16 && !
Flags.hasNoInfs() && IsUnsigned)
3307 switch (ScalarBits) {
3309 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3312 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3316 CurDAG->getConstant(1, dl, MVT::i32)};
3317 AddEmptyMVEPredicateToOps(Ops, dl,
Type);
3319 ReplaceNode(
N, CurDAG->getMachineNode(Opcode, dl,
Type, Ops));
3326 return transformFixedFloatingPointConversion(
N,
Node, IsUnsigned,
false);
3329bool ARMDAGToDAGISel::tryFMULFixed(
SDNode *
N,
SDLoc dl) {
3331 if (!Subtarget->hasMVEFloatOps())
3333 auto Type =
N->getValueType(0);
3334 if (!
Type.isVector())
3337 auto LHS =
N->getOperand(0);
3341 return transformFixedFloatingPointConversion(
3345bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(
SDNode *
N,
bool isSigned) {
3346 if (!Subtarget->hasV6T2Ops())
3350 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
3351 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
3355 unsigned And_imm = 0;
3360 if (And_imm & (And_imm + 1))
3363 unsigned Srl_imm = 0;
3366 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3371 And_imm &= -1U >> Srl_imm;
3375 unsigned LSB = Srl_imm;
3377 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3379 if ((LSB + Width + 1) ==
N->getValueType(0).getSizeInBits()) {
3381 if (Subtarget->isThumb()) {
3382 Opc =
isSigned ? ARM::t2ASRri : ARM::t2LSRri;
3383 SDValue Ops[] = {
N->getOperand(0).getOperand(0),
3384 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3385 getAL(CurDAG, dl), Reg0, Reg0 };
3386 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3395 SDValue Ops[] = {
N->getOperand(0).getOperand(0), ShOpc,
3396 getAL(CurDAG, dl), Reg0, Reg0 };
3397 CurDAG->SelectNodeTo(
N, ARM::MOVsi, MVT::i32, Ops);
3401 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3402 SDValue Ops[] = {
N->getOperand(0).getOperand(0),
3403 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3404 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3405 getAL(CurDAG, dl), Reg0 };
3406 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3414 unsigned Shl_imm = 0;
3416 assert(Shl_imm > 0 && Shl_imm < 32 &&
"bad amount in shift node!");
3417 unsigned Srl_imm = 0;
3419 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3421 unsigned Width = 32 - Srl_imm - 1;
3422 int LSB = Srl_imm - Shl_imm;
3425 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3426 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3427 SDValue Ops[] = {
N->getOperand(0).getOperand(0),
3428 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3429 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3430 getAL(CurDAG, dl), Reg0 };
3431 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3439 unsigned Srl_imm = 0;
3443 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3446 unsigned Width = MSB - LSB;
3447 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3448 assert(Srl_imm + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3449 SDValue Ops[] = {
N->getOperand(0).getOperand(0),
3450 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
3451 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3452 getAL(CurDAG, dl), Reg0 };
3453 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3459 unsigned Width = cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3465 if (LSB + Width > 32)
3468 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3469 assert(LSB + Width <= 32 &&
"Shouldn't create an invalid ubfx");
3470 SDValue Ops[] = {
N->getOperand(0).getOperand(0),
3471 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3472 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
3473 getAL(CurDAG, dl), Reg0 };
3474 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3491bool ARMDAGToDAGISel::tryABSOp(
SDNode *
N){
3492 SDValue SUBSrc0 =
N->getOperand(0);
3493 SDValue SUBSrc1 =
N->getOperand(1);
3494 EVT VT =
N->getValueType(0);
3510 if (XORSrc1 == SUBSrc1 && XORSrc0 == SRASrc0 && XType.
isInteger() &&
3512 unsigned Opcode = Subtarget->
isThumb2() ? ARM::t2ABS : ARM::ABS;
3513 CurDAG->SelectNodeTo(
N, Opcode, VT, XORSrc0);
3521void ARMDAGToDAGISel::SelectCMP_SWAP(
SDNode *
N) {
3523 EVT MemTy = cast<MemSDNode>(
N)->getMemoryVT();
3524 if (MemTy == MVT::i8)
3525 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_8 : ARM::CMP_SWAP_8;
3526 else if (MemTy == MVT::i16)
3527 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_16 : ARM::CMP_SWAP_16;
3528 else if (MemTy == MVT::i32)
3529 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_32 : ARM::CMP_SWAP_32;
3533 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
3535 SDNode *CmpSwap = CurDAG->getMachineNode(
3537 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
3540 CurDAG->setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {
MemOp});
3544 CurDAG->RemoveDeadNode(
N);
3547static std::optional<std::pair<unsigned, unsigned>>
3549 unsigned FirstOne =
A.getBitWidth() -
A.countl_zero() - 1;
3550 unsigned LastOne =
A.countr_zero();
3551 if (
A.popcount() != (FirstOne - LastOne + 1))
3552 return std::nullopt;
3553 return std::make_pair(FirstOne, LastOne);
3556void ARMDAGToDAGISel::SelectCMPZ(
SDNode *
N,
bool &SwitchEQNEToPLMI) {
3558 SwitchEQNEToPLMI =
false;
3560 if (!Subtarget->isThumb())
3567 if (!
And->hasOneUse())
3574 auto C = dyn_cast<ConstantSDNode>(
And.getOperand(1));
3588 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
3589 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3590 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3591 CurDAG->getRegister(0, MVT::i32) };
3592 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
3594 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
3595 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3596 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3597 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
3601 if (
Range->second == 0) {
3603 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3604 ReplaceNode(
And.getNode(), NewN);
3605 }
else if (
Range->first == 31) {
3607 NewN = EmitShift(ARM::tLSRri,
X,
Range->second);
3608 ReplaceNode(
And.getNode(), NewN);
3612 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3613 ReplaceNode(
And.getNode(), NewN);
3615 SwitchEQNEToPLMI =
true;
3616 }
else if (!Subtarget->hasV6T2Ops()) {
3619 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3620 NewN = EmitShift(ARM::tLSRri,
SDValue(NewN, 0),
3622 ReplaceNode(
And.getNode(), NewN);
3627 unsigned Opc128[3]) {
3629 "Unexpected vector shuffle length");
3642void ARMDAGToDAGISel::Select(
SDNode *
N) {
3645 if (
N->isMachineOpcode()) {
3650 switch (
N->getOpcode()) {
3672 cast<RegisterSDNode>(
Ptr.getOperand(1))->getReg() == ARM::SP &&
3673 Ptr.getOperand(0) ==
ST->getChain()) {
3675 CurDAG->getRegister(ARM::SP, MVT::i32),
3676 CurDAG->getTargetConstant(RHSC, dl, MVT::i32),
3678 CurDAG->getRegister(0, MVT::i32),
3681 CurDAG->getMachineNode(ARM::tSTRspi, dl, MVT::Other, Ops);
3683 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
MemOp});
3684 ReplaceNode(
N, ResNode);
3691 if (tryWriteRegister(
N))
3695 if (tryReadRegister(
N))
3700 if (tryInlineAsm(
N))
3710 unsigned Val =
N->getAsZExtVal();
3713 !Subtarget->genExecuteOnly()) {
3714 SDValue CPIdx = CurDAG->getTargetConstantPool(
3716 TLI->getPointerTy(CurDAG->getDataLayout()));
3719 if (Subtarget->isThumb()) {
3723 CurDAG->getRegister(0, MVT::i32),
3724 CurDAG->getEntryNode()
3726 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
3731 CurDAG->getTargetConstant(0, dl, MVT::i32),
3733 CurDAG->getRegister(0, MVT::i32),
3734 CurDAG->getEntryNode()
3736 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
3747 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
MemOp});
3749 ReplaceNode(
N, ResNode);
3758 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
3759 SDValue TFI = CurDAG->getTargetFrameIndex(
3760 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
3767 CurDAG->SelectNodeTo(
N, ARM::tADDframe, MVT::i32, TFI,
3768 CurDAG->getTargetConstant(0, dl, MVT::i32));
3771 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
3772 ARM::t2ADDri : ARM::ADDri);
3773 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
3774 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3775 CurDAG->getRegister(0, MVT::i32) };
3776 CurDAG->SelectNodeTo(
N, Opc, MVT::i32, Ops);
3781 if (tryInsertVectorElt(
N))
3786 if (tryV6T2BitfieldExtractOp(
N,
false))
3791 if (tryV6T2BitfieldExtractOp(
N,
true))
3798 if (tryFP_TO_INT(
N, dl))
3802 if (tryFMULFixed(
N, dl))
3809 unsigned RHSV =
C->getZExtValue();
3812 unsigned ShImm =
Log2_32(RHSV-1);
3817 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3818 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3819 if (Subtarget->isThumb()) {
3820 SDValue Ops[] = {
V,
V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
3821 CurDAG->SelectNodeTo(
N, ARM::t2ADDrs, MVT::i32, Ops);
3826 CurDAG->SelectNodeTo(
N, ARM::ADDrsi, MVT::i32, Ops);
3831 unsigned ShImm =
Log2_32(RHSV+1);
3836 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3837 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3838 if (Subtarget->isThumb()) {
3839 SDValue Ops[] = {
V,
V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
3840 CurDAG->SelectNodeTo(
N, ARM::t2RSBrs, MVT::i32, Ops);
3845 CurDAG->SelectNodeTo(
N, ARM::RSBrsi, MVT::i32, Ops);
3853 if (tryV6T2BitfieldExtractOp(
N,
false))
3859 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
3860 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
3867 bool PreferImmediateEncoding =
3868 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
3869 if (!PreferImmediateEncoding &&
3874 SDValue NewImm = CurDAG->getConstant(~Imm, dl, MVT::i32);
3878 CurDAG->RepositionNode(
N->getIterator(), NewImm.
getNode());
3880 if (!Subtarget->hasThumb2()) {
3881 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
3882 N->getOperand(0), NewImm,
getAL(CurDAG, dl),
3883 CurDAG->getRegister(0, MVT::i32)};
3884 ReplaceNode(
N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
3887 SDValue Ops[] = {
N->getOperand(0), NewImm,
getAL(CurDAG, dl),
3888 CurDAG->getRegister(0, MVT::i32),
3889 CurDAG->getRegister(0, MVT::i32)};
3891 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
3902 EVT VT =
N->getValueType(0);
3905 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
3907 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
3910 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
3911 N1C = dyn_cast<ConstantSDNode>(N1);
3919 unsigned N1CVal = N1C->getZExtValue();
3921 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
3922 (N1CVal & 0xffffU) == 0xffffU &&
3923 (N2CVal & 0xffffU) == 0x0U) {
3924 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
3927 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
3928 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
3936 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3937 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
3938 N->getOperand(2),
N->getOperand(3),
3940 CurDAG->getRegister(0, MVT::i32) };
3941 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
3945 if (Subtarget->isThumb()) {
3946 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3947 N->getOperand(3),
getAL(CurDAG, dl),
3948 CurDAG->getRegister(0, MVT::i32)};
3950 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
3953 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3954 N->getOperand(3),
getAL(CurDAG, dl),
3955 CurDAG->getRegister(0, MVT::i32),
3956 CurDAG->getRegister(0, MVT::i32) };
3957 ReplaceNode(
N, CurDAG->getMachineNode(
3958 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3959 MVT::i32, MVT::i32, Ops));
3964 if (Subtarget->isThumb()) {
3965 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3966 N->getOperand(3),
getAL(CurDAG, dl),
3967 CurDAG->getRegister(0, MVT::i32)};
3969 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
3972 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3973 N->getOperand(3),
getAL(CurDAG, dl),
3974 CurDAG->getRegister(0, MVT::i32),
3975 CurDAG->getRegister(0, MVT::i32) };
3976 ReplaceNode(
N, CurDAG->getMachineNode(
3977 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
3978 MVT::i32, MVT::i32, Ops));
3983 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
3992 if (Subtarget->isThumb())
3993 assert(Subtarget->hasThumb2() &&
3994 "This pattern should not be generated for Thumb");
3996 SDValue SmulLoHi =
N->getOperand(1);
4001 N->getOperand(1) != SmulLoHi.
getValue(1) ||
4005 unsigned Opc = Subtarget->
isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
4007 N->getOperand(0),
getAL(CurDAG, dl),
4008 CurDAG->getRegister(0, MVT::i32) };
4009 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
4013 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
4015 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
4016 if (tryT2IndexedLoad(
N))
4018 }
else if (Subtarget->isThumb()) {
4019 if (tryT1IndexedLoad(
N))
4021 }
else if (tryARMIndexedLoad(
N))
4027 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
4032 SDNode *
New = CurDAG->getMachineNode(ARM::t2WhileLoopSetup, dl, MVT::i32,
4034 ReplaceUses(
N, New);
4035 CurDAG->RemoveDeadNode(
N);
4039 SDNode *
New = CurDAG->getMachineNode(ARM::t2WhileLoopStart, dl, MVT::Other,
4040 N->getOperand(1),
N->getOperand(2),
4042 ReplaceUses(
N, New);
4043 CurDAG->RemoveDeadNode(
N);
4047 SDValue Ops[] = {
N->getOperand(1),
4050 unsigned Opc = ARM::t2LoopEnd;
4051 SDNode *
New = CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops);
4052 ReplaceUses(
N, New);
4053 CurDAG->RemoveDeadNode(
N);
4060 const SDValue &Chain =
N->getOperand(0);
4062 SelectAddrMode3(
Addr,
Base, RegOffset, ImmOffset);
4063 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4069 RegOffset = CurDAG->getRegister(0, MVT::i32);
4071 SDValue Ops[] = {
Base, RegOffset, ImmOffset, Chain};
4072 SDNode *
New = CurDAG->getMachineNode(ARM::LOADDUAL, dl,
4073 {MVT::Untyped, MVT::Other}, Ops);
4074 SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4076 SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4078 transferMemOperands(
N, New);
4082 CurDAG->RemoveDeadNode(
N);
4089 const SDValue &Chain =
N->getOperand(0);
4091 SelectAddrMode3(
Addr,
Base, RegOffset, ImmOffset);
4092 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4098 RegOffset = CurDAG->getRegister(0, MVT::i32);
4103 SDNode *
New = CurDAG->getMachineNode(ARM::STOREDUAL, dl, MVT::Other, Ops);
4104 transferMemOperands(
N, New);
4106 CurDAG->RemoveDeadNode(
N);
4110 SDValue Ops[] = {
N->getOperand(1),
4114 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4115 CurDAG->getVTList(MVT::i32, MVT::Other), Ops);
4116 ReplaceUses(
N, Dec);
4117 CurDAG->RemoveDeadNode(
N);
4133 unsigned Opc = Subtarget->isThumb() ?
4134 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
4152 if (
ID == Intrinsic::loop_decrement_reg) {
4154 SDValue Size = CurDAG->getTargetConstant(
Int.getConstantOperandVal(3),
4159 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4160 CurDAG->getVTList(MVT::i32, MVT::Other),
4162 ReplaceUses(
Int.getNode(), LoopDec);
4166 CurDAG->getMachineNode(ARM::t2LoopEnd, dl, MVT::Other, EndArgs);
4168 ReplaceUses(
N, LoopEnd);
4169 CurDAG->RemoveDeadNode(
N);
4170 CurDAG->RemoveDeadNode(InGlue.
getNode());
4171 CurDAG->RemoveDeadNode(
Int.getNode());
4176 bool SwitchEQNEToPLMI;
4177 SelectCMPZ(InGlue.
getNode(), SwitchEQNEToPLMI);
4178 InGlue =
N->getOperand(4);
4180 if (SwitchEQNEToPLMI) {
4193 SDValue Tmp2 = CurDAG->getTargetConstant(
CC, dl, MVT::i32);
4194 SDValue Ops[] = { N1, Tmp2, N3, Chain, InGlue };
4195 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
4198 if (
N->getNumValues() == 2) {
4200 ReplaceUses(
SDValue(
N, 1), InGlue);
4204 CurDAG->RemoveDeadNode(
N);
4214 auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(1).getNode());
4215 if (
C &&
C->getSExtValue() < 0 && Subtarget->isThumb()) {
4216 int64_t Addend = -
C->getSExtValue();
4223 if (Addend < 1<<8) {
4225 SDValue Ops[] = {
X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4226 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
4227 CurDAG->getRegister(0, MVT::i32) };
4228 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
4230 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
4231 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
X,
4232 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4233 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
4234 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
4239 CurDAG->MorphNodeTo(
N,
ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
4250 bool SwitchEQNEToPLMI;
4251 SelectCMPZ(InGlue.
getNode(), SwitchEQNEToPLMI);
4253 if (SwitchEQNEToPLMI) {
4266 SDValue NewARMcc = CurDAG->getConstant((
unsigned)
CC, dl, MVT::i32);
4267 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), NewARMcc,
4268 N->getOperand(3),
N->getOperand(4)};
4277 EVT VT =
N->getValueType(0);
4279 unsigned Opc64[] = {ARM::VZIPd8, ARM::VZIPd16, ARM::VTRNd32};
4280 unsigned Opc128[] = {ARM::VZIPq8, ARM::VZIPq16, ARM::VZIPq32};
4283 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4284 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4285 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
4289 EVT VT =
N->getValueType(0);
4291 unsigned Opc64[] = {ARM::VUZPd8, ARM::VUZPd16, ARM::VTRNd32};
4292 unsigned Opc128[] = {ARM::VUZPq8, ARM::VUZPq16, ARM::VUZPq32};
4295 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4296 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4297 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
4301 EVT VT =
N->getValueType(0);
4302 unsigned Opc64[] = {ARM::VTRNd8, ARM::VTRNd16, ARM::VTRNd32};
4303 unsigned Opc128[] = {ARM::VTRNq8, ARM::VTRNq16, ARM::VTRNq32};
4306 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4307 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4308 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
4312 EVT VecVT =
N->getValueType(0);
4315 if (EltVT == MVT::f64) {
4316 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
4318 N, createDRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4321 assert(EltVT == MVT::f32 &&
"unexpected type for BUILD_VECTOR");
4324 N, createSRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4327 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
4329 createQuadSRegsNode(VecVT,
N->getOperand(0),
N->getOperand(1),
4330 N->getOperand(2),
N->getOperand(3)));
4335 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
4337 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
4339 SelectVLDDup(
N,
false,
false, 1, DOpcodes, QOpcodes);
4344 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4346 SelectVLDDup(
N,
false,
false, 2, Opcodes);
4351 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
4352 ARM::VLD3DUPd16Pseudo,
4353 ARM::VLD3DUPd32Pseudo };
4354 SelectVLDDup(
N,
false,
false, 3, Opcodes);
4359 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
4360 ARM::VLD4DUPd16Pseudo,
4361 ARM::VLD4DUPd32Pseudo };
4362 SelectVLDDup(
N,
false,
false, 4, Opcodes);
4367 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
4368 ARM::VLD1DUPd16wb_fixed,
4369 ARM::VLD1DUPd32wb_fixed };
4370 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
4371 ARM::VLD1DUPq16wb_fixed,
4372 ARM::VLD1DUPq32wb_fixed };
4373 SelectVLDDup(
N,
false,
true, 1, DOpcodes, QOpcodes);
4378 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8wb_fixed,
4379 ARM::VLD2DUPd16wb_fixed,
4380 ARM::VLD2DUPd32wb_fixed,
4381 ARM::VLD1q64wb_fixed };
4382 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4383 ARM::VLD2DUPq16EvenPseudo,
4384 ARM::VLD2DUPq32EvenPseudo };
4385 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudoWB_fixed,
4386 ARM::VLD2DUPq16OddPseudoWB_fixed,
4387 ARM::VLD2DUPq32OddPseudoWB_fixed };
4388 SelectVLDDup(
N,
false,
true, 2, DOpcodes, QOpcodes0, QOpcodes1);
4393 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
4394 ARM::VLD3DUPd16Pseudo_UPD,
4395 ARM::VLD3DUPd32Pseudo_UPD,
4396 ARM::VLD1d64TPseudoWB_fixed };
4397 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4398 ARM::VLD3DUPq16EvenPseudo,
4399 ARM::VLD3DUPq32EvenPseudo };
4400 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo_UPD,
4401 ARM::VLD3DUPq16OddPseudo_UPD,
4402 ARM::VLD3DUPq32OddPseudo_UPD };
4403 SelectVLDDup(
N,
false,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4408 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
4409 ARM::VLD4DUPd16Pseudo_UPD,
4410 ARM::VLD4DUPd32Pseudo_UPD,
4411 ARM::VLD1d64QPseudoWB_fixed };
4412 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4413 ARM::VLD4DUPq16EvenPseudo,
4414 ARM::VLD4DUPq32EvenPseudo };
4415 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo_UPD,
4416 ARM::VLD4DUPq16OddPseudo_UPD,
4417 ARM::VLD4DUPq32OddPseudo_UPD };
4418 SelectVLDDup(
N,
false,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4423 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
4424 ARM::VLD1d16wb_fixed,
4425 ARM::VLD1d32wb_fixed,
4426 ARM::VLD1d64wb_fixed };
4427 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
4428 ARM::VLD1q16wb_fixed,
4429 ARM::VLD1q32wb_fixed,
4430 ARM::VLD1q64wb_fixed };
4431 SelectVLD(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4436 if (Subtarget->hasNEON()) {
4437 static const uint16_t DOpcodes[] = {
4438 ARM::VLD2d8wb_fixed, ARM::VLD2d16wb_fixed, ARM::VLD2d32wb_fixed,
4439 ARM::VLD1q64wb_fixed};
4440 static const uint16_t QOpcodes[] = {ARM::VLD2q8PseudoWB_fixed,
4441 ARM::VLD2q16PseudoWB_fixed,
4442 ARM::VLD2q32PseudoWB_fixed};
4443 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4445 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8,
4446 ARM::MVE_VLD21_8_wb};
4447 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
4448 ARM::MVE_VLD21_16_wb};
4449 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
4450 ARM::MVE_VLD21_32_wb};
4451 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4452 SelectMVE_VLD(
N, 2, Opcodes,
true);
4458 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
4459 ARM::VLD3d16Pseudo_UPD,
4460 ARM::VLD3d32Pseudo_UPD,
4461 ARM::VLD1d64TPseudoWB_fixed};
4462 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4463 ARM::VLD3q16Pseudo_UPD,
4464 ARM::VLD3q32Pseudo_UPD };
4465 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
4466 ARM::VLD3q16oddPseudo_UPD,
4467 ARM::VLD3q32oddPseudo_UPD };
4468 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4473 if (Subtarget->hasNEON()) {
4474 static const uint16_t DOpcodes[] = {
4475 ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, ARM::VLD4d32Pseudo_UPD,
4476 ARM::VLD1d64QPseudoWB_fixed};
4477 static const uint16_t QOpcodes0[] = {ARM::VLD4q8Pseudo_UPD,
4478 ARM::VLD4q16Pseudo_UPD,
4479 ARM::VLD4q32Pseudo_UPD};
4480 static const uint16_t QOpcodes1[] = {ARM::VLD4q8oddPseudo_UPD,
4481 ARM::VLD4q16oddPseudo_UPD,
4482 ARM::VLD4q32oddPseudo_UPD};
4483 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4485 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
4487 ARM::MVE_VLD43_8_wb};
4488 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
4490 ARM::MVE_VLD43_16_wb};
4491 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
4493 ARM::MVE_VLD43_32_wb};
4494 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4495 SelectMVE_VLD(
N, 4, Opcodes,
true);
4501 if (Subtarget->hasNEON()) {
4502 static const uint16_t DOpcodes[] = {
4503 ARM::VLD1q8wb_fixed, ARM::VLD1q16wb_fixed, ARM::VLD1q32wb_fixed,
4504 ARM::VLD1q64wb_fixed};
4505 static const uint16_t QOpcodes[] = {
4506 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4507 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4508 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4515 if (Subtarget->hasNEON()) {
4516 static const uint16_t DOpcodes[] = {
4517 ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d16TPseudoWB_fixed,
4518 ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d64TPseudoWB_fixed};
4519 static const uint16_t QOpcodes0[] = {
4520 ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1q16LowTPseudo_UPD,
4521 ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1q64LowTPseudo_UPD};
4522 static const uint16_t QOpcodes1[] = {
4523 ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1q16HighTPseudo_UPD,
4524 ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1q64HighTPseudo_UPD};
4525 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4532 if (Subtarget->hasNEON()) {
4533 static const uint16_t DOpcodes[] = {
4534 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4535 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4536 static const uint16_t QOpcodes0[] = {
4537 ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1q16LowQPseudo_UPD,
4538 ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1q64LowQPseudo_UPD};
4539 static const uint16_t QOpcodes1[] = {
4540 ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1q16HighQPseudo_UPD,
4541 ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1q64HighQPseudo_UPD};
4542 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4549 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
4550 ARM::VLD2LNd16Pseudo_UPD,
4551 ARM::VLD2LNd32Pseudo_UPD };
4552 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
4553 ARM::VLD2LNq32Pseudo_UPD };
4554 SelectVLDSTLane(
N,
true,
true, 2, DOpcodes, QOpcodes);
4559 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
4560 ARM::VLD3LNd16Pseudo_UPD,
4561 ARM::VLD3LNd32Pseudo_UPD };
4562 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
4563 ARM::VLD3LNq32Pseudo_UPD };
4564 SelectVLDSTLane(
N,
true,
true, 3, DOpcodes, QOpcodes);
4569 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
4570 ARM::VLD4LNd16Pseudo_UPD,
4571 ARM::VLD4LNd32Pseudo_UPD };
4572 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
4573 ARM::VLD4LNq32Pseudo_UPD };
4574 SelectVLDSTLane(
N,
true,
true, 4, DOpcodes, QOpcodes);
4579 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
4580 ARM::VST1d16wb_fixed,
4581 ARM::VST1d32wb_fixed,
4582 ARM::VST1d64wb_fixed };
4583 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
4584 ARM::VST1q16wb_fixed,
4585 ARM::VST1q32wb_fixed,
4586 ARM::VST1q64wb_fixed };
4587 SelectVST(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4592 if (Subtarget->hasNEON()) {
4593 static const uint16_t DOpcodes[] = {
4594 ARM::VST2d8wb_fixed, ARM::VST2d16wb_fixed, ARM::VST2d32wb_fixed,
4595 ARM::VST1q64wb_fixed};
4596 static const uint16_t QOpcodes[] = {ARM::VST2q8PseudoWB_fixed,
4597 ARM::VST2q16PseudoWB_fixed,
4598 ARM::VST2q32PseudoWB_fixed};
4599 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4606 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
4607 ARM::VST3d16Pseudo_UPD,
4608 ARM::VST3d32Pseudo_UPD,
4609 ARM::VST1d64TPseudoWB_fixed};
4610 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
4611 ARM::VST3q16Pseudo_UPD,
4612 ARM::VST3q32Pseudo_UPD };
4613 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
4614 ARM::VST3q16oddPseudo_UPD,
4615 ARM::VST3q32oddPseudo_UPD };
4616 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4621 if (Subtarget->hasNEON()) {
4622 static const uint16_t DOpcodes[] = {
4623 ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, ARM::VST4d32Pseudo_UPD,
4624 ARM::VST1d64QPseudoWB_fixed};
4625 static const uint16_t QOpcodes0[] = {ARM::VST4q8Pseudo_UPD,
4626 ARM::VST4q16Pseudo_UPD,
4627 ARM::VST4q32Pseudo_UPD};
4628 static const uint16_t QOpcodes1[] = {ARM::VST4q8oddPseudo_UPD,
4629 ARM::VST4q16oddPseudo_UPD,
4630 ARM::VST4q32oddPseudo_UPD};
4631 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4638 if (Subtarget->hasNEON()) {
4639 static const uint16_t DOpcodes[] = { ARM::VST1q8wb_fixed,
4640 ARM::VST1q16wb_fixed,
4641 ARM::VST1q32wb_fixed,
4642 ARM::VST1q64wb_fixed};
4643 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4644 ARM::VST1d16QPseudoWB_fixed,
4645 ARM::VST1d32QPseudoWB_fixed,
4646 ARM::VST1d64QPseudoWB_fixed };
4647 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4654 if (Subtarget->hasNEON()) {
4655 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudoWB_fixed,
4656 ARM::VST1d16TPseudoWB_fixed,
4657 ARM::VST1d32TPseudoWB_fixed,
4658 ARM::VST1d64TPseudoWB_fixed };
4659 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4660 ARM::VST1q16LowTPseudo_UPD,
4661 ARM::VST1q32LowTPseudo_UPD,
4662 ARM::VST1q64LowTPseudo_UPD };
4663 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo_UPD,
4664 ARM::VST1q16HighTPseudo_UPD,
4665 ARM::VST1q32HighTPseudo_UPD,
4666 ARM::VST1q64HighTPseudo_UPD };
4667 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4674 if (Subtarget->hasNEON()) {
4675 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4676 ARM::VST1d16QPseudoWB_fixed,
4677 ARM::VST1d32QPseudoWB_fixed,
4678 ARM::VST1d64QPseudoWB_fixed };
4679 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4680 ARM::VST1q16LowQPseudo_UPD,
4681 ARM::VST1q32LowQPseudo_UPD,
4682 ARM::VST1q64LowQPseudo_UPD };
4683 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo_UPD,
4684 ARM::VST1q16HighQPseudo_UPD,
4685 ARM::VST1q32HighQPseudo_UPD,
4686 ARM::VST1q64HighQPseudo_UPD };
4687 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4693 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
4694 ARM::VST2LNd16Pseudo_UPD,
4695 ARM::VST2LNd32Pseudo_UPD };
4696 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
4697 ARM::VST2LNq32Pseudo_UPD };
4698 SelectVLDSTLane(
N,
false,
true, 2, DOpcodes, QOpcodes);
4703 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
4704 ARM::VST3LNd16Pseudo_UPD,
4705 ARM::VST3LNd32Pseudo_UPD };
4706 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
4707 ARM::VST3LNq32Pseudo_UPD };
4708 SelectVLDSTLane(
N,
false,
true, 3, DOpcodes, QOpcodes);
4713 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
4714 ARM::VST4LNd16Pseudo_UPD,
4715 ARM::VST4LNd32Pseudo_UPD };
4716 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
4717 ARM::VST4LNq32Pseudo_UPD };
4718 SelectVLDSTLane(
N,
false,
true, 4, DOpcodes, QOpcodes);
4724 unsigned IntNo =
N->getConstantOperandVal(1);
4729 case Intrinsic::arm_mrrc:
4730 case Intrinsic::arm_mrrc2: {
4735 if (Subtarget->isThumb())
4736 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
4738 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
4741 Ops.
push_back(getI32Imm(
N->getConstantOperandVal(2), dl));
4742 Ops.
push_back(getI32Imm(
N->getConstantOperandVal(3), dl));
4743 Ops.
push_back(getI32Imm(
N->getConstantOperandVal(4), dl));
4748 if (Opc != ARM::MRRC2) {
4750 Ops.
push_back(CurDAG->getRegister(0, MVT::i32));
4756 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
4758 ReplaceNode(
N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
4761 case Intrinsic::arm_ldaexd:
4762 case Intrinsic::arm_ldrexd: {
4765 SDValue MemAddr =
N->getOperand(2);
4766 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
4768 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
4769 unsigned NewOpc =
isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
4770 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
4773 std::vector<EVT> ResTys;
4775 ResTys.push_back(MVT::i32);
4776 ResTys.push_back(MVT::i32);
4778 ResTys.push_back(MVT::Untyped);
4779 ResTys.push_back(MVT::Other);
4783 CurDAG->getRegister(0, MVT::i32), Chain};
4784 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
4787 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {
MemOp});
4797 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
4798 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4799 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4802 ReplaceUses(
SDValue(
N, 0), Result);
4810 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
4811 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4812 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4815 ReplaceUses(
SDValue(
N, 1), Result);
4817 ReplaceUses(
SDValue(
N, 2), OutChain);
4818 CurDAG->RemoveDeadNode(
N);
4821 case Intrinsic::arm_stlexd:
4822 case Intrinsic::arm_strexd: {
4827 SDValue MemAddr =
N->getOperand(4);
4831 const EVT ResTys[] = {MVT::i32, MVT::Other};
4833 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
4844 Ops.
push_back(CurDAG->getRegister(0, MVT::i32));
4847 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
4848 unsigned NewOpc =
isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
4849 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
4851 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
4854 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {
MemOp});
4860 case Intrinsic::arm_neon_vld1: {
4861 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
4862 ARM::VLD1d32, ARM::VLD1d64 };
4863 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4864 ARM::VLD1q32, ARM::VLD1q64};
4865 SelectVLD(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4869 case Intrinsic::arm_neon_vld1x2: {
4870 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4871 ARM::VLD1q32, ARM::VLD1q64 };
4872 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
4873 ARM::VLD1d16QPseudo,
4874 ARM::VLD1d32QPseudo,
4875 ARM::VLD1d64QPseudo };
4876 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4880 case Intrinsic::arm_neon_vld1x3: {
4881 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
4882 ARM::VLD1d16TPseudo,
4883 ARM::VLD1d32TPseudo,
4884 ARM::VLD1d64TPseudo };
4885 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
4886 ARM::VLD1q16LowTPseudo_UPD,
4887 ARM::VLD1q32LowTPseudo_UPD,
4888 ARM::VLD1q64LowTPseudo_UPD };
4889 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
4890 ARM::VLD1q16HighTPseudo,
4891 ARM::VLD1q32HighTPseudo,
4892 ARM::VLD1q64HighTPseudo };
4893 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4897 case Intrinsic::arm_neon_vld1x4: {
4898 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
4899 ARM::VLD1d16QPseudo,
4900 ARM::VLD1d32QPseudo,
4901 ARM::VLD1d64QPseudo };
4902 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
4903 ARM::VLD1q16LowQPseudo_UPD,
4904 ARM::VLD1q32LowQPseudo_UPD,
4905 ARM::VLD1q64LowQPseudo_UPD };
4906 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
4907 ARM::VLD1q16HighQPseudo,
4908 ARM::VLD1q32HighQPseudo,
4909 ARM::VLD1q64HighQPseudo };
4910 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4914 case Intrinsic::arm_neon_vld2: {
4915 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
4916 ARM::VLD2d32, ARM::VLD1q64 };
4917 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
4918 ARM::VLD2q32Pseudo };
4919 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4923 case Intrinsic::arm_neon_vld3: {
4924 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
4927 ARM::VLD1d64TPseudo };
4928 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4929 ARM::VLD3q16Pseudo_UPD,
4930 ARM::VLD3q32Pseudo_UPD };
4931 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
4932 ARM::VLD3q16oddPseudo,
4933 ARM::VLD3q32oddPseudo };
4934 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4938 case Intrinsic::arm_neon_vld4: {
4939 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
4942 ARM::VLD1d64QPseudo };
4943 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
4944 ARM::VLD4q16Pseudo_UPD,
4945 ARM::VLD4q32Pseudo_UPD };
4946 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
4947 ARM::VLD4q16oddPseudo,
4948 ARM::VLD4q32oddPseudo };
4949 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4953 case Intrinsic::arm_neon_vld2dup: {
4954 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4955 ARM::VLD2DUPd32, ARM::VLD1q64 };
4956 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4957 ARM::VLD2DUPq16EvenPseudo,
4958 ARM::VLD2DUPq32EvenPseudo };
4959 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo,
4960 ARM::VLD2DUPq16OddPseudo,
4961 ARM::VLD2DUPq32OddPseudo };
4962 SelectVLDDup(
N,
true,
false, 2,
4963 DOpcodes, QOpcodes0, QOpcodes1);
4967 case Intrinsic::arm_neon_vld3dup: {
4968 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo,
4969 ARM::VLD3DUPd16Pseudo,
4970 ARM::VLD3DUPd32Pseudo,
4971 ARM::VLD1d64TPseudo };
4972 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4973 ARM::VLD3DUPq16EvenPseudo,
4974 ARM::VLD3DUPq32EvenPseudo };
4975 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo,
4976 ARM::VLD3DUPq16OddPseudo,
4977 ARM::VLD3DUPq32OddPseudo };
4978 SelectVLDDup(
N,
true,
false, 3,
4979 DOpcodes, QOpcodes0, QOpcodes1);
4983 case Intrinsic::arm_neon_vld4dup: {
4984 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo,
4985 ARM::VLD4DUPd16Pseudo,
4986 ARM::VLD4DUPd32Pseudo,
4987 ARM::VLD1d64QPseudo };
4988 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4989 ARM::VLD4DUPq16EvenPseudo,
4990 ARM::VLD4DUPq32EvenPseudo };
4991 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo,
4992 ARM::VLD4DUPq16OddPseudo,
4993 ARM::VLD4DUPq32OddPseudo };
4994 SelectVLDDup(
N,
true,
false, 4,
4995 DOpcodes, QOpcodes0, QOpcodes1);
4999 case Intrinsic::arm_neon_vld2lane: {
5000 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
5001 ARM::VLD2LNd16Pseudo,
5002 ARM::VLD2LNd32Pseudo };
5003 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
5004 ARM::VLD2LNq32Pseudo };
5005 SelectVLDSTLane(
N,
true,
false, 2, DOpcodes, QOpcodes);
5009 case Intrinsic::arm_neon_vld3lane: {
5010 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
5011 ARM::VLD3LNd16Pseudo,
5012 ARM::VLD3LNd32Pseudo };
5013 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
5014 ARM::VLD3LNq32Pseudo };
5015 SelectVLDSTLane(
N,
true,
false, 3, DOpcodes, QOpcodes);
5019 case Intrinsic::arm_neon_vld4lane: {
5020 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
5021 ARM::VLD4LNd16Pseudo,
5022 ARM::VLD4LNd32Pseudo };
5023 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
5024 ARM::VLD4LNq32Pseudo };
5025 SelectVLDSTLane(
N,
true,
false, 4, DOpcodes, QOpcodes);
5029 case Intrinsic::arm_neon_vst1: {
5030 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
5031 ARM::VST1d32, ARM::VST1d64 };
5032 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
5033 ARM::VST1q32, ARM::VST1q64 };
5034 SelectVST(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
5038 case Intrinsic::arm_neon_vst1x2: {
5039 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
5040 ARM::VST1q32, ARM::VST1q64 };
5041 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
5042 ARM::VST1d16QPseudo,
5043 ARM::VST1d32QPseudo,
5044 ARM::VST1d64QPseudo };
5045 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
5049 case Intrinsic::arm_neon_vst1x3: {
5050 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
5051 ARM::VST1d16TPseudo,
5052 ARM::VST1d32TPseudo,
5053 ARM::VST1d64TPseudo };
5054 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
5055 ARM::VST1q16LowTPseudo_UPD,
5056 ARM::VST1q32LowTPseudo_UPD,
5057 ARM::VST1q64LowTPseudo_UPD };
5058 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
5059 ARM::VST1q16HighTPseudo,
5060 ARM::VST1q32HighTPseudo,
5061 ARM::VST1q64HighTPseudo };
5062 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
5066 case Intrinsic::arm_neon_vst1x4: {
5067 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
5068 ARM::VST1d16QPseudo,
5069 ARM::VST1d32QPseudo,
5070 ARM::VST1d64QPseudo };
5071 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
5072 ARM::VST1q16LowQPseudo_UPD,
5073 ARM::VST1q32LowQPseudo_UPD,
5074 ARM::VST1q64LowQPseudo_UPD };
5075 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
5076 ARM::VST1q16HighQPseudo,
5077 ARM::VST1q32HighQPseudo,
5078 ARM::VST1q64HighQPseudo };
5079 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5083 case Intrinsic::arm_neon_vst2: {
5084 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
5085 ARM::VST2d32, ARM::VST1q64 };
5086 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
5087 ARM::VST2q32Pseudo };
5088 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
5092 case Intrinsic::arm_neon_vst3: {
5093 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
5096 ARM::VST1d64TPseudo };
5097 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
5098 ARM::VST3q16Pseudo_UPD,
5099 ARM::VST3q32Pseudo_UPD };
5100 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
5101 ARM::VST3q16oddPseudo,
5102 ARM::VST3q32oddPseudo };
5103 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
5107 case Intrinsic::arm_neon_vst4: {
5108 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
5111 ARM::VST1d64QPseudo };
5112 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
5113 ARM::VST4q16Pseudo_UPD,
5114 ARM::VST4q32Pseudo_UPD };
5115 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
5116 ARM::VST4q16oddPseudo,
5117 ARM::VST4q32oddPseudo };
5118 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5122 case Intrinsic::arm_neon_vst2lane: {
5123 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
5124 ARM::VST2LNd16Pseudo,
5125 ARM::VST2LNd32Pseudo };
5126 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
5127 ARM::VST2LNq32Pseudo };
5128 SelectVLDSTLane(
N,
false,
false, 2, DOpcodes, QOpcodes);
5132 case Intrinsic::arm_neon_vst3lane: {
5133 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
5134 ARM::VST3LNd16Pseudo,
5135 ARM::VST3LNd32Pseudo };
5136 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
5137 ARM::VST3LNq32Pseudo };
5138 SelectVLDSTLane(
N,
false,
false, 3, DOpcodes, QOpcodes);
5142 case Intrinsic::arm_neon_vst4lane: {
5143 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
5144 ARM::VST4LNd16Pseudo,
5145 ARM::VST4LNd32Pseudo };
5146 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
5147 ARM::VST4LNq32Pseudo };
5148 SelectVLDSTLane(
N,
false,
false, 4, DOpcodes, QOpcodes);
5152 case Intrinsic::arm_mve_vldr_gather_base_wb:
5153 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
5154 static const uint16_t Opcodes[] = {ARM::MVE_VLDRWU32_qi_pre,
5155 ARM::MVE_VLDRDU64_qi_pre};
5156 SelectMVE_WB(
N, Opcodes,
5157 IntNo == Intrinsic::arm_mve_vldr_gather_base_wb_predicated);
5161 case Intrinsic::arm_mve_vld2q: {
5162 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, ARM::MVE_VLD21_8};
5163 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
5165 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
5167 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5168 SelectMVE_VLD(
N, 2, Opcodes,
false);
5172 case Intrinsic::arm_mve_vld4q: {
5173 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
5174 ARM::MVE_VLD42_8, ARM::MVE_VLD43_8};
5175 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
5178 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
5181 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5182 SelectMVE_VLD(
N, 4, Opcodes,
false);
5190 unsigned IntNo =
N->getConstantOperandVal(0);
5196 case Intrinsic::arm_neon_vcvtbfp2bf: {
5198 const SDValue &Src =
N->getOperand(1);
5201 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5202 SDValue Ops[] = { Src, Src, Pred, Reg0 };
5203 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVTB, DestTy, Ops);
5208 case Intrinsic::arm_neon_vcvtfp2bf: {
5210 const SDValue &Src =
N->getOperand(1);
5212 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5213 SDValue Ops[] = { Src, Pred, Reg0 };
5214 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVT, MVT::v4bf16, Ops);
5218 case Intrinsic::arm_mve_urshrl:
5219 SelectMVE_LongShift(
N, ARM::MVE_URSHRL,
true,
false);
5221 case Intrinsic::arm_mve_uqshll:
5222 SelectMVE_LongShift(
N, ARM::MVE_UQSHLL,
true,
false);
5224 case Intrinsic::arm_mve_srshrl:
5225 SelectMVE_LongShift(
N, ARM::MVE_SRSHRL,
true,
false);
5227 case Intrinsic::arm_mve_sqshll:
5228 SelectMVE_LongShift(
N, ARM::MVE_SQSHLL,
true,
false);
5230 case Intrinsic::arm_mve_uqrshll:
5231 SelectMVE_LongShift(
N, ARM::MVE_UQRSHLL,
false,
true);
5233 case Intrinsic::arm_mve_sqrshrl:
5234 SelectMVE_LongShift(
N, ARM::MVE_SQRSHRL,
false,
true);
5237 case Intrinsic::arm_mve_vadc:
5238 case Intrinsic::arm_mve_vadc_predicated:
5239 SelectMVE_VADCSBC(
N, ARM::MVE_VADC, ARM::MVE_VADCI,
true,
5240 IntNo == Intrinsic::arm_mve_vadc_predicated);
5242 case Intrinsic::arm_mve_vsbc:
5243 case Intrinsic::arm_mve_vsbc_predicated:
5244 SelectMVE_VADCSBC(
N, ARM::MVE_VSBC, ARM::MVE_VSBCI,
true,
5245 IntNo == Intrinsic::arm_mve_vsbc_predicated);
5247 case Intrinsic::arm_mve_vshlc:
5248 case Intrinsic::arm_mve_vshlc_predicated:
5249 SelectMVE_VSHLC(
N, IntNo == Intrinsic::arm_mve_vshlc_predicated);
5252 case Intrinsic::arm_mve_vmlldava:
5253 case Intrinsic::arm_mve_vmlldava_predicated: {
5254 static const uint16_t OpcodesU[] = {
5255 ARM::MVE_VMLALDAVu16, ARM::MVE_VMLALDAVu32,
5256 ARM::MVE_VMLALDAVau16, ARM::MVE_VMLALDAVau32,
5258 static const uint16_t OpcodesS[] = {
5259 ARM::MVE_VMLALDAVs16, ARM::MVE_VMLALDAVs32,
5260 ARM::MVE_VMLALDAVas16, ARM::MVE_VMLALDAVas32,
5261 ARM::MVE_VMLALDAVxs16, ARM::MVE_VMLALDAVxs32,
5262 ARM::MVE_VMLALDAVaxs16, ARM::MVE_VMLALDAVaxs32,
5263 ARM::MVE_VMLSLDAVs16, ARM::MVE_VMLSLDAVs32,
5264 ARM::MVE_VMLSLDAVas16, ARM::MVE_VMLSLDAVas32,
5265 ARM::MVE_VMLSLDAVxs16, ARM::MVE_VMLSLDAVxs32,
5266 ARM::MVE_VMLSLDAVaxs16, ARM::MVE_VMLSLDAVaxs32,
5268 SelectMVE_VMLLDAV(
N, IntNo == Intrinsic::arm_mve_vmlldava_predicated,
5269 OpcodesS, OpcodesU);
5273 case Intrinsic::arm_mve_vrmlldavha:
5274 case Intrinsic::arm_mve_vrmlldavha_predicated: {
5275 static const uint16_t OpcodesU[] = {
5276 ARM::MVE_VRMLALDAVHu32, ARM::MVE_VRMLALDAVHau32,
5278 static const uint16_t OpcodesS[] = {
5279 ARM::MVE_VRMLALDAVHs32, ARM::MVE_VRMLALDAVHas32,
5280 ARM::MVE_VRMLALDAVHxs32, ARM::MVE_VRMLALDAVHaxs32,
5281 ARM::MVE_VRMLSLDAVHs32, ARM::MVE_VRMLSLDAVHas32,
5282 ARM::MVE_VRMLSLDAVHxs32, ARM::MVE_VRMLSLDAVHaxs32,
5284 SelectMVE_VRMLLDAVH(
N, IntNo == Intrinsic::arm_mve_vrmlldavha_predicated,
5285 OpcodesS, OpcodesU);
5289 case Intrinsic::arm_mve_vidup:
5290 case Intrinsic::arm_mve_vidup_predicated: {
5291 static const uint16_t Opcodes[] = {
5292 ARM::MVE_VIDUPu8, ARM::MVE_VIDUPu16, ARM::MVE_VIDUPu32,
5294 SelectMVE_VxDUP(
N, Opcodes,
false,
5295 IntNo == Intrinsic::arm_mve_vidup_predicated);
5299 case Intrinsic::arm_mve_vddup:
5300 case Intrinsic::arm_mve_vddup_predicated: {
5301 static const uint16_t Opcodes[] = {
5302 ARM::MVE_VDDUPu8, ARM::MVE_VDDUPu16, ARM::MVE_VDDUPu32,
5304 SelectMVE_VxDUP(
N, Opcodes,
false,
5305 IntNo == Intrinsic::arm_mve_vddup_predicated);
5309 case Intrinsic::arm_mve_viwdup:
5310 case Intrinsic::arm_mve_viwdup_predicated: {
5311 static const uint16_t Opcodes[] = {
5312 ARM::MVE_VIWDUPu8, ARM::MVE_VIWDUPu16, ARM::MVE_VIWDUPu32,
5314 SelectMVE_VxDUP(
N, Opcodes,
true,
5315 IntNo == Intrinsic::arm_mve_viwdup_predicated);
5319 case Intrinsic::arm_mve_vdwdup:
5320 case Intrinsic::arm_mve_vdwdup_predicated: {
5321 static const uint16_t Opcodes[] = {
5322 ARM::MVE_VDWDUPu8, ARM::MVE_VDWDUPu16, ARM::MVE_VDWDUPu32,
5324 SelectMVE_VxDUP(
N, Opcodes,
true,
5325 IntNo == Intrinsic::arm_mve_vdwdup_predicated);
5329 case Intrinsic::arm_cde_cx1d:
5330 case Intrinsic::arm_cde_cx1da:
5331 case Intrinsic::arm_cde_cx2d:
5332 case Intrinsic::arm_cde_cx2da:
5333 case Intrinsic::arm_cde_cx3d:
5334 case Intrinsic::arm_cde_cx3da: {
5335 bool HasAccum = IntNo == Intrinsic::arm_cde_cx1da ||
5336 IntNo == Intrinsic::arm_cde_cx2da ||
5337 IntNo == Intrinsic::arm_cde_cx3da;
5341 case Intrinsic::arm_cde_cx1d:
5342 case Intrinsic::arm_cde_cx1da:
5344 Opcode = HasAccum ? ARM::CDE_CX1DA : ARM::CDE_CX1D;
5346 case Intrinsic::arm_cde_cx2d:
5347 case Intrinsic::arm_cde_cx2da:
5349 Opcode = HasAccum ? ARM::CDE_CX2DA : ARM::CDE_CX2D;
5351 case Intrinsic::arm_cde_cx3d:
5352 case Intrinsic::arm_cde_cx3da:
5354 Opcode = HasAccum ? ARM::CDE_CX3DA : ARM::CDE_CX3D;
5359 SelectCDE_CXxD(
N, Opcode, NumExtraOps, HasAccum);
5382 std::vector<SDValue> &Ops) {
5384 RegString.
split(Fields,
':');
5386 if (Fields.
size() > 1) {
5387 bool AllIntFields =
true;
5392 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
5397 "Unexpected non-integer value in special register string.");
5408 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.
lower());
5411 return TheReg->Encoding;
5423 .
Case(
"nzcvqg", 0x3)
5431 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg);
5432 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
5433 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
5435 return (
int)(TheReg->Encoding & 0xFFF);
5444 if (Reg ==
"apsr") {
5454 if (Reg !=
"cpsr" && Reg !=
"spsr") {
5459 if (Flags.empty() || Flags ==
"all")
5464 for (
char Flag : Flags) {
5484 if (!FlagVal || (Mask & FlagVal))
5499bool ARMDAGToDAGISel::tryReadRegister(
SDNode *
N){
5500 const auto *MD = cast<MDNodeSDNode>(
N->getOperand(1));
5501 const auto *RegString = cast<MDString>(MD->getMD()->getOperand(0));
5502 bool IsThumb2 = Subtarget->
isThumb2();
5505 std::vector<SDValue> Ops;
5515 if (Ops.size() == 5){
5516 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
5517 ResTypes.
append({ MVT::i32, MVT::Other });
5519 assert(Ops.size() == 3 &&
5520 "Invalid number of fields in special register string.");
5521 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
5522 ResTypes.
append({ MVT::i32, MVT::i32, MVT::Other });
5525 Ops.push_back(
getAL(CurDAG,
DL));
5526 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5527 Ops.push_back(
N->getOperand(0));
5528 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, ResTypes, Ops));
5532 std::string SpecialReg = RegString->getString().lower();
5535 if (BankedReg != -1) {
5536 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
5537 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5540 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
5541 DL, MVT::i32, MVT::Other, Ops));
5549 .
Case(
"fpscr", ARM::VMRS)
5550 .
Case(
"fpexc", ARM::VMRS_FPEXC)
5551 .
Case(
"fpsid", ARM::VMRS_FPSID)
5552 .
Case(
"mvfr0", ARM::VMRS_MVFR0)
5553 .
Case(
"mvfr1", ARM::VMRS_MVFR1)
5554 .
Case(
"mvfr2", ARM::VMRS_MVFR2)
5555 .
Case(
"fpinst", ARM::VMRS_FPINST)
5556 .
Case(
"fpinst2", ARM::VMRS_FPINST2)
5566 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5569 CurDAG->getMachineNode(Opcode,
DL, MVT::i32, MVT::Other, Ops));
5578 if (SYSmValue == -1)
5581 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5582 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5585 N, CurDAG->getMachineNode(ARM::t2MRS_M,
DL, MVT::i32, MVT::Other, Ops));
5591 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
5592 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5594 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
5595 DL, MVT::i32, MVT::Other, Ops));
5599 if (SpecialReg ==
"spsr") {
5600 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5603 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
DL,
5604 MVT::i32, MVT::Other, Ops));
5614bool ARMDAGToDAGISel::tryWriteRegister(
SDNode *
N){
5615 const auto *MD = cast<MDNodeSDNode>(
N->getOperand(1));
5616 const auto *RegString = cast<MDString>(MD->getMD()->getOperand(0));
5617 bool IsThumb2 = Subtarget->
isThumb2();
5620 std::vector<SDValue> Ops;
5629 if (Ops.size() == 5) {
5630 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
5631 Ops.insert(Ops.begin()+2,
N->getOperand(2));
5633 assert(Ops.size() == 3 &&
5634 "Invalid number of fields in special register string.");
5635 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
5636 SDValue WriteValue[] = {
N->getOperand(2),
N->getOperand(3) };
5637 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
5640 Ops.push_back(
getAL(CurDAG,
DL));
5641 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5642 Ops.push_back(
N->getOperand(0));
5644 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other, Ops));
5648 std::string SpecialReg = RegString->getString().lower();
5650 if (BankedReg != -1) {
5651 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
N->getOperand(2),
5652 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5655 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
5656 DL, MVT::Other, Ops));
5664 .
Case(
"fpscr", ARM::VMSR)
5665 .
Case(
"fpexc", ARM::VMSR_FPEXC)
5666 .
Case(
"fpsid", ARM::VMSR_FPSID)
5667 .
Case(
"fpinst", ARM::VMSR_FPINST)
5668 .
Case(
"fpinst2", ARM::VMSR_FPINST2)
5674 Ops = {
N->getOperand(2),
getAL(CurDAG,
DL),
5675 CurDAG->getRegister(0, MVT::i32),
N->getOperand(0) };
5676 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other, Ops));
5680 std::pair<StringRef, StringRef> Fields;
5682 std::string
Reg = Fields.first.str();
5689 if (SYSmValue == -1)
5692 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5693 N->getOperand(2),
getAL(CurDAG,
DL),
5694 CurDAG->getRegister(0, MVT::i32),
N->getOperand(0) };
5695 ReplaceNode(
N, CurDAG->getMachineNode(ARM::t2MSR_M,
DL, MVT::Other, Ops));
5704 Ops = { CurDAG->getTargetConstant(Mask,
DL, MVT::i32),
N->getOperand(2),
5705 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5707 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
5708 DL, MVT::Other, Ops));
5715bool ARMDAGToDAGISel::tryInlineAsm(
SDNode *
N){
5716 std::vector<SDValue> AsmNodeOperands;
5718 bool Changed =
false;
5719 unsigned NumOps =
N->getNumOperands();
5734 for(
unsigned i = 0, e =
N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
5736 AsmNodeOperands.push_back(
op);
5741 if (
const auto *
C = dyn_cast<ConstantSDNode>(
N->getOperand(i)))
5750 if (
Flag.isImmKind()) {
5752 AsmNodeOperands.push_back(
op);
5756 const unsigned NumRegs =
Flag.getNumOperandRegisters();
5760 unsigned DefIdx = 0;
5761 bool IsTiedToChangedOp =
false;
5764 if (Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
5765 IsTiedToChangedOp = OpChanged[DefIdx];
5772 if (
Flag.isMemKind()) {
5774 AsmNodeOperands.push_back(
op);
5778 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
5779 !
Flag.isRegDefEarlyClobberKind())
5783 const bool HasRC =
Flag.hasRegClassConstraint(RC);
5784 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
5788 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
5791 Register Reg0 = cast<RegisterSDNode>(V0)->getReg();
5792 Register Reg1 = cast<RegisterSDNode>(V1)->getReg();
5796 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
5800 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5801 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5804 SDNode *GU =
N->getGluedUser();
5805 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
5809 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
5811 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
5813 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
5819 Ops.push_back(
T1.getValue(1));
5820 CurDAG->UpdateNodeOperands(GU, Ops);
5827 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
5829 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
5835 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5836 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5837 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair,
T1.getValue(1));
5846 OpChanged[OpChanged.
size() -1 ] =
true;
5848 if (IsTiedToChangedOp)
5849 Flag.setMatchingOp(DefIdx);
5851 Flag.setRegClass(ARM::GPRPairRegClassID);
5853 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
5854 Flag, dl, MVT::i32);
5856 AsmNodeOperands.push_back(PairedReg);
5863 AsmNodeOperands.push_back(Glue);
5868 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
5870 ReplaceNode(
N,
New.getNode());
5874bool ARMDAGToDAGISel::SelectInlineAsmMemoryOperand(
5876 std::vector<SDValue> &OutOps) {
5877 switch(ConstraintID) {
5880 case InlineAsm::ConstraintCode::m:
5881 case InlineAsm::ConstraintCode::o:
5882 case InlineAsm::ConstraintCode::Q:
5883 case InlineAsm::ConstraintCode::Um:
5884 case InlineAsm::ConstraintCode::Un:
5885 case InlineAsm::ConstraintCode::Uq:
5886 case InlineAsm::ConstraintCode::Us:
5887 case InlineAsm::ConstraintCode::Ut:
5888 case InlineAsm::ConstraintCode::Uv:
5889 case InlineAsm::ConstraintCode::Uy:
5893 OutOps.push_back(
Op);
5904 return new ARMDAGToDAGISelLegacy(TM, OptLevel);
unsigned const MachineRegisterInfo * MRI
static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)
amdgpu AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
static unsigned getVectorShuffleOpcode(EVT VT, unsigned Opc64[3], unsigned Opc128[3])
static int getBankedRegisterMask(StringRef RegString)
static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs)
Returns true if the given increment is a Constant known to be equal to the access size performed by a...
static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc)
static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned &Imm)
static bool isVSTfixed(unsigned Opc)
static bool isVLDfixed(unsigned Opc)
static bool isInt32Immediate(SDNode *N, unsigned &Imm)
isInt32Immediate - This method tests to see if the node is a 32-bit constant operand.
static std::optional< std::pair< unsigned, unsigned > > getContiguousRangeOfSetBits(const APInt &A)
static void getIntOperandsFromRegisterString(StringRef RegString, SelectionDAG *CurDAG, const SDLoc &DL, std::vector< SDValue > &Ops)
static int getARClassRegisterMask(StringRef Reg, StringRef Flags)
static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget)
static cl::opt< bool > DisableShifterOp("disable-shifter-op", cl::Hidden, cl::desc("Disable isel of shifter-op"), cl::init(false))
static SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl)
getAL - Returns a ARMCC::AL immediate node.
static bool shouldUseZeroOffsetLdSt(SDValue N)
static int getMClassFlagsMask(StringRef Flags)
static bool SDValueToConstBool(SDValue SDVal)
static bool isScaledConstantInRange(SDValue Node, int Scale, int RangeMin, int RangeMax, int &ScaledConstant)
Check whether a particular node is a constant value representable as (N * Scale) where (N in [RangeMi...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
This file describes how to lower LLVM code to machine code.
support::ulittle16_t & Lo
support::ulittle16_t & Hi
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
An arbitrary precision integer that knows its signedness.
bool isThumb1Only() const
bool hasFPARMv8Base() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getZExtValue() const
This class represents an Operation in the Expression.
Container class for subtarget features.
FunctionPass class - This class is used to implement most global optimizations.
This class is used to form a handle around another node that is persistent and is updated across invo...
Base class for LoadSDNode and StoreSDNode.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
Describe properties that are true of each instruction in the target description file.
bool mayStore() const
Return true if this instruction could possibly modify memory.
unsigned getOpcode() const
Return the opcode number for this descriptor.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
An SDNode that represents everything that will be needed to construct a MachineInstr.
This class is used to represent an MLOAD node.
This is an abstract virtual class for memory operations.
EVT getMemoryVT() const
Return the type of the in-memory value.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
int getNodeId() const
Return the unique node id.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
op_iterator op_end() const
op_iterator op_begin() const
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.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual bool ComplexPatternFuncMutatesDAG() const
Return true if complex patterns for this target can mutate the DAG.
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...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
StringRef - 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.
std::string lower() const
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
float getFPImmFloat(unsigned Imm)
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset)
getAM5Opc - This function encodes the addrmode5 opc field.
unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset)
getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ 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...
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ 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...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ 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 ...
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ 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...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
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...
FunctionPass * createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOptLevel OptLevel)
createARMISelDag - This pass converts a legalized DAG into a ARM-specific DAG, ready for instruction ...
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...
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
CodeGenOptLevel
Code generation optimization level.
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ And
Bitwise or logical AND of integers.
@ NearestTiesToEven
roundTiesToEven.
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
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.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
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.
bool isVector() const
Return true if this is a vector value type.
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 isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
These are IR-level optimization flags that may be propagated to SDNodes.