31#include "llvm/IR/IntrinsicsARM.h"
40#define DEBUG_TYPE "arm-isel"
41#define PASS_NAME "ARM Instruction Selection"
45 cl::desc(
"Disable isel of shifter-op"),
60 ARMDAGToDAGISel() =
delete;
65 bool runOnMachineFunction(MachineFunction &MF)
override {
72 void PreprocessISelDAG()
override;
76 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &dl) {
77 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
80 void Select(SDNode *
N)
override;
84 bool ComplexPatternFuncMutatesDAG()
const override {
return true; }
86 bool hasNoVMLxHazardUse(SDNode *
N)
const;
87 bool isShifterOpProfitable(
const SDValue &Shift,
91 bool CheckProfitability =
true);
93 SDValue &
B,
bool CheckProfitability =
true);
97 return SelectRegShifterOperand(
N,
A,
B,
C,
false);
101 return SelectImmShifterOperand(
N,
A,
B,
false);
106 return SelectImmShifterOperand(
N,
A,
B,
false);
114 bool SelectAddrMode2OffsetReg(SDNode *
Op,
SDValue N,
116 bool SelectAddrMode2OffsetImm(SDNode *
Op,
SDValue N,
118 bool SelectAddrMode2OffsetImmPre(SDNode *
Op,
SDValue N,
123 bool SelectAddrMode3Offset(SDNode *
Op,
SDValue N,
145 template <
unsigned Shift>
150 template <
unsigned Shift>
154 bool SelectT2AddrModeImm8Offset(SDNode *
Op,
SDValue N,
156 template <
unsigned Shift>
160 template <
unsigned Shift>
166 template<
int Min,
int Max>
169 inline bool is_so_imm(
unsigned Imm)
const {
173 inline bool is_so_imm_not(
unsigned Imm)
const {
177 inline bool is_t2_so_imm(
unsigned Imm)
const {
181 inline bool is_t2_so_imm_not(
unsigned Imm)
const {
186#include "ARMGenDAGISel.inc"
189 void transferMemOperands(SDNode *Src, SDNode *Dst);
192 bool tryARMIndexedLoad(SDNode *
N);
193 bool tryT1IndexedLoad(SDNode *
N);
194 bool tryT2IndexedLoad(SDNode *
N);
195 bool tryMVEIndexedLoad(SDNode *
N);
196 bool tryFMULFixed(SDNode *
N, SDLoc dl);
197 bool tryFP_TO_INT(SDNode *
N, SDLoc dl);
198 bool transformFixedFloatingPointConversion(SDNode *
N, SDNode *
FMul,
206 void SelectVLD(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
207 const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
208 const uint16_t *QOpcodes1);
214 void SelectVST(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
215 const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
216 const uint16_t *QOpcodes1);
221 void SelectVLDSTLane(SDNode *
N,
bool IsLoad,
bool isUpdating,
222 unsigned NumVecs,
const uint16_t *DOpcodes,
223 const uint16_t *QOpcodes);
226 template <
typename SDValueVector>
227 void AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
229 template <
typename SDValueVector>
230 void AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
233 template <
typename SDValueVector>
234 void AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc);
235 template <
typename SDValueVector>
236 void AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc, EVT InactiveTy);
239 void SelectMVE_WB(SDNode *
N,
const uint16_t *Opcodes,
bool Predicated);
242 void SelectMVE_LongShift(SDNode *
N, uint16_t Opcode,
bool Immediate,
243 bool HasSaturationOperand);
246 void SelectMVE_VADCSBC(SDNode *
N, uint16_t OpcodeWithCarry,
261 void SelectBaseMVE_VMLLDAV(SDNode *
N,
bool Predicated,
262 const uint16_t *OpcodesS,
const uint16_t *OpcodesU,
263 size_t Stride,
size_t TySize);
267 void SelectMVE_VMLLDAV(SDNode *
N,
bool Predicated,
const uint16_t *OpcodesS,
268 const uint16_t *OpcodesU);
271 void SelectMVE_VRMLLDAVH(SDNode *
N,
bool Predicated,
const uint16_t *OpcodesS,
272 const uint16_t *OpcodesU);
279 void SelectMVE_VLD(SDNode *
N,
unsigned NumVecs,
280 const uint16_t *
const *Opcodes,
bool HasWriteback);
284 void SelectMVE_VxDUP(SDNode *
N,
const uint16_t *Opcodes,
293 void SelectCDE_CXxD(SDNode *
N, uint16_t Opcode,
size_t NumExtraOps,
299 void SelectVLDDup(SDNode *
N,
bool IsIntrinsic,
bool isUpdating,
300 unsigned NumVecs,
const uint16_t *DOpcodes,
301 const uint16_t *QOpcodes0 =
nullptr,
302 const uint16_t *QOpcodes1 =
nullptr);
305 bool tryV6T2BitfieldExtractOp(SDNode *
N,
bool isSigned);
307 bool tryInsertVectorElt(SDNode *
N);
309 bool tryShiftAmountMod(SDNode *
N);
311 bool tryReadRegister(SDNode *
N);
312 bool tryWriteRegister(SDNode *
N);
314 bool tryInlineAsm(SDNode *
N);
316 void SelectCMPZ(SDNode *
N,
bool &SwitchEQNEToPLMI);
318 void SelectCMP_SWAP(SDNode *
N);
322 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
324 std::vector<SDValue> &OutOps)
override;
338 SDValue GetVLDSTAlign(
SDValue Align,
const SDLoc &dl,
unsigned NumVecs,
346 bool canExtractShiftFromMul(
const SDValue &
N,
unsigned MaxShift,
347 unsigned &PowerOfTwo,
SDValue &NewMulConst)
const;
357 ARMDAGToDAGISelLegacy(ARMBaseTargetMachine &tm,
CodeGenOptLevel OptLevel)
358 : SelectionDAGISelLegacy(
359 ID, std::make_unique<ARMDAGToDAGISel>(tm, OptLevel)) {}
363char ARMDAGToDAGISelLegacy::ID = 0;
370 if (
N->getOpcode() ==
ISD::Constant &&
N->getValueType(0) == MVT::i32) {
371 Imm = N->getAsZExtVal();
387 return N->getOpcode() ==
Opc &&
396 int RangeMin,
int RangeMax,
397 int &ScaledConstant) {
398 assert(Scale > 0 &&
"Invalid scale!");
405 ScaledConstant = (int)
C->getZExtValue();
406 if ((ScaledConstant % Scale) != 0)
409 ScaledConstant /= Scale;
410 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
413void ARMDAGToDAGISel::PreprocessISelDAG() {
414 if (!Subtarget->hasV6T2Ops())
417 bool isThumb2 = Subtarget->isThumb();
434 unsigned And_imm = 0;
444 if (TZ != 1 && TZ != 2)
456 if (And_imm & (And_imm + 1))
461 unsigned Srl_imm = 0;
472 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
475 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
476 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
481 Srl = CurDAG->getNode(
ISD::SRL, SDLoc(Srl), MVT::i32,
483 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
485 N1 = CurDAG->getNode(
ISD::AND, SDLoc(N1), MVT::i32,
487 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
488 N1 = CurDAG->getNode(
ISD::SHL, SDLoc(N1), MVT::i32,
489 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
490 CurDAG->UpdateNodeOperands(&
N, N0, N1);
497bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *
N)
const {
498 if (OptLevel == CodeGenOptLevel::None)
501 if (!Subtarget->hasVMLxHazards())
507 SDNode *
User = *
N->user_begin();
510 if (
User->isMachineOpcode()) {
511 const ARMBaseInstrInfo *
TII =
static_cast<const ARMBaseInstrInfo *
>(
512 CurDAG->getSubtarget().getInstrInfo());
514 const MCInstrDesc &MCID =
TII->get(
User->getMachineOpcode());
518 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
533 return TII->isFpMLxInstruction(Opcode);
539bool ARMDAGToDAGISel::isShifterOpProfitable(
const SDValue &Shift,
548 (ShAmt == 2 || (Subtarget->
isSwift() && ShAmt == 1));
551bool ARMDAGToDAGISel::canExtractShiftFromMul(
const SDValue &
N,
553 unsigned &PowerOfTwo,
560 if (!
N.hasOneUse())
return false;
563 if (!MulConst)
return false;
566 if (!MulConst->
hasOneUse())
return false;
568 if (MulConstVal == 0)
return false;
571 PowerOfTwo = MaxShift;
572 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
574 if (PowerOfTwo == 0)
return false;
578 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
579 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(
N), MVT::i32);
582 return NewCost < OldCost;
586 CurDAG->RepositionNode(
N.getNode()->getIterator(),
M.getNode());
590bool ARMDAGToDAGISel::SelectImmShifterOperand(
SDValue N,
593 bool CheckProfitability) {
600 unsigned PowerOfTwo = 0;
602 if (canExtractShiftFromMul(
N, 31, PowerOfTwo, NewMulConst)) {
603 HandleSDNode Handle(
N);
605 replaceDAGValue(
N.getOperand(1), NewMulConst);
607 Opc = CurDAG->getTargetConstant(
620 unsigned ShImmVal = 0;
622 if (!
RHS)
return false;
623 ShImmVal =
RHS->getZExtValue() & 31;
629bool ARMDAGToDAGISel::SelectRegShifterOperand(
SDValue N,
633 bool CheckProfitability) {
644 unsigned ShImmVal = 0;
646 if (
RHS)
return false;
649 if (CheckProfitability && !isShifterOpProfitable(
N, ShOpcVal, ShImmVal))
658bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent,
SDValue N,
SDValue &Out) {
661 return CurDAG->haveNoCommonBitsSet(
N, Parent->
getOperand(1));
665bool ARMDAGToDAGISel::SelectAddrModeImm12(
SDValue N,
672 !CurDAG->isBaseWithConstantOffset(
N)) {
676 Base = CurDAG->getTargetFrameIndex(
677 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
678 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
682 if (
N.getOpcode() == ARMISD::Wrapper &&
686 Base =
N.getOperand(0);
689 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
694 int RHSC = (int)
RHS->getSExtValue();
698 if (RHSC > -0x1000 && RHSC < 0x1000) {
699 Base =
N.getOperand(0);
702 Base = CurDAG->getTargetFrameIndex(
703 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
705 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
712 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
724 int RHSC = (int)
RHS->getZExtValue();
733 unsigned ShAmt =
Log2_32(RHSC);
746 !CurDAG->isBaseWithConstantOffset(
N))
753 -0x1000+1, 0x1000, RHSC))
763 Base =
N.getOperand(0);
769 if (ConstantSDNode *Sh =
771 ShAmt = Sh->getZExtValue();
772 if (isShifterOpProfitable(
Offset, ShOpcVal, ShAmt))
773 Offset =
N.getOperand(1).getOperand(0);
786 N.getOperand(0).hasOneUse())) {
791 if (ConstantSDNode *Sh =
793 ShAmt = Sh->getZExtValue();
794 if (isShifterOpProfitable(
N.getOperand(0), ShOpcVal, ShAmt)) {
795 Offset =
N.getOperand(0).getOperand(0);
796 Base =
N.getOperand(1);
810 unsigned PowerOfTwo = 0;
812 if (canExtractShiftFromMul(
Offset, 31, PowerOfTwo, NewMulConst)) {
813 HandleSDNode Handle(
Offset);
814 replaceDAGValue(
Offset.getOperand(1), NewMulConst);
815 Offset = Handle.getValue();
826bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *
Op,
SDValue N,
828 unsigned Opcode =
Op->getOpcode();
845 ShAmt = Sh->getZExtValue();
846 if (isShifterOpProfitable(
N, ShOpcVal, ShAmt))
862bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *
Op,
SDValue N,
864 unsigned Opcode =
Op->getOpcode();
873 Offset = CurDAG->getRegister(0, MVT::i32);
874 Opc = CurDAG->getSignedTargetConstant(Val, SDLoc(
Op), MVT::i32);
882bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *
Op,
SDValue N,
884 unsigned Opcode =
Op->getOpcode();
892 Offset = CurDAG->getRegister(0, MVT::i32);
895 SDLoc(
Op), MVT::i32);
907bool ARMDAGToDAGISel::SelectAddrMode3(
SDValue N,
912 Base =
N.getOperand(0);
919 if (!CurDAG->isBaseWithConstantOffset(
N)) {
923 Base = CurDAG->getTargetFrameIndex(
924 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
926 Offset = CurDAG->getRegister(0, MVT::i32);
935 -256 + 1, 256, RHSC)) {
936 Base =
N.getOperand(0);
939 Base = CurDAG->getTargetFrameIndex(
940 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
942 Offset = CurDAG->getRegister(0, MVT::i32);
954 Base =
N.getOperand(0);
961bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *
Op,
SDValue N,
963 unsigned Opcode =
Op->getOpcode();
971 Offset = CurDAG->getRegister(0, MVT::i32);
985 if (!CurDAG->isBaseWithConstantOffset(
N)) {
989 Base = CurDAG->getTargetFrameIndex(
990 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
991 }
else if (
N.getOpcode() == ARMISD::Wrapper &&
995 Base =
N.getOperand(0);
1004 const int Scale = FP16 ? 2 : 4;
1007 Base =
N.getOperand(0);
1010 Base = CurDAG->getTargetFrameIndex(
1011 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1022 SDLoc(
N), MVT::i32);
1025 SDLoc(
N), MVT::i32);
1034 SDLoc(
N), MVT::i32);
1037 SDLoc(
N), MVT::i32);
1042bool ARMDAGToDAGISel::SelectAddrMode5(
SDValue N,
1047bool ARMDAGToDAGISel::SelectAddrMode5FP16(
SDValue N,
1052bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent,
SDValue N,
SDValue &Addr,
1056 unsigned Alignment = 0;
1066 llvm::Align MMOAlign = MemN->
getAlign();
1068 if (MMOAlign.
value() >= MemSize && MemSize > 1)
1069 Alignment = MemSize;
1077 Align = CurDAG->getTargetConstant(Alignment, SDLoc(
N), MVT::i32);
1081bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *
Op,
SDValue N,
1090 Offset = CurDAG->getRegister(0, MVT::i32);
1095bool ARMDAGToDAGISel::SelectAddrModePC(
SDValue N,
1097 if (
N.getOpcode() == ARMISD::PIC_ADD &&
N.hasOneUse()) {
1121 return C->getSExtValue() < 0 &&
C->getSExtValue() >= -255;
1128 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N)) {
1136 Base =
N.getOperand(0);
1145 return SelectThumbAddrModeRRSext(
N,
Base,
Offset);
1149ARMDAGToDAGISel::SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
1153 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1157 if (!CurDAG->isBaseWithConstantOffset(
N)) {
1160 }
else if (
N.getOpcode() == ARMISD::Wrapper &&
1165 Base =
N.getOperand(0);
1170 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1177 Base =
N.getOperand(0);
1178 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1189 return SelectThumbAddrModeImm5S(
N, 4,
Base, OffImm);
1195 return SelectThumbAddrModeImm5S(
N, 2,
Base, OffImm);
1201 return SelectThumbAddrModeImm5S(
N, 1,
Base, OffImm);
1204bool ARMDAGToDAGISel::SelectThumbAddrModeSP(
SDValue N,
1210 MachineFrameInfo &MFI = MF->getFrameInfo();
1213 Base = CurDAG->getTargetFrameIndex(
1214 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1215 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1219 if (!CurDAG->isBaseWithConstantOffset(
N))
1226 Base =
N.getOperand(0);
1231 MachineFrameInfo &MFI = MF->getFrameInfo();
1238 Base = CurDAG->getTargetFrameIndex(
1239 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1240 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1250template <
unsigned Shift>
1253 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1257 Base =
N.getOperand(0);
1260 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1268 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1278bool ARMDAGToDAGISel::SelectT2AddrModeImm12(
SDValue N,
1284 !CurDAG->isBaseWithConstantOffset(
N)) {
1288 Base = CurDAG->getTargetFrameIndex(
1289 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1290 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1294 if (
N.getOpcode() == ARMISD::Wrapper &&
1298 Base =
N.getOperand(0);
1303 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1308 if (SelectT2AddrModeImm8(
N,
Base, OffImm))
1312 int RHSC = (int)
RHS->getZExtValue();
1316 if (RHSC >= 0 && RHSC < 0x1000) {
1317 Base =
N.getOperand(0);
1320 Base = CurDAG->getTargetFrameIndex(
1321 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1323 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1330 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1334template <
unsigned Shift>
1337 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1340 Base =
N.getOperand(0);
1343 Base = CurDAG->getTargetFrameIndex(
1344 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1349 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1357 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1361bool ARMDAGToDAGISel::SelectT2AddrModeImm8(
SDValue N,
1365 !CurDAG->isBaseWithConstantOffset(
N))
1369 int RHSC = (int)
RHS->getSExtValue();
1373 if ((RHSC >= -255) && (RHSC < 0)) {
1374 Base =
N.getOperand(0);
1377 Base = CurDAG->getTargetFrameIndex(
1378 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1380 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1388bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *
Op,
SDValue N,
1390 unsigned Opcode =
Op->getOpcode();
1397 ? CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32)
1398 : CurDAG->getSignedTargetConstant(-RHSC, SDLoc(
N), MVT::i32);
1405template <
unsigned Shift>
1408 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1412 Base =
N.getOperand(0);
1415 Base = CurDAG->getTargetFrameIndex(
1416 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1421 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1429 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1433template <
unsigned Shift>
1434bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *
Op,
SDValue N,
1436 return SelectT2AddrModeImm7Offset(
Op,
N, OffImm, Shift);
1439bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *
Op,
SDValue N,
1442 unsigned Opcode =
Op->getOpcode();
1465 ? CurDAG->getSignedTargetConstant(RHSC * (1 << Shift),
1467 : CurDAG->getSignedTargetConstant(-RHSC * (1 << Shift),
1468 SDLoc(
N), MVT::i32);
1474template <
int Min,
int Max>
1475bool ARMDAGToDAGISel::SelectImmediateInRange(
SDValue N,
SDValue &OffImm) {
1478 OffImm = CurDAG->getSignedTargetConstant(Val, SDLoc(
N), MVT::i32);
1484bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(
SDValue N,
1488 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N))
1493 int RHSC = (int)
RHS->getZExtValue();
1494 if (RHSC >= 0 && RHSC < 0x1000)
1496 else if (RHSC < 0 && RHSC >= -255)
1502 Base =
N.getOperand(0);
1517 ShAmt = Sh->getZExtValue();
1518 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1529 unsigned PowerOfTwo = 0;
1531 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1532 HandleSDNode Handle(OffReg);
1533 replaceDAGValue(OffReg.
getOperand(1), NewMulConst);
1539 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(
N), MVT::i32);
1549 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1551 if (
N.getOpcode() !=
ISD::ADD || !CurDAG->isBaseWithConstantOffset(
N))
1558 uint32_t RHSC = (int)
RHS->getZExtValue();
1559 if (RHSC > 1020 || RHSC % 4 != 0)
1562 Base =
N.getOperand(0);
1565 Base = CurDAG->getTargetFrameIndex(
1566 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1569 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(
N), MVT::i32);
1580void ARMDAGToDAGISel::transferMemOperands(SDNode *
N, SDNode *Result) {
1585bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *
N) {
1591 EVT LoadedVT =
LD->getMemoryVT();
1594 unsigned Opcode = 0;
1596 if (LoadedVT == MVT::i32 && isPre &&
1597 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1598 Opcode = ARM::LDR_PRE_IMM;
1600 }
else if (LoadedVT == MVT::i32 && !isPre &&
1601 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1602 Opcode = ARM::LDR_POST_IMM;
1604 }
else if (LoadedVT == MVT::i32 &&
1605 SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1606 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1609 }
else if (LoadedVT == MVT::i16 &&
1610 SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1613 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1614 : (isPre ?
ARM::LDRH_PRE :
ARM::LDRH_POST);
1615 }
else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
1617 if (SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1619 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1623 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1625 Opcode = ARM::LDRB_PRE_IMM;
1626 }
else if (!isPre &&
1627 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1629 Opcode = ARM::LDRB_POST_IMM;
1630 }
else if (SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1632 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1638 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1642 CurDAG->getRegister(0, MVT::i32), Chain };
1643 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1645 transferMemOperands(
N, New);
1646 ReplaceNode(
N, New);
1652 CurDAG->getRegister(0, MVT::i32), Chain };
1653 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1655 transferMemOperands(
N, New);
1656 ReplaceNode(
N, New);
1664bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *
N) {
1666 EVT LoadedVT =
LD->getMemoryVT();
1673 if (!COffs || COffs->getZExtValue() != 4)
1683 CurDAG->getRegister(0, MVT::i32), Chain };
1684 SDNode *
New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(
N), MVT::i32,
1685 MVT::i32, MVT::Other,
Ops);
1686 transferMemOperands(
N, New);
1687 ReplaceNode(
N, New);
1691bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *
N) {
1697 EVT LoadedVT =
LD->getMemoryVT();
1701 unsigned Opcode = 0;
1703 if (SelectT2AddrModeImm8Offset(
N,
LD->getOffset(),
Offset)) {
1706 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1710 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1712 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1717 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1719 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1731 CurDAG->getRegister(0, MVT::i32), Chain };
1732 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1734 transferMemOperands(
N, New);
1735 ReplaceNode(
N, New);
1742bool ARMDAGToDAGISel::tryMVEIndexedLoad(SDNode *
N) {
1744 unsigned Opcode = 0;
1745 bool isSExtLd, isPre;
1755 LoadedVT =
LD->getMemoryVT();
1759 Chain =
LD->getChain();
1762 Alignment =
LD->getAlign();
1766 PredReg = CurDAG->getRegister(0, MVT::i32);
1771 LoadedVT =
LD->getMemoryVT();
1775 Chain =
LD->getChain();
1778 Alignment =
LD->getAlign();
1782 PredReg =
LD->getMask();
1792 if (Alignment >=
Align(2) && LoadedVT == MVT::v4i16 &&
1793 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1)) {
1795 Opcode = isPre ? ARM::MVE_VLDRHS32_pre : ARM::MVE_VLDRHS32_post;
1797 Opcode = isPre ? ARM::MVE_VLDRHU32_pre : ARM::MVE_VLDRHU32_post;
1798 }
else if (LoadedVT == MVT::v8i8 &&
1799 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1801 Opcode = isPre ? ARM::MVE_VLDRBS16_pre : ARM::MVE_VLDRBS16_post;
1803 Opcode = isPre ? ARM::MVE_VLDRBU16_pre : ARM::MVE_VLDRBU16_post;
1804 }
else if (LoadedVT == MVT::v4i8 &&
1805 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1807 Opcode = isPre ? ARM::MVE_VLDRBS32_pre : ARM::MVE_VLDRBS32_post;
1809 Opcode = isPre ? ARM::MVE_VLDRBU32_pre : ARM::MVE_VLDRBU32_post;
1810 }
else if (Alignment >=
Align(4) &&
1811 (CanChangeType || LoadedVT == MVT::v4i32 ||
1812 LoadedVT == MVT::v4f32) &&
1813 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 2))
1814 Opcode = isPre ? ARM::MVE_VLDRWU32_pre : ARM::MVE_VLDRWU32_post;
1815 else if (Alignment >=
Align(2) &&
1816 (CanChangeType || LoadedVT == MVT::v8i16 ||
1817 LoadedVT == MVT::v8f16) &&
1818 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1))
1819 Opcode = isPre ? ARM::MVE_VLDRHU16_pre : ARM::MVE_VLDRHU16_post;
1820 else if ((CanChangeType || LoadedVT == MVT::v16i8) &&
1821 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0))
1822 Opcode = isPre ? ARM::MVE_VLDRBU8_pre : ARM::MVE_VLDRBU8_post;
1828 CurDAG->getTargetConstant(Pred, SDLoc(
N), MVT::i32),
1830 CurDAG->getRegister(0, MVT::i32),
1832 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32,
1833 N->getValueType(0), MVT::Other,
Ops);
1834 transferMemOperands(
N, New);
1838 CurDAG->RemoveDeadNode(
N);
1843SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1846 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1847 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1848 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
1849 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1850 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1854SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1857 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1858 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1859 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1860 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1861 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1865SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1867 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1869 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1870 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1871 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1872 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1876SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1878 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1880 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1881 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1882 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1883 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1887SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1891 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1892 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1893 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1894 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1895 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
1896 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1897 V2, SubReg2, V3, SubReg3 };
1898 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1902SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1905 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1907 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1908 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1909 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1910 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
1911 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1912 V2, SubReg2, V3, SubReg3 };
1913 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1917SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1920 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1922 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1923 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1924 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1925 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
1926 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1927 V2, SubReg2, V3, SubReg3 };
1928 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1934SDValue ARMDAGToDAGISel::GetVLDSTAlign(
SDValue Align,
const SDLoc &dl,
1935 unsigned NumVecs,
bool is64BitVector) {
1936 unsigned NumRegs = NumVecs;
1937 if (!is64BitVector && NumVecs < 3)
1940 unsigned Alignment =
Align->getAsZExtVal();
1941 if (Alignment >= 32 && NumRegs == 4)
1943 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1945 else if (Alignment >= 8)
1950 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
1956 default:
return false;
1957 case ARM::VLD1d8wb_fixed :
return true;
1958 case ARM::VLD1d16wb_fixed :
return true;
1959 case ARM::VLD1d64Qwb_fixed :
return true;
1960 case ARM::VLD1d32wb_fixed :
return true;
1961 case ARM::VLD1d64wb_fixed :
return true;
1962 case ARM::VLD1d8TPseudoWB_fixed :
return true;
1963 case ARM::VLD1d16TPseudoWB_fixed :
return true;
1964 case ARM::VLD1d32TPseudoWB_fixed :
return true;
1965 case ARM::VLD1d64TPseudoWB_fixed :
return true;
1966 case ARM::VLD1d8QPseudoWB_fixed :
return true;
1967 case ARM::VLD1d16QPseudoWB_fixed :
return true;
1968 case ARM::VLD1d32QPseudoWB_fixed :
return true;
1969 case ARM::VLD1d64QPseudoWB_fixed :
return true;
1970 case ARM::VLD1q8wb_fixed :
return true;
1971 case ARM::VLD1q16wb_fixed :
return true;
1972 case ARM::VLD1q32wb_fixed :
return true;
1973 case ARM::VLD1q64wb_fixed :
return true;
1974 case ARM::VLD1DUPd8wb_fixed :
return true;
1975 case ARM::VLD1DUPd16wb_fixed :
return true;
1976 case ARM::VLD1DUPd32wb_fixed :
return true;
1977 case ARM::VLD1DUPq8wb_fixed :
return true;
1978 case ARM::VLD1DUPq16wb_fixed :
return true;
1979 case ARM::VLD1DUPq32wb_fixed :
return true;
1980 case ARM::VLD2d8wb_fixed :
return true;
1981 case ARM::VLD2d16wb_fixed :
return true;
1982 case ARM::VLD2d32wb_fixed :
return true;
1983 case ARM::VLD2q8PseudoWB_fixed :
return true;
1984 case ARM::VLD2q16PseudoWB_fixed :
return true;
1985 case ARM::VLD2q32PseudoWB_fixed :
return true;
1986 case ARM::VLD2DUPd8wb_fixed :
return true;
1987 case ARM::VLD2DUPd16wb_fixed :
return true;
1988 case ARM::VLD2DUPd32wb_fixed :
return true;
1989 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return true;
1990 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return true;
1991 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return true;
1998 default:
return false;
1999 case ARM::VST1d8wb_fixed :
return true;
2000 case ARM::VST1d16wb_fixed :
return true;
2001 case ARM::VST1d32wb_fixed :
return true;
2002 case ARM::VST1d64wb_fixed :
return true;
2003 case ARM::VST1q8wb_fixed :
return true;
2004 case ARM::VST1q16wb_fixed :
return true;
2005 case ARM::VST1q32wb_fixed :
return true;
2006 case ARM::VST1q64wb_fixed :
return true;
2007 case ARM::VST1d8TPseudoWB_fixed :
return true;
2008 case ARM::VST1d16TPseudoWB_fixed :
return true;
2009 case ARM::VST1d32TPseudoWB_fixed :
return true;
2010 case ARM::VST1d64TPseudoWB_fixed :
return true;
2011 case ARM::VST1d8QPseudoWB_fixed :
return true;
2012 case ARM::VST1d16QPseudoWB_fixed :
return true;
2013 case ARM::VST1d32QPseudoWB_fixed :
return true;
2014 case ARM::VST1d64QPseudoWB_fixed :
return true;
2015 case ARM::VST2d8wb_fixed :
return true;
2016 case ARM::VST2d16wb_fixed :
return true;
2017 case ARM::VST2d32wb_fixed :
return true;
2018 case ARM::VST2q8PseudoWB_fixed :
return true;
2019 case ARM::VST2q16PseudoWB_fixed :
return true;
2020 case ARM::VST2q32PseudoWB_fixed :
return true;
2028 &&
"Incorrect fixed stride updating instruction.");
2031 case ARM::VLD1d8wb_fixed:
return ARM::VLD1d8wb_register;
2032 case ARM::VLD1d16wb_fixed:
return ARM::VLD1d16wb_register;
2033 case ARM::VLD1d32wb_fixed:
return ARM::VLD1d32wb_register;
2034 case ARM::VLD1d64wb_fixed:
return ARM::VLD1d64wb_register;
2035 case ARM::VLD1q8wb_fixed:
return ARM::VLD1q8wb_register;
2036 case ARM::VLD1q16wb_fixed:
return ARM::VLD1q16wb_register;
2037 case ARM::VLD1q32wb_fixed:
return ARM::VLD1q32wb_register;
2038 case ARM::VLD1q64wb_fixed:
return ARM::VLD1q64wb_register;
2039 case ARM::VLD1d64Twb_fixed:
return ARM::VLD1d64Twb_register;
2040 case ARM::VLD1d64Qwb_fixed:
return ARM::VLD1d64Qwb_register;
2041 case ARM::VLD1d8TPseudoWB_fixed:
return ARM::VLD1d8TPseudoWB_register;
2042 case ARM::VLD1d16TPseudoWB_fixed:
return ARM::VLD1d16TPseudoWB_register;
2043 case ARM::VLD1d32TPseudoWB_fixed:
return ARM::VLD1d32TPseudoWB_register;
2044 case ARM::VLD1d64TPseudoWB_fixed:
return ARM::VLD1d64TPseudoWB_register;
2045 case ARM::VLD1d8QPseudoWB_fixed:
return ARM::VLD1d8QPseudoWB_register;
2046 case ARM::VLD1d16QPseudoWB_fixed:
return ARM::VLD1d16QPseudoWB_register;
2047 case ARM::VLD1d32QPseudoWB_fixed:
return ARM::VLD1d32QPseudoWB_register;
2048 case ARM::VLD1d64QPseudoWB_fixed:
return ARM::VLD1d64QPseudoWB_register;
2049 case ARM::VLD1DUPd8wb_fixed :
return ARM::VLD1DUPd8wb_register;
2050 case ARM::VLD1DUPd16wb_fixed :
return ARM::VLD1DUPd16wb_register;
2051 case ARM::VLD1DUPd32wb_fixed :
return ARM::VLD1DUPd32wb_register;
2052 case ARM::VLD1DUPq8wb_fixed :
return ARM::VLD1DUPq8wb_register;
2053 case ARM::VLD1DUPq16wb_fixed :
return ARM::VLD1DUPq16wb_register;
2054 case ARM::VLD1DUPq32wb_fixed :
return ARM::VLD1DUPq32wb_register;
2055 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return ARM::VLD2DUPq8OddPseudoWB_register;
2056 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return ARM::VLD2DUPq16OddPseudoWB_register;
2057 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return ARM::VLD2DUPq32OddPseudoWB_register;
2059 case ARM::VST1d8wb_fixed:
return ARM::VST1d8wb_register;
2060 case ARM::VST1d16wb_fixed:
return ARM::VST1d16wb_register;
2061 case ARM::VST1d32wb_fixed:
return ARM::VST1d32wb_register;
2062 case ARM::VST1d64wb_fixed:
return ARM::VST1d64wb_register;
2063 case ARM::VST1q8wb_fixed:
return ARM::VST1q8wb_register;
2064 case ARM::VST1q16wb_fixed:
return ARM::VST1q16wb_register;
2065 case ARM::VST1q32wb_fixed:
return ARM::VST1q32wb_register;
2066 case ARM::VST1q64wb_fixed:
return ARM::VST1q64wb_register;
2067 case ARM::VST1d8TPseudoWB_fixed:
return ARM::VST1d8TPseudoWB_register;
2068 case ARM::VST1d16TPseudoWB_fixed:
return ARM::VST1d16TPseudoWB_register;
2069 case ARM::VST1d32TPseudoWB_fixed:
return ARM::VST1d32TPseudoWB_register;
2070 case ARM::VST1d64TPseudoWB_fixed:
return ARM::VST1d64TPseudoWB_register;
2071 case ARM::VST1d8QPseudoWB_fixed:
return ARM::VST1d8QPseudoWB_register;
2072 case ARM::VST1d16QPseudoWB_fixed:
return ARM::VST1d16QPseudoWB_register;
2073 case ARM::VST1d32QPseudoWB_fixed:
return ARM::VST1d32QPseudoWB_register;
2074 case ARM::VST1d64QPseudoWB_fixed:
return ARM::VST1d64QPseudoWB_register;
2076 case ARM::VLD2d8wb_fixed:
return ARM::VLD2d8wb_register;
2077 case ARM::VLD2d16wb_fixed:
return ARM::VLD2d16wb_register;
2078 case ARM::VLD2d32wb_fixed:
return ARM::VLD2d32wb_register;
2079 case ARM::VLD2q8PseudoWB_fixed:
return ARM::VLD2q8PseudoWB_register;
2080 case ARM::VLD2q16PseudoWB_fixed:
return ARM::VLD2q16PseudoWB_register;
2081 case ARM::VLD2q32PseudoWB_fixed:
return ARM::VLD2q32PseudoWB_register;
2083 case ARM::VST2d8wb_fixed:
return ARM::VST2d8wb_register;
2084 case ARM::VST2d16wb_fixed:
return ARM::VST2d16wb_register;
2085 case ARM::VST2d32wb_fixed:
return ARM::VST2d32wb_register;
2086 case ARM::VST2q8PseudoWB_fixed:
return ARM::VST2q8PseudoWB_register;
2087 case ARM::VST2q16PseudoWB_fixed:
return ARM::VST2q16PseudoWB_register;
2088 case ARM::VST2q32PseudoWB_fixed:
return ARM::VST2q32PseudoWB_register;
2090 case ARM::VLD2DUPd8wb_fixed:
return ARM::VLD2DUPd8wb_register;
2091 case ARM::VLD2DUPd16wb_fixed:
return ARM::VLD2DUPd16wb_register;
2092 case ARM::VLD2DUPd32wb_fixed:
return ARM::VLD2DUPd32wb_register;
2105void ARMDAGToDAGISel::SelectVLD(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2106 const uint16_t *DOpcodes,
2107 const uint16_t *QOpcodes0,
2108 const uint16_t *QOpcodes1) {
2109 assert(Subtarget->hasNEON());
2110 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLD NumVecs out-of-range");
2114 bool IsIntrinsic = !isUpdating;
2116 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2117 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2121 EVT VT =
N->getValueType(0);
2123 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
2151 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2156 std::vector<EVT> ResTys;
2157 ResTys.push_back(ResTy);
2159 ResTys.push_back(MVT::i32);
2160 ResTys.push_back(MVT::Other);
2163 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2168 if (is64BitVector || NumVecs <= 2) {
2171 Ops.push_back(MemAddr);
2172 Ops.push_back(Align);
2174 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2185 Ops.push_back(Reg0);
2187 Ops.push_back(Pred);
2188 Ops.push_back(Reg0);
2189 Ops.push_back(Chain);
2190 VLd = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2200 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
2201 const SDValue OpsA[] = { MemAddr,
Align, Reg0, ImplDef, Pred, Reg0, Chain };
2202 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl,
2203 ResTy, AddrTy, MVT::Other, OpsA);
2208 Ops.push_back(Align);
2212 "only constant post-increment update allowed for VLD3/4");
2214 Ops.push_back(Reg0);
2217 Ops.push_back(Pred);
2218 Ops.push_back(Reg0);
2219 Ops.push_back(Chain);
2220 VLd = CurDAG->getMachineNode(QOpcodes1[
OpcodeIndex], dl, ResTys,
Ops);
2228 ReplaceNode(
N, VLd);
2234 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2235 ARM::qsub_3 == ARM::qsub_0 + 3,
2236 "Unexpected subreg numbering");
2237 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
2238 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2240 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2244 CurDAG->RemoveDeadNode(
N);
2247void ARMDAGToDAGISel::SelectVST(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2248 const uint16_t *DOpcodes,
2249 const uint16_t *QOpcodes0,
2250 const uint16_t *QOpcodes1) {
2251 assert(Subtarget->hasNEON());
2252 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VST NumVecs out-of-range");
2256 bool IsIntrinsic = !isUpdating;
2258 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2259 unsigned Vec0Idx = 3;
2260 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2266 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2268 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
2292 std::vector<EVT> ResTys;
2294 ResTys.push_back(MVT::i32);
2295 ResTys.push_back(MVT::Other);
2298 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2302 if (is64BitVector || NumVecs <= 2) {
2306 }
else if (is64BitVector) {
2311 SrcReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2317 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
2319 SrcReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2323 SDValue Q0 =
N->getOperand(Vec0Idx);
2324 SDValue Q1 =
N->getOperand(Vec0Idx + 1);
2325 SrcReg =
SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
2330 Ops.push_back(MemAddr);
2331 Ops.push_back(Align);
2345 Ops.push_back(Reg0);
2347 Ops.push_back(SrcReg);
2348 Ops.push_back(Pred);
2349 Ops.push_back(Reg0);
2350 Ops.push_back(Chain);
2351 SDNode *VSt = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2356 ReplaceNode(
N, VSt);
2368 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2370 SDValue RegSeq =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2374 const SDValue OpsA[] = { MemAddr,
Align, Reg0, RegSeq, Pred, Reg0, Chain };
2375 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl,
2383 Ops.push_back(Align);
2387 "only constant post-increment update allowed for VST3/4");
2389 Ops.push_back(Reg0);
2391 Ops.push_back(RegSeq);
2392 Ops.push_back(Pred);
2393 Ops.push_back(Reg0);
2394 Ops.push_back(Chain);
2395 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[
OpcodeIndex], dl, ResTys,
2398 ReplaceNode(
N, VStB);
2401void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *
N,
bool IsLoad,
bool isUpdating,
2403 const uint16_t *DOpcodes,
2404 const uint16_t *QOpcodes) {
2405 assert(Subtarget->hasNEON());
2406 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDSTLane NumVecs out-of-range");
2410 bool IsIntrinsic = !isUpdating;
2412 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2413 unsigned Vec0Idx = 3;
2414 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2421 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2424 unsigned Alignment = 0;
2426 Alignment =
Align->getAsZExtVal();
2428 if (Alignment > NumBytes)
2429 Alignment = NumBytes;
2430 if (Alignment < 8 && Alignment < NumBytes)
2433 Alignment = (Alignment & -Alignment);
2437 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
2457 std::vector<EVT> ResTys;
2459 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2463 MVT::i64, ResTyElts));
2466 ResTys.push_back(MVT::i32);
2467 ResTys.push_back(MVT::Other);
2470 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2473 Ops.push_back(MemAddr);
2474 Ops.push_back(Align);
2479 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
2487 SuperReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2489 SuperReg =
SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
2493 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2496 SuperReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2498 SuperReg =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2500 Ops.push_back(SuperReg);
2501 Ops.push_back(getI32Imm(Lane, dl));
2502 Ops.push_back(Pred);
2503 Ops.push_back(Reg0);
2504 Ops.push_back(Chain);
2508 SDNode *VLdLn = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2511 ReplaceNode(
N, VLdLn);
2517 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2518 ARM::qsub_3 == ARM::qsub_0 + 3,
2519 "Unexpected subreg numbering");
2520 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2521 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2523 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2527 CurDAG->RemoveDeadNode(
N);
2530template <
typename SDValueVector>
2531void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2533 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2534 Ops.push_back(PredicateMask);
2535 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2538template <
typename SDValueVector>
2539void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2542 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2543 Ops.push_back(PredicateMask);
2544 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2545 Ops.push_back(Inactive);
2548template <
typename SDValueVector>
2549void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc) {
2550 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2551 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2552 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2555template <
typename SDValueVector>
2556void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2558 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2559 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2560 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2562 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, InactiveTy), 0));
2565void ARMDAGToDAGISel::SelectMVE_WB(SDNode *
N,
const uint16_t *Opcodes,
2571 switch (
N->getValueType(1).getVectorElementType().getSizeInBits()) {
2573 Opcode = Opcodes[0];
2576 Opcode = Opcodes[1];
2582 Ops.push_back(
N->getOperand(2));
2584 int32_t ImmValue =
N->getConstantOperandVal(3);
2585 Ops.push_back(getI32Imm(ImmValue, Loc));
2588 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(4));
2590 AddEmptyMVEPredicateToOps(
Ops, Loc);
2592 Ops.push_back(
N->getOperand(0));
2599 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), VTs,
Ops);
2603 transferMemOperands(
N, New);
2604 CurDAG->RemoveDeadNode(
N);
2607void ARMDAGToDAGISel::SelectMVE_LongShift(SDNode *
N, uint16_t Opcode,
2609 bool HasSaturationOperand) {
2614 Ops.push_back(
N->getOperand(1));
2615 Ops.push_back(
N->getOperand(2));
2619 int32_t ImmValue =
N->getConstantOperandVal(3);
2620 Ops.push_back(getI32Imm(ImmValue, Loc));
2622 Ops.push_back(
N->getOperand(3));
2626 if (HasSaturationOperand) {
2627 int32_t SatOp =
N->getConstantOperandVal(4);
2628 int SatBit = (SatOp == 64 ? 0 : 1);
2629 Ops.push_back(getI32Imm(SatBit, Loc));
2635 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2637 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2640void ARMDAGToDAGISel::SelectMVE_VADCSBC(SDNode *
N, uint16_t OpcodeWithCarry,
2641 uint16_t OpcodeWithNoCarry,
2650 Ops.push_back(
N->getOperand(FirstInputOp));
2651 Ops.push_back(
N->getOperand(FirstInputOp + 1));
2652 SDValue CarryIn =
N->getOperand(FirstInputOp + 2);
2654 uint32_t CarryMask = 1 << 29;
2655 uint32_t CarryExpected =
Add ? 0 : CarryMask;
2656 if (CarryInConstant &&
2657 (CarryInConstant->
getZExtValue() & CarryMask) == CarryExpected) {
2658 Opcode = OpcodeWithNoCarry;
2660 Ops.push_back(CarryIn);
2661 Opcode = OpcodeWithCarry;
2665 AddMVEPredicateToOps(
Ops, Loc,
2666 N->getOperand(FirstInputOp + 3),
2667 N->getOperand(FirstInputOp - 1));
2669 AddEmptyMVEPredicateToOps(
Ops, Loc,
N->getValueType(0));
2671 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2674void ARMDAGToDAGISel::SelectMVE_VSHLC(SDNode *
N,
bool Predicated) {
2680 Ops.push_back(
N->getOperand(1));
2681 Ops.push_back(
N->getOperand(2));
2682 int32_t ImmValue =
N->getConstantOperandVal(3);
2683 Ops.push_back(getI32Imm(ImmValue, Loc));
2686 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(4));
2688 AddEmptyMVEPredicateToOps(
Ops, Loc);
2690 CurDAG->SelectNodeTo(
N, ARM::MVE_VSHLC,
N->getVTList(),
ArrayRef(
Ops));
2701void ARMDAGToDAGISel::SelectBaseMVE_VMLLDAV(SDNode *
N,
bool Predicated,
2702 const uint16_t *OpcodesS,
2703 const uint16_t *OpcodesU,
2704 size_t Stride,
size_t TySize) {
2705 assert(TySize < Stride &&
"Invalid TySize");
2711 "Unsigned versions of vmlsldav[a]/vrmlsldavh[a] do not exist");
2713 "Unsigned versions of vmlaldav[a]x/vrmlaldavh[a]x do not exist");
2716 auto OpIsZero = [
N](
size_t OpNo) {
2722 bool IsAccum = !(OpIsZero(4) && OpIsZero(5));
2724 const uint16_t *Opcodes = IsUnsigned ? OpcodesU : OpcodesS;
2726 Opcodes += 4 * Stride;
2728 Opcodes += 2 * Stride;
2731 uint16_t Opcode = Opcodes[TySize];
2737 Ops.push_back(
N->getOperand(4));
2738 Ops.push_back(
N->getOperand(5));
2741 Ops.push_back(
N->getOperand(6));
2742 Ops.push_back(
N->getOperand(7));
2745 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(8));
2747 AddEmptyMVEPredicateToOps(
Ops, Loc);
2749 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2752void ARMDAGToDAGISel::SelectMVE_VMLLDAV(SDNode *
N,
bool Predicated,
2753 const uint16_t *OpcodesS,
2754 const uint16_t *OpcodesU) {
2755 EVT VecTy =
N->getOperand(6).getValueType();
2768 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 2, SizeIndex);
2771void ARMDAGToDAGISel::SelectMVE_VRMLLDAVH(SDNode *
N,
bool Predicated,
2772 const uint16_t *OpcodesS,
2773 const uint16_t *OpcodesU) {
2775 N->getOperand(6).getValueType().getVectorElementType().getSizeInBits() ==
2777 "bad vector element size");
2778 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 1, 0);
2781void ARMDAGToDAGISel::SelectMVE_VLD(SDNode *
N,
unsigned NumVecs,
2782 const uint16_t *
const *Opcodes,
2783 bool HasWriteback) {
2784 EVT VT =
N->getValueType(0);
2787 const uint16_t *OurOpcodes;
2790 OurOpcodes = Opcodes[0];
2793 OurOpcodes = Opcodes[1];
2796 OurOpcodes = Opcodes[2];
2802 EVT DataTy =
EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, NumVecs * 2);
2804 unsigned PtrOperand = HasWriteback ? 1 : 2;
2807 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, DataTy), 0);
2810 for (
unsigned Stage = 0; Stage < NumVecs - 1; ++Stage) {
2813 CurDAG->getMachineNode(OurOpcodes[Stage], Loc, ResultTys,
Ops);
2816 transferMemOperands(
N, LoadInst);
2820 ResultTys = {DataTy, MVT::i32, MVT::Other};
2823 CurDAG->getMachineNode(OurOpcodes[NumVecs - 1], Loc, ResultTys,
Ops);
2824 transferMemOperands(
N, LoadInst);
2827 for (i = 0; i < NumVecs; i++)
2829 CurDAG->getTargetExtractSubreg(ARM::qsub_0 + i, Loc, VT,
2834 CurDAG->RemoveDeadNode(
N);
2837void ARMDAGToDAGISel::SelectMVE_VxDUP(SDNode *
N,
const uint16_t *Opcodes,
2839 EVT VT =
N->getValueType(0);
2845 Opcode = Opcodes[0];
2848 Opcode = Opcodes[1];
2851 Opcode = Opcodes[2];
2870 Ops.push_back(getI32Imm(ImmValue, Loc));
2873 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(
OpIdx), Inactive);
2875 AddEmptyMVEPredicateToOps(
Ops, Loc,
N->getValueType(0));
2877 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2880void ARMDAGToDAGISel::SelectCDE_CXxD(SDNode *
N, uint16_t Opcode,
2881 size_t NumExtraOps,
bool HasAccum) {
2882 bool IsBigEndian = CurDAG->getDataLayout().isBigEndian();
2891 Ops.push_back(getI32Imm(ImmCoprocVal, Loc));
2904 for (
size_t I = 0;
I < NumExtraOps;
I++)
2909 uint32_t ImmVal =
Imm->getAsZExtVal();
2910 Ops.push_back(getI32Imm(ImmVal, Loc));
2915 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2916 Ops.push_back(Pred);
2917 Ops.push_back(PredReg);
2921 SDNode *InstrNode = CurDAG->getMachineNode(Opcode, Loc, MVT::Untyped,
Ops);
2928 uint16_t SubRegs[2] = {ARM::gsub_0, ARM::gsub_1};
2932 for (
size_t ResIdx = 0; ResIdx < 2; ResIdx++) {
2933 if (
SDValue(
N, ResIdx).use_empty())
2935 SDValue SubReg = CurDAG->getTargetExtractSubreg(SubRegs[ResIdx], Loc,
2936 MVT::i32, ResultPair);
2937 ReplaceUses(
SDValue(
N, ResIdx), SubReg);
2940 CurDAG->RemoveDeadNode(
N);
2943void ARMDAGToDAGISel::SelectVLDDup(SDNode *
N,
bool IsIntrinsic,
2944 bool isUpdating,
unsigned NumVecs,
2945 const uint16_t *DOpcodes,
2946 const uint16_t *QOpcodes0,
2947 const uint16_t *QOpcodes1) {
2948 assert(Subtarget->hasNEON());
2949 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLDDup NumVecs out-of-range");
2953 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2954 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2958 EVT VT =
N->getValueType(0);
2961 unsigned Alignment = 0;
2963 Alignment =
Align->getAsZExtVal();
2965 if (Alignment > NumBytes)
2966 Alignment = NumBytes;
2967 if (Alignment < 8 && Alignment < NumBytes)
2970 Alignment = (Alignment & -Alignment);
2974 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
2996 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
3001 std::vector<EVT> ResTys;
3002 ResTys.push_back(ResTy);
3004 ResTys.push_back(MVT::i32);
3005 ResTys.push_back(MVT::Other);
3008 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3011 Ops.push_back(MemAddr);
3012 Ops.push_back(Align);
3022 Ops.push_back(Reg0);
3029 if (is64BitVector || NumVecs == 1) {
3033 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
3034 const SDValue OpsA[] = {MemAddr,
Align, ImplDef, Pred, Reg0, Chain};
3035 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl, ResTy,
3041 Ops.push_back(Pred);
3042 Ops.push_back(Reg0);
3043 Ops.push_back(Chain);
3045 SDNode *VLdDup = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
3056 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7,
"Unexpected subreg numbering");
3057 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
3058 for (
unsigned Vec = 0; Vec != NumVecs; ++Vec) {
3060 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
3066 CurDAG->RemoveDeadNode(
N);
3069bool ARMDAGToDAGISel::tryInsertVectorElt(SDNode *
N) {
3070 if (!Subtarget->hasMVEIntegerOps())
3084 (VT != MVT::v8f16 && VT != MVT::v8i16) || (Ins2.
getValueType() != VT))
3089 if (Lane2 % 2 != 0 || Lane1 != Lane2 + 1)
3101 Val1.
getOpcode() == ARMISD::VGETLANEu) &&
3103 Val2.
getOpcode() == ARMISD::VGETLANEu) &&
3116 ExtractLane1 == ExtractLane2 + 1) {
3117 SDValue NewExt = CurDAG->getTargetExtractSubreg(
3118 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val1.
getOperand(0));
3119 SDValue NewIns = CurDAG->getTargetInsertSubreg(
3120 ARM::ssub_0 + Lane2 / 2, dl, VT, Ins2.
getOperand(0),
3122 ReplaceUses(Ins1, NewIns);
3128 if (VT == MVT::v8i16 && Subtarget->hasFullFP16()) {
3129 SDValue Inp1 = CurDAG->getTargetExtractSubreg(
3130 ARM::ssub_0 + ExtractLane1 / 2, dl, MVT::f32, Val1.
getOperand(0));
3131 SDValue Inp2 = CurDAG->getTargetExtractSubreg(
3132 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val2.
getOperand(0));
3133 if (ExtractLane1 % 2 != 0)
3134 Inp1 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp1), 0);
3135 if (ExtractLane2 % 2 != 0)
3136 Inp2 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp2), 0);
3137 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Inp2, Inp1);
3139 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3141 ReplaceUses(Ins1, NewIns);
3148 if (VT == MVT::v8f16 && Subtarget->hasFullFP16()) {
3149 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Val2, Val1);
3151 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3153 ReplaceUses(Ins1, NewIns);
3162bool ARMDAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
3163 EVT VT =
N->getValueType(0);
3171 SDValue ShiftAmt =
N->getOperand(1);
3174 auto emitUnary = [&](
unsigned Opc,
SDValue Src,
bool IsRSB) {
3175 if (Subtarget->
isThumb2() || !Subtarget->isThumb()) {
3178 SDValue ZeroImm = CurDAG->getTargetConstant(0,
DL, MVT::i32);
3180 CurDAG->getRegister(0, MVT::i32),
3181 CurDAG->getRegister(0, MVT::i32)};
3182 MachineSDNode *Unary =
3183 CurDAG->getMachineNode(
Opc,
DL, MVT::i32, FullOps);
3187 CurDAG->getRegister(0, MVT::i32),
3188 CurDAG->getRegister(0, MVT::i32)};
3189 MachineSDNode *Unary = CurDAG->getMachineNode(
Opc,
DL, MVT::i32, FullOps);
3192 SDValue Thumb1Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
3193 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32)};
3194 MachineSDNode *Unary = CurDAG->getMachineNode(
Opc,
DL, MVT::i32, Thumb1Ops);
3207 ((Add0Imm & 31) == 0)) {
3209 Subtarget->isThumb()
3210 ? (Subtarget->hasThumb2() ? ARM::t2RSBri : ARM::tRSB)
3212 NewShiftAmt = emitUnary(NegOpc, Add1,
true);
3215 unsigned NotOpc = Subtarget->isThumb()
3216 ? (Subtarget->
isThumb2() ? ARM::t2MVNr : ARM::tMVN)
3218 NewShiftAmt = emitUnary(NotOpc, Add1,
false);
3226 if (Subtarget->isThumb()) {
3228 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
3229 N->getOperand(0), NewShiftAmt,
getAL(CurDAG,
DL),
3230 CurDAG->getRegister(0, MVT::i32)};
3231 CurDAG->SelectNodeTo(
N, ARM::tROR, VT,
Ops);
3234 CurDAG->getRegister(0, MVT::i32),
3235 CurDAG->getRegister(0, MVT::i32)};
3236 CurDAG->SelectNodeTo(
N, ARM::t2RORrr, VT,
Ops);
3241 SDValue OpcEnc = CurDAG->getTargetConstant(
3247 CurDAG->getRegister(0, MVT::i32),
3248 CurDAG->getRegister(0, MVT::i32)};
3249 CurDAG->SelectNodeTo(
N, ARM::MOVsr, VT,
Ops);
3254bool ARMDAGToDAGISel::transformFixedFloatingPointConversion(SDNode *
N,
3257 bool FixedToFloat) {
3258 auto Type =
N->getValueType(0);
3259 unsigned ScalarBits =
Type.getScalarSizeInBits();
3260 if (ScalarBits > 32)
3263 SDNodeFlags FMulFlags =
FMul->getFlags();
3266 if (ScalarBits == 16 && !FMulFlags.
hasNoInfs() && IsUnsigned)
3289 case ARMISD::VMOVIMM:
3290 case ARMISD::VDUP: {
3294 if (ImmNode.
getOpcode() == ARMISD::VMOVIMM)
3297 APFloat(ScalarBits == 32 ? APFloat::IEEEsingle() : APFloat::IEEEhalf(),
3298 APInt(ScalarBits, Imm));
3301 case ARMISD::VMOVFPIMM: {
3315 if (!ImmAPF.getExactInverse(&ToConvert))
3318 APSInt Converted(64,
false);
3322 if (!IsExact || !Converted.isPowerOf2())
3325 unsigned FracBits = Converted.logBase2();
3326 if (FracBits > ScalarBits)
3330 VecVal, CurDAG->getConstant(FracBits, SDLoc(
N), MVT::i32)};
3331 AddEmptyMVEPredicateToOps(
Ops, SDLoc(
N),
Type);
3333 unsigned int Opcode;
3334 switch (ScalarBits) {
3337 Opcode = IsUnsigned ? ARM::MVE_VCVTf16u16_fix : ARM::MVE_VCVTf16s16_fix;
3339 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3343 Opcode = IsUnsigned ? ARM::MVE_VCVTf32u32_fix : ARM::MVE_VCVTf32s32_fix;
3345 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3352 ReplaceNode(
N, CurDAG->getMachineNode(Opcode, SDLoc(
N),
Type,
Ops));
3356bool ARMDAGToDAGISel::tryFP_TO_INT(SDNode *
N, SDLoc dl) {
3358 if (!Subtarget->hasMVEFloatOps())
3360 EVT
Type =
N->getValueType(0);
3361 if (!
Type.isVector())
3363 unsigned int ScalarBits =
Type.getScalarSizeInBits();
3367 SDNode *
Node =
N->getOperand(0).getNode();
3372 if (
Node->getOperand(0) !=
Node->getOperand(1))
3377 if (ScalarBits == 16 && !
Flags.hasNoInfs() && IsUnsigned)
3381 switch (ScalarBits) {
3383 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3386 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3390 CurDAG->getConstant(1, dl, MVT::i32)};
3391 AddEmptyMVEPredicateToOps(
Ops, dl,
Type);
3393 ReplaceNode(
N, CurDAG->getMachineNode(Opcode, dl,
Type,
Ops));
3400 return transformFixedFloatingPointConversion(
N, Node, IsUnsigned,
false);
3403bool ARMDAGToDAGISel::tryFMULFixed(SDNode *
N, SDLoc dl) {
3405 if (!Subtarget->hasMVEFloatOps())
3407 auto Type =
N->getValueType(0);
3408 if (!
Type.isVector())
3411 auto LHS =
N->getOperand(0);
3415 return transformFixedFloatingPointConversion(
3419bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *
N,
bool isSigned) {
3420 if (!Subtarget->hasV6T2Ops())
3423 unsigned Opc = isSigned
3424 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
3429 unsigned And_imm = 0;
3434 if (And_imm & (And_imm + 1))
3437 unsigned Srl_imm = 0;
3440 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3445 And_imm &= -1U >> Srl_imm;
3449 unsigned LSB = Srl_imm;
3451 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3453 if ((LSB + Width + 1) ==
N->getValueType(0).getSizeInBits()) {
3455 if (Subtarget->isThumb()) {
3456 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
3458 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3459 getAL(CurDAG, dl), Reg0, Reg0 };
3460 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3469 SDValue Ops[] = {
N->getOperand(0).getOperand(0), ShOpc,
3470 getAL(CurDAG, dl), Reg0, Reg0 };
3471 CurDAG->SelectNodeTo(
N, ARM::MOVsi, MVT::i32,
Ops);
3475 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3477 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3478 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3479 getAL(CurDAG, dl), Reg0 };
3480 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3488 unsigned Shl_imm = 0;
3490 assert(Shl_imm > 0 && Shl_imm < 32 &&
"bad amount in shift node!");
3491 unsigned Srl_imm = 0;
3493 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3495 unsigned Width = 32 - Srl_imm - 1;
3496 int LSB = Srl_imm - Shl_imm;
3499 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3500 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3502 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3503 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3504 getAL(CurDAG, dl), Reg0 };
3505 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3513 unsigned Srl_imm = 0;
3517 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3520 unsigned Width = MSB - LSB;
3521 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3522 assert(Srl_imm + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3524 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
3525 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3526 getAL(CurDAG, dl), Reg0 };
3527 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3533 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3539 if (LSB + Width > 32)
3542 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3543 assert(LSB + Width <= 32 &&
"Shouldn't create an invalid ubfx");
3545 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3546 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
3547 getAL(CurDAG, dl), Reg0 };
3548 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3556void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
3559 if (MemTy == MVT::i8)
3560 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_8 : ARM::CMP_SWAP_8;
3561 else if (MemTy == MVT::i16)
3562 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_16 : ARM::CMP_SWAP_16;
3563 else if (MemTy == MVT::i32)
3564 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_32 : ARM::CMP_SWAP_32;
3568 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
3570 SDNode *CmpSwap = CurDAG->getMachineNode(
3572 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other),
Ops);
3579 CurDAG->RemoveDeadNode(
N);
3582static std::optional<std::pair<unsigned, unsigned>>
3584 unsigned FirstOne =
A.getBitWidth() -
A.countl_zero() - 1;
3585 unsigned LastOne =
A.countr_zero();
3586 if (
A.popcount() != (FirstOne - LastOne + 1))
3587 return std::nullopt;
3588 return std::make_pair(FirstOne, LastOne);
3591void ARMDAGToDAGISel::SelectCMPZ(SDNode *
N,
bool &SwitchEQNEToPLMI) {
3592 assert(
N->getOpcode() == ARMISD::CMPZ);
3593 SwitchEQNEToPLMI =
false;
3595 if (!Subtarget->isThumb())
3602 if (!
And->hasOneUse())
3621 auto EmitShift = [&](
unsigned Opc,
SDValue Src,
unsigned Imm) -> SDNode* {
3623 Opc = (
Opc == ARM::tLSLri) ? ARM::t2LSLri :
ARM::t2LSRri;
3624 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3625 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3626 CurDAG->getRegister(0, MVT::i32) };
3627 return CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
3629 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
3630 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3631 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3632 return CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
3636 if (
Range->second == 0) {
3638 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3639 ReplaceNode(
And.getNode(), NewN);
3640 }
else if (
Range->first == 31) {
3642 NewN = EmitShift(ARM::tLSRri,
X,
Range->second);
3643 ReplaceNode(
And.getNode(), NewN);
3649 if (!
N->hasOneUse())
3651 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3652 ReplaceNode(
And.getNode(), NewN);
3654 SwitchEQNEToPLMI =
true;
3655 }
else if (!Subtarget->hasV6T2Ops()) {
3658 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3659 NewN = EmitShift(ARM::tLSRri,
SDValue(NewN, 0),
3661 ReplaceNode(
And.getNode(), NewN);
3666 unsigned Opc128[3]) {
3668 "Unexpected vector shuffle length");
3681void ARMDAGToDAGISel::Select(SDNode *
N) {
3684 if (
N->isMachineOpcode()) {
3689 switch (
N->getOpcode()) {
3714 CurDAG->getRegister(ARM::SP, MVT::i32),
3715 CurDAG->getTargetConstant(RHSC, dl, MVT::i32),
3717 CurDAG->getRegister(0, MVT::i32),
3719 MachineSDNode *ResNode =
3720 CurDAG->getMachineNode(ARM::tSTRspi, dl, MVT::Other,
Ops);
3721 MachineMemOperand *MemOp =
ST->getMemOperand();
3723 ReplaceNode(
N, ResNode);
3730 if (tryWriteRegister(
N))
3734 if (tryReadRegister(
N))
3739 if (tryInlineAsm(
N))
3743 unsigned Val =
N->getAsZExtVal();
3746 !Subtarget->genExecuteOnly()) {
3747 SDValue CPIdx = CurDAG->getTargetConstantPool(
3748 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
3749 TLI->getPointerTy(CurDAG->getDataLayout()));
3752 if (Subtarget->isThumb()) {
3756 CurDAG->getRegister(0, MVT::i32),
3757 CurDAG->getEntryNode()
3759 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
3764 CurDAG->getTargetConstant(0, dl, MVT::i32),
3766 CurDAG->getRegister(0, MVT::i32),
3767 CurDAG->getEntryNode()
3769 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
3775 MachineFunction& MF = CurDAG->getMachineFunction();
3776 MachineMemOperand *MemOp =
3782 ReplaceNode(
N, ResNode);
3792 SDValue TFI = CurDAG->getTargetFrameIndex(
3793 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
3800 CurDAG->SelectNodeTo(
N, ARM::tADDframe, MVT::i32, TFI,
3801 CurDAG->getTargetConstant(0, dl, MVT::i32));
3804 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
3805 ARM::t2ADDri : ARM::ADDri);
3806 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
3807 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3808 CurDAG->getRegister(0, MVT::i32) };
3809 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3814 if (tryInsertVectorElt(
N))
3819 if (tryV6T2BitfieldExtractOp(
N,
false))
3824 if (tryV6T2BitfieldExtractOp(
N,
true))
3828 if (tryShiftAmountMod(
N))
3835 if (tryFP_TO_INT(
N, dl))
3839 if (tryFMULFixed(
N, dl))
3846 unsigned RHSV =
C->getZExtValue();
3849 unsigned ShImm =
Log2_32(RHSV-1);
3854 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3855 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3856 if (Subtarget->isThumb()) {
3858 CurDAG->SelectNodeTo(
N, ARM::t2ADDrs, MVT::i32,
Ops);
3863 CurDAG->SelectNodeTo(
N, ARM::ADDrsi, MVT::i32,
Ops);
3868 unsigned ShImm =
Log2_32(RHSV+1);
3873 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3874 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3875 if (Subtarget->isThumb()) {
3877 CurDAG->SelectNodeTo(
N, ARM::t2RSBrs, MVT::i32,
Ops);
3882 CurDAG->SelectNodeTo(
N, ARM::RSBrsi, MVT::i32,
Ops);
3890 if (tryV6T2BitfieldExtractOp(
N,
false))
3897 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
3898 uint32_t
Imm = (uint32_t) N1C->getZExtValue();
3904 bool PreferImmediateEncoding =
3905 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
3906 if (!PreferImmediateEncoding &&
3911 SDValue NewImm = CurDAG->getConstant(~Imm, dl, MVT::i32);
3915 CurDAG->RepositionNode(
N->getIterator(), NewImm.
getNode());
3917 if (!Subtarget->hasThumb2()) {
3918 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
3919 N->getOperand(0), NewImm,
getAL(CurDAG, dl),
3920 CurDAG->getRegister(0, MVT::i32)};
3921 ReplaceNode(
N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32,
Ops));
3925 CurDAG->getRegister(0, MVT::i32),
3926 CurDAG->getRegister(0, MVT::i32)};
3928 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32,
Ops));
3939 EVT VT =
N->getValueType(0);
3942 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
3944 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
3956 unsigned N1CVal = N1C->getZExtValue();
3958 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
3959 (N1CVal & 0xffffU) == 0xffffU &&
3960 (N2CVal & 0xffffU) == 0x0U) {
3961 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
3964 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
3965 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
3972 case ARMISD::UMAAL: {
3973 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3975 N->getOperand(2),
N->getOperand(3),
3977 CurDAG->getRegister(0, MVT::i32) };
3978 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, MVT::i32, MVT::i32,
Ops));
3981 case ARMISD::UMLAL:{
3982 if (Subtarget->isThumb()) {
3983 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3984 N->getOperand(3),
getAL(CurDAG, dl),
3985 CurDAG->getRegister(0, MVT::i32)};
3987 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32,
Ops));
3990 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3991 N->getOperand(3),
getAL(CurDAG, dl),
3992 CurDAG->getRegister(0, MVT::i32),
3993 CurDAG->getRegister(0, MVT::i32) };
3994 ReplaceNode(
N, CurDAG->getMachineNode(
3995 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3996 MVT::i32, MVT::i32,
Ops));
4000 case ARMISD::SMLAL:{
4001 if (Subtarget->isThumb()) {
4002 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
4003 N->getOperand(3),
getAL(CurDAG, dl),
4004 CurDAG->getRegister(0, MVT::i32)};
4006 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32,
Ops));
4009 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
4010 N->getOperand(3),
getAL(CurDAG, dl),
4011 CurDAG->getRegister(0, MVT::i32),
4012 CurDAG->getRegister(0, MVT::i32) };
4013 ReplaceNode(
N, CurDAG->getMachineNode(
4014 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
4015 MVT::i32, MVT::i32,
Ops));
4019 case ARMISD::SUBE: {
4020 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
4025 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
4029 if (Subtarget->isThumb())
4030 assert(Subtarget->hasThumb2() &&
4031 "This pattern should not be generated for Thumb");
4033 SDValue SmulLoHi =
N->getOperand(1);
4042 unsigned Opc = Subtarget->
isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
4045 CurDAG->getRegister(0, MVT::i32) };
4046 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops));
4050 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
4052 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
4053 if (tryT2IndexedLoad(
N))
4055 }
else if (Subtarget->isThumb()) {
4056 if (tryT1IndexedLoad(
N))
4058 }
else if (tryARMIndexedLoad(
N))
4064 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
4068 case ARMISD::LDRD: {
4074 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
4075 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4081 RegOffset = CurDAG->getRegister(0, MVT::i32);
4084 SDNode *
New = CurDAG->getMachineNode(ARM::LOADDUAL, dl,
4085 {MVT::Untyped, MVT::Other},
Ops);
4086 SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4088 SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4090 transferMemOperands(
N, New);
4094 CurDAG->RemoveDeadNode(
N);
4097 case ARMISD::STRD: {
4103 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
4104 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4110 RegOffset = CurDAG->getRegister(0, MVT::i32);
4115 SDNode *
New = CurDAG->getMachineNode(ARM::STOREDUAL, dl, MVT::Other,
Ops);
4116 transferMemOperands(
N, New);
4118 CurDAG->RemoveDeadNode(
N);
4121 case ARMISD::BRCOND: {
4134 unsigned Opc = Subtarget->isThumb() ?
4135 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
4145 if (
Flags.getOpcode() == ARMISD::CMPZ) {
4148 uint64_t
ID =
Int->getConstantOperandVal(1);
4151 if (
ID == Intrinsic::loop_decrement_reg) {
4153 SDValue Size = CurDAG->getTargetConstant(
Int.getConstantOperandVal(3),
4158 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4159 CurDAG->getVTList(MVT::i32, MVT::Other),
4161 ReplaceUses(
Int.getNode(), LoopDec);
4165 CurDAG->getMachineNode(ARM::t2LoopEnd, dl, MVT::Other, EndArgs);
4167 ReplaceUses(
N, LoopEnd);
4168 CurDAG->RemoveDeadNode(
N);
4169 CurDAG->RemoveDeadNode(
Flags.getNode());
4170 CurDAG->RemoveDeadNode(
Int.getNode());
4175 bool SwitchEQNEToPLMI;
4176 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4177 Flags =
N->getOperand(3);
4179 if (SwitchEQNEToPLMI) {
4192 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
4193 Chain = CurDAG->getCopyToReg(Chain, dl, ARM::CPSR, Flags,
SDValue());
4194 SDValue Ops[] = {N1, Tmp2, CurDAG->getRegister(ARM::CPSR, MVT::i32), Chain,
4196 CurDAG->SelectNodeTo(
N,
Opc, MVT::Other,
Ops);
4200 case ARMISD::CMPZ: {
4207 if (
C &&
C->getSExtValue() < 0 && Subtarget->isThumb()) {
4208 int64_t Addend = -
C->getSExtValue();
4210 SDNode *
Add =
nullptr;
4215 if (Addend < 1<<8) {
4217 SDValue Ops[] = {
X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4218 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
4219 CurDAG->getRegister(0, MVT::i32) };
4220 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32,
Ops);
4222 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 :
ARM::tADDi8;
4223 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
X,
4224 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4225 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
4226 Add = CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
4231 CurDAG->MorphNodeTo(
N, ARMISD::CMPZ,
N->getVTList(), Ops2);
4238 case ARMISD::CMOV: {
4241 if (
Flags.getOpcode() == ARMISD::CMPZ) {
4242 bool SwitchEQNEToPLMI;
4243 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4245 if (SwitchEQNEToPLMI) {
4258 SDValue NewARMcc = CurDAG->getConstant((
unsigned)CC, dl, MVT::i32);
4259 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), NewARMcc,
4261 CurDAG->MorphNodeTo(
N, ARMISD::CMOV,
N->getVTList(),
Ops);
4267 case ARMISD::VZIP: {
4268 EVT VT =
N->getValueType(0);
4270 unsigned Opc64[] = {ARM::VZIPd8, ARM::VZIPd16, ARM::VTRNd32};
4271 unsigned Opc128[] = {ARM::VZIPq8, ARM::VZIPq16, ARM::VZIPq32};
4274 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4275 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4276 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4279 case ARMISD::VUZP: {
4280 EVT VT =
N->getValueType(0);
4282 unsigned Opc64[] = {ARM::VUZPd8, ARM::VUZPd16, ARM::VTRNd32};
4283 unsigned Opc128[] = {ARM::VUZPq8, ARM::VUZPq16, ARM::VUZPq32};
4286 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4287 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4288 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4291 case ARMISD::VTRN: {
4292 EVT VT =
N->getValueType(0);
4293 unsigned Opc64[] = {ARM::VTRNd8, ARM::VTRNd16, ARM::VTRNd32};
4294 unsigned Opc128[] = {ARM::VTRNq8, ARM::VTRNq16, ARM::VTRNq32};
4297 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4298 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4299 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4303 EVT VecVT =
N->getValueType(0);
4306 if (EltVT == MVT::f64) {
4307 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
4309 N, createDRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4312 assert(EltVT == MVT::f32 &&
"unexpected type for BUILD_VECTOR");
4315 N, createSRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4318 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
4320 createQuadSRegsNode(VecVT,
N->getOperand(0),
N->getOperand(1),
4321 N->getOperand(2),
N->getOperand(3)));
4326 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
4328 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
4330 SelectVLDDup(
N,
false,
false, 1, DOpcodes, QOpcodes);
4335 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4337 SelectVLDDup(
N,
false,
false, 2, Opcodes);
4342 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
4343 ARM::VLD3DUPd16Pseudo,
4344 ARM::VLD3DUPd32Pseudo };
4345 SelectVLDDup(
N,
false,
false, 3, Opcodes);
4350 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
4351 ARM::VLD4DUPd16Pseudo,
4352 ARM::VLD4DUPd32Pseudo };
4353 SelectVLDDup(
N,
false,
false, 4, Opcodes);
4358 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
4359 ARM::VLD1DUPd16wb_fixed,
4360 ARM::VLD1DUPd32wb_fixed };
4361 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
4362 ARM::VLD1DUPq16wb_fixed,
4363 ARM::VLD1DUPq32wb_fixed };
4364 SelectVLDDup(
N,
false,
true, 1, DOpcodes, QOpcodes);
4369 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8wb_fixed,
4370 ARM::VLD2DUPd16wb_fixed,
4371 ARM::VLD2DUPd32wb_fixed,
4372 ARM::VLD1q64wb_fixed };
4373 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4374 ARM::VLD2DUPq16EvenPseudo,
4375 ARM::VLD2DUPq32EvenPseudo };
4376 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudoWB_fixed,
4377 ARM::VLD2DUPq16OddPseudoWB_fixed,
4378 ARM::VLD2DUPq32OddPseudoWB_fixed };
4379 SelectVLDDup(
N,
false,
true, 2, DOpcodes, QOpcodes0, QOpcodes1);
4384 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
4385 ARM::VLD3DUPd16Pseudo_UPD,
4386 ARM::VLD3DUPd32Pseudo_UPD,
4387 ARM::VLD1d64TPseudoWB_fixed };
4388 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4389 ARM::VLD3DUPq16EvenPseudo,
4390 ARM::VLD3DUPq32EvenPseudo };
4391 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo_UPD,
4392 ARM::VLD3DUPq16OddPseudo_UPD,
4393 ARM::VLD3DUPq32OddPseudo_UPD };
4394 SelectVLDDup(
N,
false,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4399 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
4400 ARM::VLD4DUPd16Pseudo_UPD,
4401 ARM::VLD4DUPd32Pseudo_UPD,
4402 ARM::VLD1d64QPseudoWB_fixed };
4403 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4404 ARM::VLD4DUPq16EvenPseudo,
4405 ARM::VLD4DUPq32EvenPseudo };
4406 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo_UPD,
4407 ARM::VLD4DUPq16OddPseudo_UPD,
4408 ARM::VLD4DUPq32OddPseudo_UPD };
4409 SelectVLDDup(
N,
false,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4414 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
4415 ARM::VLD1d16wb_fixed,
4416 ARM::VLD1d32wb_fixed,
4417 ARM::VLD1d64wb_fixed };
4418 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
4419 ARM::VLD1q16wb_fixed,
4420 ARM::VLD1q32wb_fixed,
4421 ARM::VLD1q64wb_fixed };
4422 SelectVLD(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4427 if (Subtarget->hasNEON()) {
4428 static const uint16_t DOpcodes[] = {
4429 ARM::VLD2d8wb_fixed, ARM::VLD2d16wb_fixed, ARM::VLD2d32wb_fixed,
4430 ARM::VLD1q64wb_fixed};
4431 static const uint16_t QOpcodes[] = {ARM::VLD2q8PseudoWB_fixed,
4432 ARM::VLD2q16PseudoWB_fixed,
4433 ARM::VLD2q32PseudoWB_fixed};
4434 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4436 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8,
4437 ARM::MVE_VLD21_8_wb};
4438 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
4439 ARM::MVE_VLD21_16_wb};
4440 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
4441 ARM::MVE_VLD21_32_wb};
4442 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4443 SelectMVE_VLD(
N, 2, Opcodes,
true);
4449 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
4450 ARM::VLD3d16Pseudo_UPD,
4451 ARM::VLD3d32Pseudo_UPD,
4452 ARM::VLD1d64TPseudoWB_fixed};
4453 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4454 ARM::VLD3q16Pseudo_UPD,
4455 ARM::VLD3q32Pseudo_UPD };
4456 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
4457 ARM::VLD3q16oddPseudo_UPD,
4458 ARM::VLD3q32oddPseudo_UPD };
4459 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4464 if (Subtarget->hasNEON()) {
4465 static const uint16_t DOpcodes[] = {
4466 ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, ARM::VLD4d32Pseudo_UPD,
4467 ARM::VLD1d64QPseudoWB_fixed};
4468 static const uint16_t QOpcodes0[] = {ARM::VLD4q8Pseudo_UPD,
4469 ARM::VLD4q16Pseudo_UPD,
4470 ARM::VLD4q32Pseudo_UPD};
4471 static const uint16_t QOpcodes1[] = {ARM::VLD4q8oddPseudo_UPD,
4472 ARM::VLD4q16oddPseudo_UPD,
4473 ARM::VLD4q32oddPseudo_UPD};
4474 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4476 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
4478 ARM::MVE_VLD43_8_wb};
4479 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
4481 ARM::MVE_VLD43_16_wb};
4482 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
4484 ARM::MVE_VLD43_32_wb};
4485 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4486 SelectMVE_VLD(
N, 4, Opcodes,
true);
4492 if (Subtarget->hasNEON()) {
4493 static const uint16_t DOpcodes[] = {
4494 ARM::VLD1q8wb_fixed, ARM::VLD1q16wb_fixed, ARM::VLD1q32wb_fixed,
4495 ARM::VLD1q64wb_fixed};
4496 static const uint16_t QOpcodes[] = {
4497 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4498 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4499 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4506 if (Subtarget->hasNEON()) {
4507 static const uint16_t DOpcodes[] = {
4508 ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d16TPseudoWB_fixed,
4509 ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d64TPseudoWB_fixed};
4510 static const uint16_t QOpcodes0[] = {
4511 ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1q16LowTPseudo_UPD,
4512 ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1q64LowTPseudo_UPD};
4513 static const uint16_t QOpcodes1[] = {
4514 ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1q16HighTPseudo_UPD,
4515 ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1q64HighTPseudo_UPD};
4516 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4523 if (Subtarget->hasNEON()) {
4524 static const uint16_t DOpcodes[] = {
4525 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4526 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4527 static const uint16_t QOpcodes0[] = {
4528 ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1q16LowQPseudo_UPD,
4529 ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1q64LowQPseudo_UPD};
4530 static const uint16_t QOpcodes1[] = {
4531 ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1q16HighQPseudo_UPD,
4532 ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1q64HighQPseudo_UPD};
4533 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4540 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
4541 ARM::VLD2LNd16Pseudo_UPD,
4542 ARM::VLD2LNd32Pseudo_UPD };
4543 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
4544 ARM::VLD2LNq32Pseudo_UPD };
4545 SelectVLDSTLane(
N,
true,
true, 2, DOpcodes, QOpcodes);
4550 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
4551 ARM::VLD3LNd16Pseudo_UPD,
4552 ARM::VLD3LNd32Pseudo_UPD };
4553 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
4554 ARM::VLD3LNq32Pseudo_UPD };
4555 SelectVLDSTLane(
N,
true,
true, 3, DOpcodes, QOpcodes);
4560 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
4561 ARM::VLD4LNd16Pseudo_UPD,
4562 ARM::VLD4LNd32Pseudo_UPD };
4563 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
4564 ARM::VLD4LNq32Pseudo_UPD };
4565 SelectVLDSTLane(
N,
true,
true, 4, DOpcodes, QOpcodes);
4570 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
4571 ARM::VST1d16wb_fixed,
4572 ARM::VST1d32wb_fixed,
4573 ARM::VST1d64wb_fixed };
4574 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
4575 ARM::VST1q16wb_fixed,
4576 ARM::VST1q32wb_fixed,
4577 ARM::VST1q64wb_fixed };
4578 SelectVST(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4582 case ARMISD::VST2_UPD: {
4583 if (Subtarget->hasNEON()) {
4584 static const uint16_t DOpcodes[] = {
4585 ARM::VST2d8wb_fixed, ARM::VST2d16wb_fixed, ARM::VST2d32wb_fixed,
4586 ARM::VST1q64wb_fixed};
4587 static const uint16_t QOpcodes[] = {ARM::VST2q8PseudoWB_fixed,
4588 ARM::VST2q16PseudoWB_fixed,
4589 ARM::VST2q32PseudoWB_fixed};
4590 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4597 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
4598 ARM::VST3d16Pseudo_UPD,
4599 ARM::VST3d32Pseudo_UPD,
4600 ARM::VST1d64TPseudoWB_fixed};
4601 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
4602 ARM::VST3q16Pseudo_UPD,
4603 ARM::VST3q32Pseudo_UPD };
4604 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
4605 ARM::VST3q16oddPseudo_UPD,
4606 ARM::VST3q32oddPseudo_UPD };
4607 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4611 case ARMISD::VST4_UPD: {
4612 if (Subtarget->hasNEON()) {
4613 static const uint16_t DOpcodes[] = {
4614 ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, ARM::VST4d32Pseudo_UPD,
4615 ARM::VST1d64QPseudoWB_fixed};
4616 static const uint16_t QOpcodes0[] = {ARM::VST4q8Pseudo_UPD,
4617 ARM::VST4q16Pseudo_UPD,
4618 ARM::VST4q32Pseudo_UPD};
4619 static const uint16_t QOpcodes1[] = {ARM::VST4q8oddPseudo_UPD,
4620 ARM::VST4q16oddPseudo_UPD,
4621 ARM::VST4q32oddPseudo_UPD};
4622 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4629 if (Subtarget->hasNEON()) {
4630 static const uint16_t DOpcodes[] = { ARM::VST1q8wb_fixed,
4631 ARM::VST1q16wb_fixed,
4632 ARM::VST1q32wb_fixed,
4633 ARM::VST1q64wb_fixed};
4634 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4635 ARM::VST1d16QPseudoWB_fixed,
4636 ARM::VST1d32QPseudoWB_fixed,
4637 ARM::VST1d64QPseudoWB_fixed };
4638 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4645 if (Subtarget->hasNEON()) {
4646 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudoWB_fixed,
4647 ARM::VST1d16TPseudoWB_fixed,
4648 ARM::VST1d32TPseudoWB_fixed,
4649 ARM::VST1d64TPseudoWB_fixed };
4650 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4651 ARM::VST1q16LowTPseudo_UPD,
4652 ARM::VST1q32LowTPseudo_UPD,
4653 ARM::VST1q64LowTPseudo_UPD };
4654 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo_UPD,
4655 ARM::VST1q16HighTPseudo_UPD,
4656 ARM::VST1q32HighTPseudo_UPD,
4657 ARM::VST1q64HighTPseudo_UPD };
4658 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4665 if (Subtarget->hasNEON()) {
4666 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4667 ARM::VST1d16QPseudoWB_fixed,
4668 ARM::VST1d32QPseudoWB_fixed,
4669 ARM::VST1d64QPseudoWB_fixed };
4670 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4671 ARM::VST1q16LowQPseudo_UPD,
4672 ARM::VST1q32LowQPseudo_UPD,
4673 ARM::VST1q64LowQPseudo_UPD };
4674 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo_UPD,
4675 ARM::VST1q16HighQPseudo_UPD,
4676 ARM::VST1q32HighQPseudo_UPD,
4677 ARM::VST1q64HighQPseudo_UPD };
4678 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4684 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
4685 ARM::VST2LNd16Pseudo_UPD,
4686 ARM::VST2LNd32Pseudo_UPD };
4687 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
4688 ARM::VST2LNq32Pseudo_UPD };
4689 SelectVLDSTLane(
N,
false,
true, 2, DOpcodes, QOpcodes);
4694 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
4695 ARM::VST3LNd16Pseudo_UPD,
4696 ARM::VST3LNd32Pseudo_UPD };
4697 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
4698 ARM::VST3LNq32Pseudo_UPD };
4699 SelectVLDSTLane(
N,
false,
true, 3, DOpcodes, QOpcodes);
4704 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
4705 ARM::VST4LNd16Pseudo_UPD,
4706 ARM::VST4LNd32Pseudo_UPD };
4707 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
4708 ARM::VST4LNq32Pseudo_UPD };
4709 SelectVLDSTLane(
N,
false,
true, 4, DOpcodes, QOpcodes);
4715 unsigned IntNo =
N->getConstantOperandVal(1);
4720 case Intrinsic::arm_mrrc:
4721 case Intrinsic::arm_mrrc2: {
4726 if (Subtarget->isThumb())
4727 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
4729 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
4732 Ops.push_back(getI32Imm(
N->getConstantOperandVal(2), dl));
4733 Ops.push_back(getI32Imm(
N->getConstantOperandVal(3), dl));
4734 Ops.push_back(getI32Imm(
N->getConstantOperandVal(4), dl));
4739 if (
Opc != ARM::MRRC2) {
4741 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4744 Ops.push_back(Chain);
4747 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
4749 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, RetType,
Ops));
4752 case Intrinsic::arm_ldaexd:
4753 case Intrinsic::arm_ldrexd: {
4757 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
4759 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
4760 unsigned NewOpc =
isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
4761 : (IsAcquire ?
ARM::LDAEXD :
ARM::LDREXD);
4764 std::vector<EVT> ResTys;
4766 ResTys.push_back(MVT::i32);
4767 ResTys.push_back(MVT::i32);
4769 ResTys.push_back(MVT::Untyped);
4770 ResTys.push_back(MVT::Other);
4774 CurDAG->getRegister(0, MVT::i32), Chain};
4775 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4788 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
4789 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4790 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4793 ReplaceUses(
SDValue(
N, 0), Result);
4801 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
4802 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4803 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4806 ReplaceUses(
SDValue(
N, 1), Result);
4808 ReplaceUses(
SDValue(
N, 2), OutChain);
4809 CurDAG->RemoveDeadNode(
N);
4812 case Intrinsic::arm_stlexd:
4813 case Intrinsic::arm_strexd: {
4822 const EVT ResTys[] = {MVT::i32, MVT::Other};
4824 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
4828 Ops.push_back(Val0);
4829 Ops.push_back(Val1);
4833 Ops.push_back(MemAddr);
4835 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4836 Ops.push_back(Chain);
4838 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
4839 unsigned NewOpc =
isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
4840 : (IsRelease ?
ARM::STLEXD :
ARM::STREXD);
4842 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4851 case Intrinsic::arm_neon_vld1: {
4852 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
4853 ARM::VLD1d32, ARM::VLD1d64 };
4854 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4855 ARM::VLD1q32, ARM::VLD1q64};
4856 SelectVLD(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4860 case Intrinsic::arm_neon_vld1x2: {
4861 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4862 ARM::VLD1q32, ARM::VLD1q64 };
4863 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
4864 ARM::VLD1d16QPseudo,
4865 ARM::VLD1d32QPseudo,
4866 ARM::VLD1d64QPseudo };
4867 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4871 case Intrinsic::arm_neon_vld1x3: {
4872 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
4873 ARM::VLD1d16TPseudo,
4874 ARM::VLD1d32TPseudo,
4875 ARM::VLD1d64TPseudo };
4876 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
4877 ARM::VLD1q16LowTPseudo_UPD,
4878 ARM::VLD1q32LowTPseudo_UPD,
4879 ARM::VLD1q64LowTPseudo_UPD };
4880 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
4881 ARM::VLD1q16HighTPseudo,
4882 ARM::VLD1q32HighTPseudo,
4883 ARM::VLD1q64HighTPseudo };
4884 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4888 case Intrinsic::arm_neon_vld1x4: {
4889 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
4890 ARM::VLD1d16QPseudo,
4891 ARM::VLD1d32QPseudo,
4892 ARM::VLD1d64QPseudo };
4893 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
4894 ARM::VLD1q16LowQPseudo_UPD,
4895 ARM::VLD1q32LowQPseudo_UPD,
4896 ARM::VLD1q64LowQPseudo_UPD };
4897 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
4898 ARM::VLD1q16HighQPseudo,
4899 ARM::VLD1q32HighQPseudo,
4900 ARM::VLD1q64HighQPseudo };
4901 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4905 case Intrinsic::arm_neon_vld2: {
4906 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
4907 ARM::VLD2d32, ARM::VLD1q64 };
4908 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
4909 ARM::VLD2q32Pseudo };
4910 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4914 case Intrinsic::arm_neon_vld3: {
4915 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
4918 ARM::VLD1d64TPseudo };
4919 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4920 ARM::VLD3q16Pseudo_UPD,
4921 ARM::VLD3q32Pseudo_UPD };
4922 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
4923 ARM::VLD3q16oddPseudo,
4924 ARM::VLD3q32oddPseudo };
4925 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4929 case Intrinsic::arm_neon_vld4: {
4930 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
4933 ARM::VLD1d64QPseudo };
4934 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
4935 ARM::VLD4q16Pseudo_UPD,
4936 ARM::VLD4q32Pseudo_UPD };
4937 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
4938 ARM::VLD4q16oddPseudo,
4939 ARM::VLD4q32oddPseudo };
4940 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4944 case Intrinsic::arm_neon_vld2dup: {
4945 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4946 ARM::VLD2DUPd32, ARM::VLD1q64 };
4947 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4948 ARM::VLD2DUPq16EvenPseudo,
4949 ARM::VLD2DUPq32EvenPseudo };
4950 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo,
4951 ARM::VLD2DUPq16OddPseudo,
4952 ARM::VLD2DUPq32OddPseudo };
4953 SelectVLDDup(
N,
true,
false, 2,
4954 DOpcodes, QOpcodes0, QOpcodes1);
4958 case Intrinsic::arm_neon_vld3dup: {
4959 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo,
4960 ARM::VLD3DUPd16Pseudo,
4961 ARM::VLD3DUPd32Pseudo,
4962 ARM::VLD1d64TPseudo };
4963 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4964 ARM::VLD3DUPq16EvenPseudo,
4965 ARM::VLD3DUPq32EvenPseudo };
4966 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo,
4967 ARM::VLD3DUPq16OddPseudo,
4968 ARM::VLD3DUPq32OddPseudo };
4969 SelectVLDDup(
N,
true,
false, 3,
4970 DOpcodes, QOpcodes0, QOpcodes1);
4974 case Intrinsic::arm_neon_vld4dup: {
4975 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo,
4976 ARM::VLD4DUPd16Pseudo,
4977 ARM::VLD4DUPd32Pseudo,
4978 ARM::VLD1d64QPseudo };
4979 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4980 ARM::VLD4DUPq16EvenPseudo,
4981 ARM::VLD4DUPq32EvenPseudo };
4982 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo,
4983 ARM::VLD4DUPq16OddPseudo,
4984 ARM::VLD4DUPq32OddPseudo };
4985 SelectVLDDup(
N,
true,
false, 4,
4986 DOpcodes, QOpcodes0, QOpcodes1);
4990 case Intrinsic::arm_neon_vld2lane: {
4991 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
4992 ARM::VLD2LNd16Pseudo,
4993 ARM::VLD2LNd32Pseudo };
4994 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
4995 ARM::VLD2LNq32Pseudo };
4996 SelectVLDSTLane(
N,
true,
false, 2, DOpcodes, QOpcodes);
5000 case Intrinsic::arm_neon_vld3lane: {
5001 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
5002 ARM::VLD3LNd16Pseudo,
5003 ARM::VLD3LNd32Pseudo };
5004 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
5005 ARM::VLD3LNq32Pseudo };
5006 SelectVLDSTLane(
N,
true,
false, 3, DOpcodes, QOpcodes);
5010 case Intrinsic::arm_neon_vld4lane: {
5011 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
5012 ARM::VLD4LNd16Pseudo,
5013 ARM::VLD4LNd32Pseudo };
5014 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
5015 ARM::VLD4LNq32Pseudo };
5016 SelectVLDSTLane(
N,
true,
false, 4, DOpcodes, QOpcodes);
5020 case Intrinsic::arm_neon_vst1: {
5021 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
5022 ARM::VST1d32, ARM::VST1d64 };
5023 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
5024 ARM::VST1q32, ARM::VST1q64 };
5025 SelectVST(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
5029 case Intrinsic::arm_neon_vst1x2: {
5030 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
5031 ARM::VST1q32, ARM::VST1q64 };
5032 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
5033 ARM::VST1d16QPseudo,
5034 ARM::VST1d32QPseudo,
5035 ARM::VST1d64QPseudo };
5036 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
5040 case Intrinsic::arm_neon_vst1x3: {
5041 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
5042 ARM::VST1d16TPseudo,
5043 ARM::VST1d32TPseudo,
5044 ARM::VST1d64TPseudo };
5045 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
5046 ARM::VST1q16LowTPseudo_UPD,
5047 ARM::VST1q32LowTPseudo_UPD,
5048 ARM::VST1q64LowTPseudo_UPD };
5049 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
5050 ARM::VST1q16HighTPseudo,
5051 ARM::VST1q32HighTPseudo,
5052 ARM::VST1q64HighTPseudo };
5053 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
5057 case Intrinsic::arm_neon_vst1x4: {
5058 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
5059 ARM::VST1d16QPseudo,
5060 ARM::VST1d32QPseudo,
5061 ARM::VST1d64QPseudo };
5062 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
5063 ARM::VST1q16LowQPseudo_UPD,
5064 ARM::VST1q32LowQPseudo_UPD,
5065 ARM::VST1q64LowQPseudo_UPD };
5066 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
5067 ARM::VST1q16HighQPseudo,
5068 ARM::VST1q32HighQPseudo,
5069 ARM::VST1q64HighQPseudo };
5070 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5074 case Intrinsic::arm_neon_vst2: {
5075 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
5076 ARM::VST2d32, ARM::VST1q64 };
5077 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
5078 ARM::VST2q32Pseudo };
5079 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
5083 case Intrinsic::arm_neon_vst3: {
5084 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
5087 ARM::VST1d64TPseudo };
5088 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
5089 ARM::VST3q16Pseudo_UPD,
5090 ARM::VST3q32Pseudo_UPD };
5091 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
5092 ARM::VST3q16oddPseudo,
5093 ARM::VST3q32oddPseudo };
5094 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
5098 case Intrinsic::arm_neon_vst4: {
5099 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
5102 ARM::VST1d64QPseudo };
5103 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
5104 ARM::VST4q16Pseudo_UPD,
5105 ARM::VST4q32Pseudo_UPD };
5106 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
5107 ARM::VST4q16oddPseudo,
5108 ARM::VST4q32oddPseudo };
5109 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5113 case Intrinsic::arm_neon_vst2lane: {
5114 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
5115 ARM::VST2LNd16Pseudo,
5116 ARM::VST2LNd32Pseudo };
5117 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
5118 ARM::VST2LNq32Pseudo };
5119 SelectVLDSTLane(
N,
false,
false, 2, DOpcodes, QOpcodes);
5123 case Intrinsic::arm_neon_vst3lane: {
5124 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
5125 ARM::VST3LNd16Pseudo,
5126 ARM::VST3LNd32Pseudo };
5127 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
5128 ARM::VST3LNq32Pseudo };
5129 SelectVLDSTLane(
N,
false,
false, 3, DOpcodes, QOpcodes);
5133 case Intrinsic::arm_neon_vst4lane: {
5134 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
5135 ARM::VST4LNd16Pseudo,
5136 ARM::VST4LNd32Pseudo };
5137 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
5138 ARM::VST4LNq32Pseudo };
5139 SelectVLDSTLane(
N,
false,
false, 4, DOpcodes, QOpcodes);
5143 case Intrinsic::arm_mve_vldr_gather_base_wb:
5144 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
5145 static const uint16_t Opcodes[] = {ARM::MVE_VLDRWU32_qi_pre,
5146 ARM::MVE_VLDRDU64_qi_pre};
5147 SelectMVE_WB(
N, Opcodes,
5148 IntNo == Intrinsic::arm_mve_vldr_gather_base_wb_predicated);
5152 case Intrinsic::arm_mve_vld2q: {
5153 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, ARM::MVE_VLD21_8};
5154 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
5156 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
5158 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5159 SelectMVE_VLD(
N, 2, Opcodes,
false);
5163 case Intrinsic::arm_mve_vld4q: {
5164 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
5165 ARM::MVE_VLD42_8, ARM::MVE_VLD43_8};
5166 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
5169 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
5172 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5173 SelectMVE_VLD(
N, 4, Opcodes,
false);
5181 unsigned IntNo =
N->getConstantOperandVal(0);
5187 case Intrinsic::arm_neon_vcvtbfp2bf: {
5189 const SDValue &Src =
N->getOperand(1);
5190 llvm::EVT DestTy =
N->getValueType(0);
5192 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5194 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVTB, DestTy,
Ops);
5199 case Intrinsic::arm_neon_vcvtfp2bf: {
5201 const SDValue &Src =
N->getOperand(1);
5203 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5205 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVT, MVT::v4bf16,
Ops);
5209 case Intrinsic::arm_mve_urshrl:
5210 SelectMVE_LongShift(
N, ARM::MVE_URSHRL,
true,
false);
5212 case Intrinsic::arm_mve_uqshll:
5213 SelectMVE_LongShift(
N, ARM::MVE_UQSHLL,
true,
false);
5215 case Intrinsic::arm_mve_srshrl:
5216 SelectMVE_LongShift(
N, ARM::MVE_SRSHRL,
true,
false);
5218 case Intrinsic::arm_mve_sqshll:
5219 SelectMVE_LongShift(
N, ARM::MVE_SQSHLL,
true,
false);
5221 case Intrinsic::arm_mve_uqrshll:
5222 SelectMVE_LongShift(
N, ARM::MVE_UQRSHLL,
false,
true);
5224 case Intrinsic::arm_mve_sqrshrl:
5225 SelectMVE_LongShift(
N, ARM::MVE_SQRSHRL,
false,
true);
5228 case Intrinsic::arm_mve_vadc:
5229 case Intrinsic::arm_mve_vadc_predicated:
5230 SelectMVE_VADCSBC(
N, ARM::MVE_VADC, ARM::MVE_VADCI,
true,
5231 IntNo == Intrinsic::arm_mve_vadc_predicated);
5233 case Intrinsic::arm_mve_vsbc:
5234 case Intrinsic::arm_mve_vsbc_predicated:
5235 SelectMVE_VADCSBC(
N, ARM::MVE_VSBC, ARM::MVE_VSBCI,
false,
5236 IntNo == Intrinsic::arm_mve_vsbc_predicated);
5238 case Intrinsic::arm_mve_vshlc:
5239 case Intrinsic::arm_mve_vshlc_predicated:
5240 SelectMVE_VSHLC(
N, IntNo == Intrinsic::arm_mve_vshlc_predicated);
5243 case Intrinsic::arm_mve_vmlldava:
5244 case Intrinsic::arm_mve_vmlldava_predicated: {
5245 static const uint16_t OpcodesU[] = {
5246 ARM::MVE_VMLALDAVu16, ARM::MVE_VMLALDAVu32,
5247 ARM::MVE_VMLALDAVau16, ARM::MVE_VMLALDAVau32,
5249 static const uint16_t OpcodesS[] = {
5250 ARM::MVE_VMLALDAVs16, ARM::MVE_VMLALDAVs32,
5251 ARM::MVE_VMLALDAVas16, ARM::MVE_VMLALDAVas32,
5252 ARM::MVE_VMLALDAVxs16, ARM::MVE_VMLALDAVxs32,
5253 ARM::MVE_VMLALDAVaxs16, ARM::MVE_VMLALDAVaxs32,
5254 ARM::MVE_VMLSLDAVs16, ARM::MVE_VMLSLDAVs32,
5255 ARM::MVE_VMLSLDAVas16, ARM::MVE_VMLSLDAVas32,
5256 ARM::MVE_VMLSLDAVxs16, ARM::MVE_VMLSLDAVxs32,
5257 ARM::MVE_VMLSLDAVaxs16, ARM::MVE_VMLSLDAVaxs32,
5259 SelectMVE_VMLLDAV(
N, IntNo == Intrinsic::arm_mve_vmlldava_predicated,
5260 OpcodesS, OpcodesU);
5264 case Intrinsic::arm_mve_vrmlldavha:
5265 case Intrinsic::arm_mve_vrmlldavha_predicated: {
5266 static const uint16_t OpcodesU[] = {
5267 ARM::MVE_VRMLALDAVHu32, ARM::MVE_VRMLALDAVHau32,
5269 static const uint16_t OpcodesS[] = {
5270 ARM::MVE_VRMLALDAVHs32, ARM::MVE_VRMLALDAVHas32,
5271 ARM::MVE_VRMLALDAVHxs32, ARM::MVE_VRMLALDAVHaxs32,
5272 ARM::MVE_VRMLSLDAVHs32, ARM::MVE_VRMLSLDAVHas32,
5273 ARM::MVE_VRMLSLDAVHxs32, ARM::MVE_VRMLSLDAVHaxs32,
5275 SelectMVE_VRMLLDAVH(
N, IntNo == Intrinsic::arm_mve_vrmlldavha_predicated,
5276 OpcodesS, OpcodesU);
5280 case Intrinsic::arm_mve_vidup:
5281 case Intrinsic::arm_mve_vidup_predicated: {
5282 static const uint16_t Opcodes[] = {
5283 ARM::MVE_VIDUPu8, ARM::MVE_VIDUPu16, ARM::MVE_VIDUPu32,
5285 SelectMVE_VxDUP(
N, Opcodes,
false,
5286 IntNo == Intrinsic::arm_mve_vidup_predicated);
5290 case Intrinsic::arm_mve_vddup:
5291 case Intrinsic::arm_mve_vddup_predicated: {
5292 static const uint16_t Opcodes[] = {
5293 ARM::MVE_VDDUPu8, ARM::MVE_VDDUPu16, ARM::MVE_VDDUPu32,
5295 SelectMVE_VxDUP(
N, Opcodes,
false,
5296 IntNo == Intrinsic::arm_mve_vddup_predicated);
5300 case Intrinsic::arm_mve_viwdup:
5301 case Intrinsic::arm_mve_viwdup_predicated: {
5302 static const uint16_t Opcodes[] = {
5303 ARM::MVE_VIWDUPu8, ARM::MVE_VIWDUPu16, ARM::MVE_VIWDUPu32,
5305 SelectMVE_VxDUP(
N, Opcodes,
true,
5306 IntNo == Intrinsic::arm_mve_viwdup_predicated);
5310 case Intrinsic::arm_mve_vdwdup:
5311 case Intrinsic::arm_mve_vdwdup_predicated: {
5312 static const uint16_t Opcodes[] = {
5313 ARM::MVE_VDWDUPu8, ARM::MVE_VDWDUPu16, ARM::MVE_VDWDUPu32,
5315 SelectMVE_VxDUP(
N, Opcodes,
true,
5316 IntNo == Intrinsic::arm_mve_vdwdup_predicated);
5320 case Intrinsic::arm_cde_cx1d:
5321 case Intrinsic::arm_cde_cx1da:
5322 case Intrinsic::arm_cde_cx2d:
5323 case Intrinsic::arm_cde_cx2da:
5324 case Intrinsic::arm_cde_cx3d:
5325 case Intrinsic::arm_cde_cx3da: {
5326 bool HasAccum = IntNo == Intrinsic::arm_cde_cx1da ||
5327 IntNo == Intrinsic::arm_cde_cx2da ||
5328 IntNo == Intrinsic::arm_cde_cx3da;
5332 case Intrinsic::arm_cde_cx1d:
5333 case Intrinsic::arm_cde_cx1da:
5335 Opcode = HasAccum ? ARM::CDE_CX1DA : ARM::CDE_CX1D;
5337 case Intrinsic::arm_cde_cx2d:
5338 case Intrinsic::arm_cde_cx2da:
5340 Opcode = HasAccum ? ARM::CDE_CX2DA : ARM::CDE_CX2D;
5342 case Intrinsic::arm_cde_cx3d:
5343 case Intrinsic::arm_cde_cx3da:
5345 Opcode = HasAccum ? ARM::CDE_CX3DA : ARM::CDE_CX3D;
5350 SelectCDE_CXxD(
N, Opcode, NumExtraOps, HasAccum);
5373 std::vector<SDValue> &
Ops) {
5375 RegString.
split(Fields,
':');
5377 if (Fields.
size() > 1) {
5378 bool AllIntFields =
true;
5383 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
5388 "Unexpected non-integer value in special register string.");
5399 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.
lower());
5402 return TheReg->Encoding;
5414 .
Case(
"nzcvqg", 0x3)
5422 auto TheReg = ARMSysReg::lookupMClassSysRegByName(
Reg);
5423 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
5424 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
5426 return (
int)(TheReg->Encoding & 0xFFF);
5435 if (
Reg ==
"apsr") {
5445 if (
Reg !=
"cpsr" &&
Reg !=
"spsr") {
5450 if (Flags.empty() || Flags ==
"all")
5455 for (
char Flag : Flags) {
5475 if (!FlagVal || (Mask & FlagVal))
5490bool ARMDAGToDAGISel::tryReadRegister(SDNode *
N){
5492 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5493 bool IsThumb2 = Subtarget->
isThumb2();
5496 std::vector<SDValue>
Ops;
5506 if (
Ops.size() == 5){
5507 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
5508 ResTypes.
append({ MVT::i32, MVT::Other });
5511 "Invalid number of fields in special register string.");
5512 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
5513 ResTypes.
append({ MVT::i32, MVT::i32, MVT::Other });
5517 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5518 Ops.push_back(
N->getOperand(0));
5519 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, ResTypes,
Ops));
5523 std::string SpecialReg = RegString->getString().lower();
5526 if (BankedReg != -1) {
5527 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
5528 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5531 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
5532 DL, MVT::i32, MVT::Other,
Ops));
5539 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5540 .Case(
"fpscr", ARM::VMRS)
5541 .Case(
"fpexc", ARM::VMRS_FPEXC)
5542 .Case(
"fpsid", ARM::VMRS_FPSID)
5543 .Case(
"mvfr0", ARM::VMRS_MVFR0)
5544 .Case(
"mvfr1", ARM::VMRS_MVFR1)
5545 .Case(
"mvfr2", ARM::VMRS_MVFR2)
5546 .Case(
"fpinst", ARM::VMRS_FPINST)
5547 .Case(
"fpinst2", ARM::VMRS_FPINST2)
5557 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5560 CurDAG->getMachineNode(Opcode,
DL, MVT::i32, MVT::Other,
Ops));
5569 if (SYSmValue == -1)
5572 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5573 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5576 N, CurDAG->getMachineNode(ARM::t2MRS_M,
DL, MVT::i32, MVT::Other,
Ops));
5582 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
5583 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5585 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
5586 DL, MVT::i32, MVT::Other,
Ops));
5590 if (SpecialReg ==
"spsr") {
5591 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5594 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
DL,
5595 MVT::i32, MVT::Other,
Ops));
5605bool ARMDAGToDAGISel::tryWriteRegister(SDNode *
N){
5607 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5608 bool IsThumb2 = Subtarget->
isThumb2();
5611 std::vector<SDValue>
Ops;
5620 if (
Ops.size() == 5) {
5621 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
5622 Ops.insert(
Ops.begin()+2,
N->getOperand(2));
5625 "Invalid number of fields in special register string.");
5626 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
5627 SDValue WriteValue[] = {
N->getOperand(2),
N->getOperand(3) };
5628 Ops.insert(
Ops.begin()+2, WriteValue, WriteValue+2);
5632 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5633 Ops.push_back(
N->getOperand(0));
5635 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5639 std::string SpecialReg = RegString->getString().lower();
5641 if (BankedReg != -1) {
5642 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
N->getOperand(2),
5643 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5646 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
5647 DL, MVT::Other,
Ops));
5654 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5655 .Case(
"fpscr", ARM::VMSR)
5656 .Case(
"fpexc", ARM::VMSR_FPEXC)
5657 .Case(
"fpsid", ARM::VMSR_FPSID)
5658 .Case(
"fpinst", ARM::VMSR_FPINST)
5659 .Case(
"fpinst2", ARM::VMSR_FPINST2)
5666 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5667 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5671 std::pair<StringRef, StringRef> Fields;
5672 Fields = StringRef(SpecialReg).rsplit(
'_');
5673 std::string
Reg = Fields.first.str();
5674 StringRef
Flags = Fields.second;
5680 if (SYSmValue == -1)
5683 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5684 N->getOperand(2),
getAL(CurDAG,
DL),
5685 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5686 ReplaceNode(
N, CurDAG->getMachineNode(ARM::t2MSR_M,
DL, MVT::Other,
Ops));
5695 Ops = { CurDAG->getTargetConstant(Mask,
DL, MVT::i32),
N->getOperand(2),
5696 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5698 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
5699 DL, MVT::Other,
Ops));
5706bool ARMDAGToDAGISel::tryInlineAsm(SDNode *
N){
5707 std::vector<SDValue> AsmNodeOperands;
5708 InlineAsm::Flag
Flag;
5710 unsigned NumOps =
N->getNumOperands();
5725 for(
unsigned i = 0, e =
N->getGluedNode() ?
NumOps - 1 :
NumOps; i < e; ++i) {
5727 AsmNodeOperands.push_back(
op);
5733 Flag = InlineAsm::Flag(
C->getZExtValue());
5741 if (
Flag.isImmKind()) {
5743 AsmNodeOperands.push_back(
op);
5747 const unsigned NumRegs =
Flag.getNumOperandRegisters();
5751 unsigned DefIdx = 0;
5752 bool IsTiedToChangedOp =
false;
5755 if (
Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
5756 IsTiedToChangedOp = OpChanged[DefIdx];
5763 if (
Flag.isMemKind()) {
5765 AsmNodeOperands.push_back(
op);
5769 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
5770 !
Flag.isRegDefEarlyClobberKind())
5774 const bool HasRC =
Flag.hasRegClassConstraint(RC);
5775 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
5779 assert((i+2 <
NumOps) &&
"Invalid number of operands in inline asm");
5787 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
5792 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5795 SDNode *GU =
N->getGluedUser();
5796 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
5800 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
5802 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
5804 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
5810 Ops.push_back(
T1.getValue(1));
5811 CurDAG->UpdateNodeOperands(GU,
Ops);
5818 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
5820 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
5827 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5828 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
5837 OpChanged[OpChanged.
size() -1 ] =
true;
5838 Flag = InlineAsm::Flag(
Flag.getKind(), 1 );
5839 if (IsTiedToChangedOp)
5840 Flag.setMatchingOp(DefIdx);
5842 Flag.setRegClass(ARM::GPRPairRegClassID);
5844 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
5845 Flag, dl, MVT::i32);
5847 AsmNodeOperands.push_back(PairedReg);
5854 AsmNodeOperands.push_back(Glue);
5858 SDValue New = CurDAG->getNode(
N->getOpcode(), SDLoc(
N),
5859 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
5861 ReplaceNode(
N,
New.getNode());
5865bool ARMDAGToDAGISel::SelectInlineAsmMemoryOperand(
5867 std::vector<SDValue> &OutOps) {
5868 switch(ConstraintID) {
5871 case InlineAsm::ConstraintCode::m:
5872 case InlineAsm::ConstraintCode::o:
5873 case InlineAsm::ConstraintCode::Q:
5874 case InlineAsm::ConstraintCode::Um:
5875 case InlineAsm::ConstraintCode::Un:
5876 case InlineAsm::ConstraintCode::Uq:
5877 case InlineAsm::ConstraintCode::Us:
5878 case InlineAsm::ConstraintCode::Ut:
5879 case InlineAsm::ConstraintCode::Uv:
5880 case InlineAsm::ConstraintCode::Uy:
5884 OutOps.push_back(
Op);
5895 return new ARMDAGToDAGISelLegacy(TM, OptLevel);
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Promote Memory to Register
MachineInstr unsigned OpIdx
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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.
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
bool isThumb1Only() const
bool hasFPARMv8Base() const
uint64_t getZExtValue() const
Container class for subtarget features.
FunctionPass class - This class is used to implement most global optimizations.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool mayStore() const
Return true if this instruction could possibly modify memory.
unsigned getOpcode() const
Return the opcode number for this descriptor.
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.
const MachineOperand & getOperand(unsigned i) const
@ MOLoad
The memory access reads data.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
EVT getMemoryVT() const
Return the type of the in-memory value.
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
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 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.
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.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< NodeBase * > Node
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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.
DWARFExpression::Operation Op
@ NearestTiesToEven
roundTiesToEven.
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
constexpr 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 is64BitVector() const
Return true if this is a 64-bit vector type.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.