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 tryReadRegister(SDNode *
N);
310 bool tryWriteRegister(SDNode *
N);
312 bool tryInlineAsm(SDNode *
N);
314 void SelectCMPZ(SDNode *
N,
bool &SwitchEQNEToPLMI);
316 void SelectCMP_SWAP(SDNode *
N);
320 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
322 std::vector<SDValue> &OutOps)
override;
336 SDValue GetVLDSTAlign(
SDValue Align,
const SDLoc &dl,
unsigned NumVecs,
344 bool canExtractShiftFromMul(
const SDValue &
N,
unsigned MaxShift,
345 unsigned &PowerOfTwo,
SDValue &NewMulConst)
const;
355 ARMDAGToDAGISelLegacy(ARMBaseTargetMachine &tm,
CodeGenOptLevel OptLevel)
356 : SelectionDAGISelLegacy(
357 ID, std::make_unique<ARMDAGToDAGISel>(tm, OptLevel)) {}
361char ARMDAGToDAGISelLegacy::ID = 0;
368 if (
N->getOpcode() ==
ISD::Constant &&
N->getValueType(0) == MVT::i32) {
369 Imm = N->getAsZExtVal();
385 return N->getOpcode() ==
Opc &&
394 int RangeMin,
int RangeMax,
395 int &ScaledConstant) {
396 assert(Scale > 0 &&
"Invalid scale!");
403 ScaledConstant = (int)
C->getZExtValue();
404 if ((ScaledConstant % Scale) != 0)
407 ScaledConstant /= Scale;
408 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
411void ARMDAGToDAGISel::PreprocessISelDAG() {
412 if (!Subtarget->hasV6T2Ops())
415 bool isThumb2 = Subtarget->isThumb();
432 unsigned And_imm = 0;
442 if (TZ != 1 && TZ != 2)
454 if (And_imm & (And_imm + 1))
459 unsigned Srl_imm = 0;
470 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
473 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
474 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
479 Srl = CurDAG->getNode(
ISD::SRL, SDLoc(Srl), MVT::i32,
481 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
483 N1 = CurDAG->getNode(
ISD::AND, SDLoc(N1), MVT::i32,
485 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
486 N1 = CurDAG->getNode(
ISD::SHL, SDLoc(N1), MVT::i32,
487 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
488 CurDAG->UpdateNodeOperands(&
N, N0, N1);
495bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *
N)
const {
496 if (OptLevel == CodeGenOptLevel::None)
499 if (!Subtarget->hasVMLxHazards())
505 SDNode *
User = *
N->user_begin();
508 if (
User->isMachineOpcode()) {
509 const ARMBaseInstrInfo *
TII =
static_cast<const ARMBaseInstrInfo *
>(
510 CurDAG->getSubtarget().getInstrInfo());
512 const MCInstrDesc &MCID =
TII->get(
User->getMachineOpcode());
516 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
531 return TII->isFpMLxInstruction(Opcode);
537bool ARMDAGToDAGISel::isShifterOpProfitable(
const SDValue &Shift,
546 (ShAmt == 2 || (Subtarget->
isSwift() && ShAmt == 1));
549bool ARMDAGToDAGISel::canExtractShiftFromMul(
const SDValue &
N,
551 unsigned &PowerOfTwo,
558 if (!
N.hasOneUse())
return false;
561 if (!MulConst)
return false;
564 if (!MulConst->
hasOneUse())
return false;
566 if (MulConstVal == 0)
return false;
569 PowerOfTwo = MaxShift;
570 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
572 if (PowerOfTwo == 0)
return false;
576 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
577 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(
N), MVT::i32);
580 return NewCost < OldCost;
584 CurDAG->RepositionNode(
N.getNode()->getIterator(),
M.getNode());
588bool ARMDAGToDAGISel::SelectImmShifterOperand(
SDValue N,
591 bool CheckProfitability) {
598 unsigned PowerOfTwo = 0;
600 if (canExtractShiftFromMul(
N, 31, PowerOfTwo, NewMulConst)) {
601 HandleSDNode Handle(
N);
603 replaceDAGValue(
N.getOperand(1), NewMulConst);
605 Opc = CurDAG->getTargetConstant(
618 unsigned ShImmVal = 0;
620 if (!
RHS)
return false;
621 ShImmVal =
RHS->getZExtValue() & 31;
627bool ARMDAGToDAGISel::SelectRegShifterOperand(
SDValue N,
631 bool CheckProfitability) {
642 unsigned ShImmVal = 0;
644 if (
RHS)
return false;
647 if (CheckProfitability && !isShifterOpProfitable(
N, ShOpcVal, ShImmVal))
656bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent,
SDValue N,
SDValue &Out) {
659 return CurDAG->haveNoCommonBitsSet(
N, Parent->
getOperand(1));
663bool ARMDAGToDAGISel::SelectAddrModeImm12(
SDValue N,
670 !CurDAG->isBaseWithConstantOffset(
N)) {
674 Base = CurDAG->getTargetFrameIndex(
675 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
676 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
684 Base =
N.getOperand(0);
687 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
692 int RHSC = (int)
RHS->getSExtValue();
696 if (RHSC > -0x1000 && RHSC < 0x1000) {
697 Base =
N.getOperand(0);
700 Base = CurDAG->getTargetFrameIndex(
701 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
703 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
710 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
722 int RHSC = (int)
RHS->getZExtValue();
731 unsigned ShAmt =
Log2_32(RHSC);
744 !CurDAG->isBaseWithConstantOffset(
N))
751 -0x1000+1, 0x1000, RHSC))
761 Base =
N.getOperand(0);
767 if (ConstantSDNode *Sh =
769 ShAmt = Sh->getZExtValue();
770 if (isShifterOpProfitable(
Offset, ShOpcVal, ShAmt))
771 Offset =
N.getOperand(1).getOperand(0);
784 N.getOperand(0).hasOneUse())) {
789 if (ConstantSDNode *Sh =
791 ShAmt = Sh->getZExtValue();
792 if (isShifterOpProfitable(
N.getOperand(0), ShOpcVal, ShAmt)) {
793 Offset =
N.getOperand(0).getOperand(0);
794 Base =
N.getOperand(1);
808 unsigned PowerOfTwo = 0;
810 if (canExtractShiftFromMul(
Offset, 31, PowerOfTwo, NewMulConst)) {
811 HandleSDNode Handle(
Offset);
812 replaceDAGValue(
Offset.getOperand(1), NewMulConst);
813 Offset = Handle.getValue();
824bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *
Op,
SDValue N,
826 unsigned Opcode =
Op->getOpcode();
843 ShAmt = Sh->getZExtValue();
844 if (isShifterOpProfitable(
N, ShOpcVal, ShAmt))
860bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *
Op,
SDValue N,
862 unsigned Opcode =
Op->getOpcode();
871 Offset = CurDAG->getRegister(0, MVT::i32);
872 Opc = CurDAG->getSignedTargetConstant(Val, SDLoc(
Op), MVT::i32);
880bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *
Op,
SDValue N,
882 unsigned Opcode =
Op->getOpcode();
890 Offset = CurDAG->getRegister(0, MVT::i32);
893 SDLoc(
Op), MVT::i32);
905bool ARMDAGToDAGISel::SelectAddrMode3(
SDValue N,
910 Base =
N.getOperand(0);
917 if (!CurDAG->isBaseWithConstantOffset(
N)) {
921 Base = CurDAG->getTargetFrameIndex(
922 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
924 Offset = CurDAG->getRegister(0, MVT::i32);
933 -256 + 1, 256, RHSC)) {
934 Base =
N.getOperand(0);
937 Base = CurDAG->getTargetFrameIndex(
938 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
940 Offset = CurDAG->getRegister(0, MVT::i32);
952 Base =
N.getOperand(0);
959bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *
Op,
SDValue N,
961 unsigned Opcode =
Op->getOpcode();
969 Offset = CurDAG->getRegister(0, MVT::i32);
983 if (!CurDAG->isBaseWithConstantOffset(
N)) {
987 Base = CurDAG->getTargetFrameIndex(
988 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
993 Base =
N.getOperand(0);
1002 const int Scale = FP16 ? 2 : 4;
1005 Base =
N.getOperand(0);
1008 Base = CurDAG->getTargetFrameIndex(
1009 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1020 SDLoc(
N), MVT::i32);
1023 SDLoc(
N), MVT::i32);
1032 SDLoc(
N), MVT::i32);
1035 SDLoc(
N), MVT::i32);
1040bool ARMDAGToDAGISel::SelectAddrMode5(
SDValue N,
1045bool ARMDAGToDAGISel::SelectAddrMode5FP16(
SDValue N,
1050bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent,
SDValue N,
SDValue &Addr,
1054 unsigned Alignment = 0;
1064 llvm::Align MMOAlign = MemN->
getAlign();
1066 if (MMOAlign.
value() >= MemSize && MemSize > 1)
1067 Alignment = MemSize;
1075 Align = CurDAG->getTargetConstant(Alignment, SDLoc(
N), MVT::i32);
1079bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *
Op,
SDValue N,
1088 Offset = CurDAG->getRegister(0, MVT::i32);
1093bool ARMDAGToDAGISel::SelectAddrModePC(
SDValue N,
1119 return C->getSExtValue() < 0 &&
C->getSExtValue() >= -255;
1126 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N)) {
1134 Base =
N.getOperand(0);
1143 return SelectThumbAddrModeRRSext(
N,
Base,
Offset);
1147ARMDAGToDAGISel::SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
1151 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1155 if (!CurDAG->isBaseWithConstantOffset(
N)) {
1163 Base =
N.getOperand(0);
1168 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1175 Base =
N.getOperand(0);
1176 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1187 return SelectThumbAddrModeImm5S(
N, 4,
Base, OffImm);
1193 return SelectThumbAddrModeImm5S(
N, 2,
Base, OffImm);
1199 return SelectThumbAddrModeImm5S(
N, 1,
Base, OffImm);
1202bool ARMDAGToDAGISel::SelectThumbAddrModeSP(
SDValue N,
1208 MachineFrameInfo &MFI = MF->getFrameInfo();
1211 Base = CurDAG->getTargetFrameIndex(
1212 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1213 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1217 if (!CurDAG->isBaseWithConstantOffset(
N))
1224 Base =
N.getOperand(0);
1229 MachineFrameInfo &MFI = MF->getFrameInfo();
1236 Base = CurDAG->getTargetFrameIndex(
1237 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1238 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1248template <
unsigned Shift>
1251 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1255 Base =
N.getOperand(0);
1258 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1266 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1276bool ARMDAGToDAGISel::SelectT2AddrModeImm12(
SDValue N,
1282 !CurDAG->isBaseWithConstantOffset(
N)) {
1286 Base = CurDAG->getTargetFrameIndex(
1287 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1288 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1296 Base =
N.getOperand(0);
1301 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1306 if (SelectT2AddrModeImm8(
N,
Base, OffImm))
1310 int RHSC = (int)
RHS->getZExtValue();
1314 if (RHSC >= 0 && RHSC < 0x1000) {
1315 Base =
N.getOperand(0);
1318 Base = CurDAG->getTargetFrameIndex(
1319 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1321 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1328 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1332template <
unsigned Shift>
1335 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1338 Base =
N.getOperand(0);
1341 Base = CurDAG->getTargetFrameIndex(
1342 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1347 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1355 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1359bool ARMDAGToDAGISel::SelectT2AddrModeImm8(
SDValue N,
1363 !CurDAG->isBaseWithConstantOffset(
N))
1367 int RHSC = (int)
RHS->getSExtValue();
1371 if ((RHSC >= -255) && (RHSC < 0)) {
1372 Base =
N.getOperand(0);
1375 Base = CurDAG->getTargetFrameIndex(
1376 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1378 OffImm = CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32);
1386bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *
Op,
SDValue N,
1388 unsigned Opcode =
Op->getOpcode();
1395 ? CurDAG->getSignedTargetConstant(RHSC, SDLoc(
N), MVT::i32)
1396 : CurDAG->getSignedTargetConstant(-RHSC, SDLoc(
N), MVT::i32);
1403template <
unsigned Shift>
1406 if (
N.getOpcode() ==
ISD::SUB || CurDAG->isBaseWithConstantOffset(
N)) {
1410 Base =
N.getOperand(0);
1413 Base = CurDAG->getTargetFrameIndex(
1414 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1419 OffImm = CurDAG->getSignedTargetConstant(RHSC * (1 << Shift), SDLoc(
N),
1427 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1431template <
unsigned Shift>
1432bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *
Op,
SDValue N,
1434 return SelectT2AddrModeImm7Offset(
Op,
N, OffImm, Shift);
1437bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *
Op,
SDValue N,
1440 unsigned Opcode =
Op->getOpcode();
1463 ? CurDAG->getSignedTargetConstant(RHSC * (1 << Shift),
1465 : CurDAG->getSignedTargetConstant(-RHSC * (1 << Shift),
1466 SDLoc(
N), MVT::i32);
1472template <
int Min,
int Max>
1473bool ARMDAGToDAGISel::SelectImmediateInRange(
SDValue N,
SDValue &OffImm) {
1476 OffImm = CurDAG->getSignedTargetConstant(Val, SDLoc(
N), MVT::i32);
1482bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(
SDValue N,
1486 if (
N.getOpcode() !=
ISD::ADD && !CurDAG->isBaseWithConstantOffset(
N))
1491 int RHSC = (int)
RHS->getZExtValue();
1492 if (RHSC >= 0 && RHSC < 0x1000)
1494 else if (RHSC < 0 && RHSC >= -255)
1500 Base =
N.getOperand(0);
1515 ShAmt = Sh->getZExtValue();
1516 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1527 unsigned PowerOfTwo = 0;
1529 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1530 HandleSDNode Handle(OffReg);
1531 replaceDAGValue(OffReg.
getOperand(1), NewMulConst);
1537 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(
N), MVT::i32);
1547 OffImm = CurDAG->getTargetConstant(0, SDLoc(
N), MVT::i32);
1549 if (
N.getOpcode() !=
ISD::ADD || !CurDAG->isBaseWithConstantOffset(
N))
1556 uint32_t RHSC = (int)
RHS->getZExtValue();
1557 if (RHSC > 1020 || RHSC % 4 != 0)
1560 Base =
N.getOperand(0);
1563 Base = CurDAG->getTargetFrameIndex(
1564 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1567 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(
N), MVT::i32);
1578void ARMDAGToDAGISel::transferMemOperands(SDNode *
N, SDNode *Result) {
1583bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *
N) {
1589 EVT LoadedVT =
LD->getMemoryVT();
1592 unsigned Opcode = 0;
1594 if (LoadedVT == MVT::i32 && isPre &&
1595 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1596 Opcode = ARM::LDR_PRE_IMM;
1598 }
else if (LoadedVT == MVT::i32 && !isPre &&
1599 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1600 Opcode = ARM::LDR_POST_IMM;
1602 }
else if (LoadedVT == MVT::i32 &&
1603 SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1604 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1607 }
else if (LoadedVT == MVT::i16 &&
1608 SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1611 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1612 : (isPre ?
ARM::LDRH_PRE :
ARM::LDRH_POST);
1613 }
else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
1615 if (SelectAddrMode3Offset(
N,
LD->getOffset(),
Offset, AMOpc)) {
1617 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1621 SelectAddrMode2OffsetImmPre(
N,
LD->getOffset(),
Offset, AMOpc)) {
1623 Opcode = ARM::LDRB_PRE_IMM;
1624 }
else if (!isPre &&
1625 SelectAddrMode2OffsetImm(
N,
LD->getOffset(),
Offset, AMOpc)) {
1627 Opcode = ARM::LDRB_POST_IMM;
1628 }
else if (SelectAddrMode2OffsetReg(
N,
LD->getOffset(),
Offset, AMOpc)) {
1630 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1636 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1640 CurDAG->getRegister(0, MVT::i32), Chain };
1641 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1643 transferMemOperands(
N, New);
1644 ReplaceNode(
N, New);
1650 CurDAG->getRegister(0, MVT::i32), Chain };
1651 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1653 transferMemOperands(
N, New);
1654 ReplaceNode(
N, New);
1662bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *
N) {
1664 EVT LoadedVT =
LD->getMemoryVT();
1671 if (!COffs || COffs->getZExtValue() != 4)
1681 CurDAG->getRegister(0, MVT::i32), Chain };
1682 SDNode *
New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(
N), MVT::i32,
1683 MVT::i32, MVT::Other,
Ops);
1684 transferMemOperands(
N, New);
1685 ReplaceNode(
N, New);
1689bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *
N) {
1695 EVT LoadedVT =
LD->getMemoryVT();
1699 unsigned Opcode = 0;
1701 if (SelectT2AddrModeImm8Offset(
N,
LD->getOffset(),
Offset)) {
1704 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1708 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1710 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1715 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1717 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1729 CurDAG->getRegister(0, MVT::i32), Chain };
1730 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32, MVT::i32,
1732 transferMemOperands(
N, New);
1733 ReplaceNode(
N, New);
1740bool ARMDAGToDAGISel::tryMVEIndexedLoad(SDNode *
N) {
1742 unsigned Opcode = 0;
1743 bool isSExtLd, isPre;
1753 LoadedVT =
LD->getMemoryVT();
1757 Chain =
LD->getChain();
1760 Alignment =
LD->getAlign();
1764 PredReg = CurDAG->getRegister(0, MVT::i32);
1769 LoadedVT =
LD->getMemoryVT();
1773 Chain =
LD->getChain();
1776 Alignment =
LD->getAlign();
1780 PredReg =
LD->getMask();
1790 if (Alignment >=
Align(2) && LoadedVT == MVT::v4i16 &&
1791 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1)) {
1793 Opcode = isPre ? ARM::MVE_VLDRHS32_pre : ARM::MVE_VLDRHS32_post;
1795 Opcode = isPre ? ARM::MVE_VLDRHU32_pre : ARM::MVE_VLDRHU32_post;
1796 }
else if (LoadedVT == MVT::v8i8 &&
1797 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1799 Opcode = isPre ? ARM::MVE_VLDRBS16_pre : ARM::MVE_VLDRBS16_post;
1801 Opcode = isPre ? ARM::MVE_VLDRBU16_pre : ARM::MVE_VLDRBU16_post;
1802 }
else if (LoadedVT == MVT::v4i8 &&
1803 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0)) {
1805 Opcode = isPre ? ARM::MVE_VLDRBS32_pre : ARM::MVE_VLDRBS32_post;
1807 Opcode = isPre ? ARM::MVE_VLDRBU32_pre : ARM::MVE_VLDRBU32_post;
1808 }
else if (Alignment >=
Align(4) &&
1809 (CanChangeType || LoadedVT == MVT::v4i32 ||
1810 LoadedVT == MVT::v4f32) &&
1811 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 2))
1812 Opcode = isPre ? ARM::MVE_VLDRWU32_pre : ARM::MVE_VLDRWU32_post;
1813 else if (Alignment >=
Align(2) &&
1814 (CanChangeType || LoadedVT == MVT::v8i16 ||
1815 LoadedVT == MVT::v8f16) &&
1816 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 1))
1817 Opcode = isPre ? ARM::MVE_VLDRHU16_pre : ARM::MVE_VLDRHU16_post;
1818 else if ((CanChangeType || LoadedVT == MVT::v16i8) &&
1819 SelectT2AddrModeImm7Offset(
N,
Offset, NewOffset, 0))
1820 Opcode = isPre ? ARM::MVE_VLDRBU8_pre : ARM::MVE_VLDRBU8_post;
1826 CurDAG->getTargetConstant(Pred, SDLoc(
N), MVT::i32),
1828 CurDAG->getRegister(0, MVT::i32),
1830 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), MVT::i32,
1831 N->getValueType(0), MVT::Other,
Ops);
1832 transferMemOperands(
N, New);
1836 CurDAG->RemoveDeadNode(
N);
1841SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1844 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1845 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1846 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
1847 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1848 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1852SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1855 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1856 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1857 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1858 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1859 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1863SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1865 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1867 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1868 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1869 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1870 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1874SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT,
SDValue V0,
SDValue V1) {
1876 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1878 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1879 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1880 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1881 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1885SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1889 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1890 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1891 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1892 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1893 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
1894 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1895 V2, SubReg2, V3, SubReg3 };
1896 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1900SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1903 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1905 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1906 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1907 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1908 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
1909 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1910 V2, SubReg2, V3, SubReg3 };
1911 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1915SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT,
SDValue V0,
SDValue V1,
1918 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1920 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1921 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1922 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1923 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
1924 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1925 V2, SubReg2, V3, SubReg3 };
1926 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT,
Ops);
1932SDValue ARMDAGToDAGISel::GetVLDSTAlign(
SDValue Align,
const SDLoc &dl,
1933 unsigned NumVecs,
bool is64BitVector) {
1934 unsigned NumRegs = NumVecs;
1935 if (!is64BitVector && NumVecs < 3)
1938 unsigned Alignment =
Align->getAsZExtVal();
1939 if (Alignment >= 32 && NumRegs == 4)
1941 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1943 else if (Alignment >= 8)
1948 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
1954 default:
return false;
1955 case ARM::VLD1d8wb_fixed :
return true;
1956 case ARM::VLD1d16wb_fixed :
return true;
1957 case ARM::VLD1d64Qwb_fixed :
return true;
1958 case ARM::VLD1d32wb_fixed :
return true;
1959 case ARM::VLD1d64wb_fixed :
return true;
1960 case ARM::VLD1d8TPseudoWB_fixed :
return true;
1961 case ARM::VLD1d16TPseudoWB_fixed :
return true;
1962 case ARM::VLD1d32TPseudoWB_fixed :
return true;
1963 case ARM::VLD1d64TPseudoWB_fixed :
return true;
1964 case ARM::VLD1d8QPseudoWB_fixed :
return true;
1965 case ARM::VLD1d16QPseudoWB_fixed :
return true;
1966 case ARM::VLD1d32QPseudoWB_fixed :
return true;
1967 case ARM::VLD1d64QPseudoWB_fixed :
return true;
1968 case ARM::VLD1q8wb_fixed :
return true;
1969 case ARM::VLD1q16wb_fixed :
return true;
1970 case ARM::VLD1q32wb_fixed :
return true;
1971 case ARM::VLD1q64wb_fixed :
return true;
1972 case ARM::VLD1DUPd8wb_fixed :
return true;
1973 case ARM::VLD1DUPd16wb_fixed :
return true;
1974 case ARM::VLD1DUPd32wb_fixed :
return true;
1975 case ARM::VLD1DUPq8wb_fixed :
return true;
1976 case ARM::VLD1DUPq16wb_fixed :
return true;
1977 case ARM::VLD1DUPq32wb_fixed :
return true;
1978 case ARM::VLD2d8wb_fixed :
return true;
1979 case ARM::VLD2d16wb_fixed :
return true;
1980 case ARM::VLD2d32wb_fixed :
return true;
1981 case ARM::VLD2q8PseudoWB_fixed :
return true;
1982 case ARM::VLD2q16PseudoWB_fixed :
return true;
1983 case ARM::VLD2q32PseudoWB_fixed :
return true;
1984 case ARM::VLD2DUPd8wb_fixed :
return true;
1985 case ARM::VLD2DUPd16wb_fixed :
return true;
1986 case ARM::VLD2DUPd32wb_fixed :
return true;
1987 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return true;
1988 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return true;
1989 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return true;
1996 default:
return false;
1997 case ARM::VST1d8wb_fixed :
return true;
1998 case ARM::VST1d16wb_fixed :
return true;
1999 case ARM::VST1d32wb_fixed :
return true;
2000 case ARM::VST1d64wb_fixed :
return true;
2001 case ARM::VST1q8wb_fixed :
return true;
2002 case ARM::VST1q16wb_fixed :
return true;
2003 case ARM::VST1q32wb_fixed :
return true;
2004 case ARM::VST1q64wb_fixed :
return true;
2005 case ARM::VST1d8TPseudoWB_fixed :
return true;
2006 case ARM::VST1d16TPseudoWB_fixed :
return true;
2007 case ARM::VST1d32TPseudoWB_fixed :
return true;
2008 case ARM::VST1d64TPseudoWB_fixed :
return true;
2009 case ARM::VST1d8QPseudoWB_fixed :
return true;
2010 case ARM::VST1d16QPseudoWB_fixed :
return true;
2011 case ARM::VST1d32QPseudoWB_fixed :
return true;
2012 case ARM::VST1d64QPseudoWB_fixed :
return true;
2013 case ARM::VST2d8wb_fixed :
return true;
2014 case ARM::VST2d16wb_fixed :
return true;
2015 case ARM::VST2d32wb_fixed :
return true;
2016 case ARM::VST2q8PseudoWB_fixed :
return true;
2017 case ARM::VST2q16PseudoWB_fixed :
return true;
2018 case ARM::VST2q32PseudoWB_fixed :
return true;
2026 &&
"Incorrect fixed stride updating instruction.");
2029 case ARM::VLD1d8wb_fixed:
return ARM::VLD1d8wb_register;
2030 case ARM::VLD1d16wb_fixed:
return ARM::VLD1d16wb_register;
2031 case ARM::VLD1d32wb_fixed:
return ARM::VLD1d32wb_register;
2032 case ARM::VLD1d64wb_fixed:
return ARM::VLD1d64wb_register;
2033 case ARM::VLD1q8wb_fixed:
return ARM::VLD1q8wb_register;
2034 case ARM::VLD1q16wb_fixed:
return ARM::VLD1q16wb_register;
2035 case ARM::VLD1q32wb_fixed:
return ARM::VLD1q32wb_register;
2036 case ARM::VLD1q64wb_fixed:
return ARM::VLD1q64wb_register;
2037 case ARM::VLD1d64Twb_fixed:
return ARM::VLD1d64Twb_register;
2038 case ARM::VLD1d64Qwb_fixed:
return ARM::VLD1d64Qwb_register;
2039 case ARM::VLD1d8TPseudoWB_fixed:
return ARM::VLD1d8TPseudoWB_register;
2040 case ARM::VLD1d16TPseudoWB_fixed:
return ARM::VLD1d16TPseudoWB_register;
2041 case ARM::VLD1d32TPseudoWB_fixed:
return ARM::VLD1d32TPseudoWB_register;
2042 case ARM::VLD1d64TPseudoWB_fixed:
return ARM::VLD1d64TPseudoWB_register;
2043 case ARM::VLD1d8QPseudoWB_fixed:
return ARM::VLD1d8QPseudoWB_register;
2044 case ARM::VLD1d16QPseudoWB_fixed:
return ARM::VLD1d16QPseudoWB_register;
2045 case ARM::VLD1d32QPseudoWB_fixed:
return ARM::VLD1d32QPseudoWB_register;
2046 case ARM::VLD1d64QPseudoWB_fixed:
return ARM::VLD1d64QPseudoWB_register;
2047 case ARM::VLD1DUPd8wb_fixed :
return ARM::VLD1DUPd8wb_register;
2048 case ARM::VLD1DUPd16wb_fixed :
return ARM::VLD1DUPd16wb_register;
2049 case ARM::VLD1DUPd32wb_fixed :
return ARM::VLD1DUPd32wb_register;
2050 case ARM::VLD1DUPq8wb_fixed :
return ARM::VLD1DUPq8wb_register;
2051 case ARM::VLD1DUPq16wb_fixed :
return ARM::VLD1DUPq16wb_register;
2052 case ARM::VLD1DUPq32wb_fixed :
return ARM::VLD1DUPq32wb_register;
2053 case ARM::VLD2DUPq8OddPseudoWB_fixed:
return ARM::VLD2DUPq8OddPseudoWB_register;
2054 case ARM::VLD2DUPq16OddPseudoWB_fixed:
return ARM::VLD2DUPq16OddPseudoWB_register;
2055 case ARM::VLD2DUPq32OddPseudoWB_fixed:
return ARM::VLD2DUPq32OddPseudoWB_register;
2057 case ARM::VST1d8wb_fixed:
return ARM::VST1d8wb_register;
2058 case ARM::VST1d16wb_fixed:
return ARM::VST1d16wb_register;
2059 case ARM::VST1d32wb_fixed:
return ARM::VST1d32wb_register;
2060 case ARM::VST1d64wb_fixed:
return ARM::VST1d64wb_register;
2061 case ARM::VST1q8wb_fixed:
return ARM::VST1q8wb_register;
2062 case ARM::VST1q16wb_fixed:
return ARM::VST1q16wb_register;
2063 case ARM::VST1q32wb_fixed:
return ARM::VST1q32wb_register;
2064 case ARM::VST1q64wb_fixed:
return ARM::VST1q64wb_register;
2065 case ARM::VST1d8TPseudoWB_fixed:
return ARM::VST1d8TPseudoWB_register;
2066 case ARM::VST1d16TPseudoWB_fixed:
return ARM::VST1d16TPseudoWB_register;
2067 case ARM::VST1d32TPseudoWB_fixed:
return ARM::VST1d32TPseudoWB_register;
2068 case ARM::VST1d64TPseudoWB_fixed:
return ARM::VST1d64TPseudoWB_register;
2069 case ARM::VST1d8QPseudoWB_fixed:
return ARM::VST1d8QPseudoWB_register;
2070 case ARM::VST1d16QPseudoWB_fixed:
return ARM::VST1d16QPseudoWB_register;
2071 case ARM::VST1d32QPseudoWB_fixed:
return ARM::VST1d32QPseudoWB_register;
2072 case ARM::VST1d64QPseudoWB_fixed:
return ARM::VST1d64QPseudoWB_register;
2074 case ARM::VLD2d8wb_fixed:
return ARM::VLD2d8wb_register;
2075 case ARM::VLD2d16wb_fixed:
return ARM::VLD2d16wb_register;
2076 case ARM::VLD2d32wb_fixed:
return ARM::VLD2d32wb_register;
2077 case ARM::VLD2q8PseudoWB_fixed:
return ARM::VLD2q8PseudoWB_register;
2078 case ARM::VLD2q16PseudoWB_fixed:
return ARM::VLD2q16PseudoWB_register;
2079 case ARM::VLD2q32PseudoWB_fixed:
return ARM::VLD2q32PseudoWB_register;
2081 case ARM::VST2d8wb_fixed:
return ARM::VST2d8wb_register;
2082 case ARM::VST2d16wb_fixed:
return ARM::VST2d16wb_register;
2083 case ARM::VST2d32wb_fixed:
return ARM::VST2d32wb_register;
2084 case ARM::VST2q8PseudoWB_fixed:
return ARM::VST2q8PseudoWB_register;
2085 case ARM::VST2q16PseudoWB_fixed:
return ARM::VST2q16PseudoWB_register;
2086 case ARM::VST2q32PseudoWB_fixed:
return ARM::VST2q32PseudoWB_register;
2088 case ARM::VLD2DUPd8wb_fixed:
return ARM::VLD2DUPd8wb_register;
2089 case ARM::VLD2DUPd16wb_fixed:
return ARM::VLD2DUPd16wb_register;
2090 case ARM::VLD2DUPd32wb_fixed:
return ARM::VLD2DUPd32wb_register;
2103void ARMDAGToDAGISel::SelectVLD(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2104 const uint16_t *DOpcodes,
2105 const uint16_t *QOpcodes0,
2106 const uint16_t *QOpcodes1) {
2107 assert(Subtarget->hasNEON());
2108 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLD NumVecs out-of-range");
2112 bool IsIntrinsic = !isUpdating;
2114 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2115 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2119 EVT VT =
N->getValueType(0);
2121 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
2149 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2154 std::vector<EVT> ResTys;
2155 ResTys.push_back(ResTy);
2157 ResTys.push_back(MVT::i32);
2158 ResTys.push_back(MVT::Other);
2161 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2166 if (is64BitVector || NumVecs <= 2) {
2169 Ops.push_back(MemAddr);
2170 Ops.push_back(Align);
2172 SDValue Inc =
N->getOperand(AddrOpIdx + 1);
2183 Ops.push_back(Reg0);
2185 Ops.push_back(Pred);
2186 Ops.push_back(Reg0);
2187 Ops.push_back(Chain);
2188 VLd = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2198 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
2199 const SDValue OpsA[] = { MemAddr,
Align, Reg0, ImplDef, Pred, Reg0, Chain };
2200 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl,
2201 ResTy, AddrTy, MVT::Other, OpsA);
2206 Ops.push_back(Align);
2210 "only constant post-increment update allowed for VLD3/4");
2212 Ops.push_back(Reg0);
2215 Ops.push_back(Pred);
2216 Ops.push_back(Reg0);
2217 Ops.push_back(Chain);
2218 VLd = CurDAG->getMachineNode(QOpcodes1[
OpcodeIndex], dl, ResTys,
Ops);
2226 ReplaceNode(
N, VLd);
2232 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2233 ARM::qsub_3 == ARM::qsub_0 + 3,
2234 "Unexpected subreg numbering");
2235 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
2236 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2238 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2242 CurDAG->RemoveDeadNode(
N);
2245void ARMDAGToDAGISel::SelectVST(SDNode *
N,
bool isUpdating,
unsigned NumVecs,
2246 const uint16_t *DOpcodes,
2247 const uint16_t *QOpcodes0,
2248 const uint16_t *QOpcodes1) {
2249 assert(Subtarget->hasNEON());
2250 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VST NumVecs out-of-range");
2254 bool IsIntrinsic = !isUpdating;
2256 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2257 unsigned Vec0Idx = 3;
2258 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2264 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2266 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
2290 std::vector<EVT> ResTys;
2292 ResTys.push_back(MVT::i32);
2293 ResTys.push_back(MVT::Other);
2296 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2300 if (is64BitVector || NumVecs <= 2) {
2304 }
else if (is64BitVector) {
2309 SrcReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2315 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
2317 SrcReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2321 SDValue Q0 =
N->getOperand(Vec0Idx);
2322 SDValue Q1 =
N->getOperand(Vec0Idx + 1);
2323 SrcReg =
SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
2328 Ops.push_back(MemAddr);
2329 Ops.push_back(Align);
2343 Ops.push_back(Reg0);
2345 Ops.push_back(SrcReg);
2346 Ops.push_back(Pred);
2347 Ops.push_back(Reg0);
2348 Ops.push_back(Chain);
2349 SDNode *VSt = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2354 ReplaceNode(
N, VSt);
2366 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2368 SDValue RegSeq =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2372 const SDValue OpsA[] = { MemAddr,
Align, Reg0, RegSeq, Pred, Reg0, Chain };
2373 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl,
2381 Ops.push_back(Align);
2385 "only constant post-increment update allowed for VST3/4");
2387 Ops.push_back(Reg0);
2389 Ops.push_back(RegSeq);
2390 Ops.push_back(Pred);
2391 Ops.push_back(Reg0);
2392 Ops.push_back(Chain);
2393 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[
OpcodeIndex], dl, ResTys,
2396 ReplaceNode(
N, VStB);
2399void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *
N,
bool IsLoad,
bool isUpdating,
2401 const uint16_t *DOpcodes,
2402 const uint16_t *QOpcodes) {
2403 assert(Subtarget->hasNEON());
2404 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDSTLane NumVecs out-of-range");
2408 bool IsIntrinsic = !isUpdating;
2410 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2411 unsigned Vec0Idx = 3;
2412 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2419 EVT VT =
N->getOperand(Vec0Idx).getValueType();
2422 unsigned Alignment = 0;
2424 Alignment =
Align->getAsZExtVal();
2426 if (Alignment > NumBytes)
2427 Alignment = NumBytes;
2428 if (Alignment < 8 && Alignment < NumBytes)
2431 Alignment = (Alignment & -Alignment);
2435 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
2455 std::vector<EVT> ResTys;
2457 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2461 MVT::i64, ResTyElts));
2464 ResTys.push_back(MVT::i32);
2465 ResTys.push_back(MVT::Other);
2468 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2471 Ops.push_back(MemAddr);
2472 Ops.push_back(Align);
2477 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
2485 SuperReg =
SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
2487 SuperReg =
SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
2491 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2494 SuperReg =
SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
2496 SuperReg =
SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
2498 Ops.push_back(SuperReg);
2499 Ops.push_back(getI32Imm(Lane, dl));
2500 Ops.push_back(Pred);
2501 Ops.push_back(Reg0);
2502 Ops.push_back(Chain);
2506 SDNode *VLdLn = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
2509 ReplaceNode(
N, VLdLn);
2515 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2516 ARM::qsub_3 == ARM::qsub_0 + 3,
2517 "Unexpected subreg numbering");
2518 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2519 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2521 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2525 CurDAG->RemoveDeadNode(
N);
2528template <
typename SDValueVector>
2529void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2531 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2532 Ops.push_back(PredicateMask);
2533 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2536template <
typename SDValueVector>
2537void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2540 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::Then, Loc, MVT::i32));
2541 Ops.push_back(PredicateMask);
2542 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2543 Ops.push_back(Inactive);
2546template <
typename SDValueVector>
2547void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc) {
2548 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2549 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2550 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2553template <
typename SDValueVector>
2554void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &
Ops, SDLoc Loc,
2556 Ops.push_back(CurDAG->getTargetConstant(
ARMVCC::None, Loc, MVT::i32));
2557 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2558 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2560 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, InactiveTy), 0));
2563void ARMDAGToDAGISel::SelectMVE_WB(SDNode *
N,
const uint16_t *Opcodes,
2569 switch (
N->getValueType(1).getVectorElementType().getSizeInBits()) {
2571 Opcode = Opcodes[0];
2574 Opcode = Opcodes[1];
2580 Ops.push_back(
N->getOperand(2));
2582 int32_t ImmValue =
N->getConstantOperandVal(3);
2583 Ops.push_back(getI32Imm(ImmValue, Loc));
2586 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(4));
2588 AddEmptyMVEPredicateToOps(
Ops, Loc);
2590 Ops.push_back(
N->getOperand(0));
2597 SDNode *
New = CurDAG->getMachineNode(Opcode, SDLoc(
N), VTs,
Ops);
2601 transferMemOperands(
N, New);
2602 CurDAG->RemoveDeadNode(
N);
2605void ARMDAGToDAGISel::SelectMVE_LongShift(SDNode *
N, uint16_t Opcode,
2607 bool HasSaturationOperand) {
2612 Ops.push_back(
N->getOperand(1));
2613 Ops.push_back(
N->getOperand(2));
2617 int32_t ImmValue =
N->getConstantOperandVal(3);
2618 Ops.push_back(getI32Imm(ImmValue, Loc));
2620 Ops.push_back(
N->getOperand(3));
2624 if (HasSaturationOperand) {
2625 int32_t SatOp =
N->getConstantOperandVal(4);
2626 int SatBit = (SatOp == 64 ? 0 : 1);
2627 Ops.push_back(getI32Imm(SatBit, Loc));
2633 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
2635 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2638void ARMDAGToDAGISel::SelectMVE_VADCSBC(SDNode *
N, uint16_t OpcodeWithCarry,
2639 uint16_t OpcodeWithNoCarry,
2648 Ops.push_back(
N->getOperand(FirstInputOp));
2649 Ops.push_back(
N->getOperand(FirstInputOp + 1));
2650 SDValue CarryIn =
N->getOperand(FirstInputOp + 2);
2652 uint32_t CarryMask = 1 << 29;
2653 uint32_t CarryExpected =
Add ? 0 : CarryMask;
2654 if (CarryInConstant &&
2655 (CarryInConstant->
getZExtValue() & CarryMask) == CarryExpected) {
2656 Opcode = OpcodeWithNoCarry;
2658 Ops.push_back(CarryIn);
2659 Opcode = OpcodeWithCarry;
2663 AddMVEPredicateToOps(
Ops, Loc,
2664 N->getOperand(FirstInputOp + 3),
2665 N->getOperand(FirstInputOp - 1));
2667 AddEmptyMVEPredicateToOps(
Ops, Loc,
N->getValueType(0));
2669 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2672void ARMDAGToDAGISel::SelectMVE_VSHLC(SDNode *
N,
bool Predicated) {
2678 Ops.push_back(
N->getOperand(1));
2679 Ops.push_back(
N->getOperand(2));
2680 int32_t ImmValue =
N->getConstantOperandVal(3);
2681 Ops.push_back(getI32Imm(ImmValue, Loc));
2684 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(4));
2686 AddEmptyMVEPredicateToOps(
Ops, Loc);
2688 CurDAG->SelectNodeTo(
N, ARM::MVE_VSHLC,
N->getVTList(),
ArrayRef(
Ops));
2699void ARMDAGToDAGISel::SelectBaseMVE_VMLLDAV(SDNode *
N,
bool Predicated,
2700 const uint16_t *OpcodesS,
2701 const uint16_t *OpcodesU,
2702 size_t Stride,
size_t TySize) {
2703 assert(TySize < Stride &&
"Invalid TySize");
2709 "Unsigned versions of vmlsldav[a]/vrmlsldavh[a] do not exist");
2711 "Unsigned versions of vmlaldav[a]x/vrmlaldavh[a]x do not exist");
2714 auto OpIsZero = [
N](
size_t OpNo) {
2720 bool IsAccum = !(OpIsZero(4) && OpIsZero(5));
2722 const uint16_t *Opcodes = IsUnsigned ? OpcodesU : OpcodesS;
2724 Opcodes += 4 * Stride;
2726 Opcodes += 2 * Stride;
2729 uint16_t Opcode = Opcodes[TySize];
2735 Ops.push_back(
N->getOperand(4));
2736 Ops.push_back(
N->getOperand(5));
2739 Ops.push_back(
N->getOperand(6));
2740 Ops.push_back(
N->getOperand(7));
2743 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(8));
2745 AddEmptyMVEPredicateToOps(
Ops, Loc);
2747 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2750void ARMDAGToDAGISel::SelectMVE_VMLLDAV(SDNode *
N,
bool Predicated,
2751 const uint16_t *OpcodesS,
2752 const uint16_t *OpcodesU) {
2753 EVT VecTy =
N->getOperand(6).getValueType();
2766 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 2, SizeIndex);
2769void ARMDAGToDAGISel::SelectMVE_VRMLLDAVH(SDNode *
N,
bool Predicated,
2770 const uint16_t *OpcodesS,
2771 const uint16_t *OpcodesU) {
2773 N->getOperand(6).getValueType().getVectorElementType().getSizeInBits() ==
2775 "bad vector element size");
2776 SelectBaseMVE_VMLLDAV(
N,
Predicated, OpcodesS, OpcodesU, 1, 0);
2779void ARMDAGToDAGISel::SelectMVE_VLD(SDNode *
N,
unsigned NumVecs,
2780 const uint16_t *
const *Opcodes,
2781 bool HasWriteback) {
2782 EVT VT =
N->getValueType(0);
2785 const uint16_t *OurOpcodes;
2788 OurOpcodes = Opcodes[0];
2791 OurOpcodes = Opcodes[1];
2794 OurOpcodes = Opcodes[2];
2800 EVT DataTy =
EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, NumVecs * 2);
2802 unsigned PtrOperand = HasWriteback ? 1 : 2;
2805 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, DataTy), 0);
2808 for (
unsigned Stage = 0; Stage < NumVecs - 1; ++Stage) {
2811 CurDAG->getMachineNode(OurOpcodes[Stage], Loc, ResultTys,
Ops);
2814 transferMemOperands(
N, LoadInst);
2818 ResultTys = {DataTy, MVT::i32, MVT::Other};
2821 CurDAG->getMachineNode(OurOpcodes[NumVecs - 1], Loc, ResultTys,
Ops);
2822 transferMemOperands(
N, LoadInst);
2825 for (i = 0; i < NumVecs; i++)
2827 CurDAG->getTargetExtractSubreg(ARM::qsub_0 + i, Loc, VT,
2832 CurDAG->RemoveDeadNode(
N);
2835void ARMDAGToDAGISel::SelectMVE_VxDUP(SDNode *
N,
const uint16_t *Opcodes,
2837 EVT VT =
N->getValueType(0);
2843 Opcode = Opcodes[0];
2846 Opcode = Opcodes[1];
2849 Opcode = Opcodes[2];
2868 Ops.push_back(getI32Imm(ImmValue, Loc));
2871 AddMVEPredicateToOps(
Ops, Loc,
N->getOperand(
OpIdx), Inactive);
2873 AddEmptyMVEPredicateToOps(
Ops, Loc,
N->getValueType(0));
2875 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
ArrayRef(
Ops));
2878void ARMDAGToDAGISel::SelectCDE_CXxD(SDNode *
N, uint16_t Opcode,
2879 size_t NumExtraOps,
bool HasAccum) {
2880 bool IsBigEndian = CurDAG->getDataLayout().isBigEndian();
2889 Ops.push_back(getI32Imm(ImmCoprocVal, Loc));
2902 for (
size_t I = 0;
I < NumExtraOps;
I++)
2907 uint32_t ImmVal =
Imm->getAsZExtVal();
2908 Ops.push_back(getI32Imm(ImmVal, Loc));
2913 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2914 Ops.push_back(Pred);
2915 Ops.push_back(PredReg);
2919 SDNode *InstrNode = CurDAG->getMachineNode(Opcode, Loc, MVT::Untyped,
Ops);
2926 uint16_t SubRegs[2] = {ARM::gsub_0, ARM::gsub_1};
2930 for (
size_t ResIdx = 0; ResIdx < 2; ResIdx++) {
2931 if (
SDValue(
N, ResIdx).use_empty())
2933 SDValue SubReg = CurDAG->getTargetExtractSubreg(SubRegs[ResIdx], Loc,
2934 MVT::i32, ResultPair);
2938 CurDAG->RemoveDeadNode(
N);
2941void ARMDAGToDAGISel::SelectVLDDup(SDNode *
N,
bool IsIntrinsic,
2942 bool isUpdating,
unsigned NumVecs,
2943 const uint16_t *DOpcodes,
2944 const uint16_t *QOpcodes0,
2945 const uint16_t *QOpcodes1) {
2946 assert(Subtarget->hasNEON());
2947 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLDDup NumVecs out-of-range");
2951 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2952 if (!SelectAddrMode6(
N,
N->getOperand(AddrOpIdx), MemAddr, Align))
2956 EVT VT =
N->getValueType(0);
2959 unsigned Alignment = 0;
2961 Alignment =
Align->getAsZExtVal();
2963 if (Alignment > NumBytes)
2964 Alignment = NumBytes;
2965 if (Alignment < 8 && Alignment < NumBytes)
2968 Alignment = (Alignment & -Alignment);
2972 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
2994 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2999 std::vector<EVT> ResTys;
3000 ResTys.push_back(ResTy);
3002 ResTys.push_back(MVT::i32);
3003 ResTys.push_back(MVT::Other);
3006 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3009 Ops.push_back(MemAddr);
3010 Ops.push_back(Align);
3020 Ops.push_back(Reg0);
3027 if (is64BitVector || NumVecs == 1) {
3031 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
3032 const SDValue OpsA[] = {MemAddr,
Align, ImplDef, Pred, Reg0, Chain};
3033 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[
OpcodeIndex], dl, ResTy,
3039 Ops.push_back(Pred);
3040 Ops.push_back(Reg0);
3041 Ops.push_back(Chain);
3043 SDNode *VLdDup = CurDAG->getMachineNode(
Opc, dl, ResTys,
Ops);
3054 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7,
"Unexpected subreg numbering");
3055 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
3056 for (
unsigned Vec = 0; Vec != NumVecs; ++Vec) {
3058 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
3064 CurDAG->RemoveDeadNode(
N);
3067bool ARMDAGToDAGISel::tryInsertVectorElt(SDNode *
N) {
3068 if (!Subtarget->hasMVEIntegerOps())
3082 (VT != MVT::v8f16 && VT != MVT::v8i16) || (Ins2.
getValueType() != VT))
3087 if (Lane2 % 2 != 0 || Lane1 != Lane2 + 1)
3114 ExtractLane1 == ExtractLane2 + 1) {
3115 SDValue NewExt = CurDAG->getTargetExtractSubreg(
3116 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val1.
getOperand(0));
3117 SDValue NewIns = CurDAG->getTargetInsertSubreg(
3118 ARM::ssub_0 + Lane2 / 2, dl, VT, Ins2.
getOperand(0),
3120 ReplaceUses(Ins1, NewIns);
3126 if (VT == MVT::v8i16 && Subtarget->hasFullFP16()) {
3127 SDValue Inp1 = CurDAG->getTargetExtractSubreg(
3128 ARM::ssub_0 + ExtractLane1 / 2, dl, MVT::f32, Val1.
getOperand(0));
3129 SDValue Inp2 = CurDAG->getTargetExtractSubreg(
3130 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val2.
getOperand(0));
3131 if (ExtractLane1 % 2 != 0)
3132 Inp1 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp1), 0);
3133 if (ExtractLane2 % 2 != 0)
3134 Inp2 =
SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp2), 0);
3135 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Inp2, Inp1);
3137 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3139 ReplaceUses(Ins1, NewIns);
3146 if (VT == MVT::v8f16 && Subtarget->hasFullFP16()) {
3147 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Val2, Val1);
3149 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32,
3151 ReplaceUses(Ins1, NewIns);
3158bool ARMDAGToDAGISel::transformFixedFloatingPointConversion(SDNode *
N,
3161 bool FixedToFloat) {
3164 if (ScalarBits > 32)
3167 SDNodeFlags FMulFlags =
FMul->getFlags();
3170 if (ScalarBits == 16 && !FMulFlags.
hasNoInfs() && IsUnsigned)
3182 if (ImmNode.
getOpcode() == ISD::BITCAST) {
3201 APFloat(ScalarBits == 32 ? APFloat::IEEEsingle() : APFloat::IEEEhalf(),
3202 APInt(ScalarBits, Imm));
3219 if (!ImmAPF.getExactInverse(&ToConvert))
3222 APSInt Converted(64,
false);
3226 if (!IsExact || !Converted.isPowerOf2())
3229 unsigned FracBits = Converted.logBase2();
3230 if (FracBits > ScalarBits)
3234 VecVal, CurDAG->getConstant(FracBits, SDLoc(
N), MVT::i32)};
3235 AddEmptyMVEPredicateToOps(
Ops, SDLoc(
N),
Type);
3237 unsigned int Opcode;
3238 switch (ScalarBits) {
3241 Opcode = IsUnsigned ? ARM::MVE_VCVTf16u16_fix : ARM::MVE_VCVTf16s16_fix;
3243 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3247 Opcode = IsUnsigned ? ARM::MVE_VCVTf32u32_fix : ARM::MVE_VCVTf32s32_fix;
3249 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3256 ReplaceNode(
N, CurDAG->getMachineNode(Opcode, SDLoc(
N),
Type,
Ops));
3260bool ARMDAGToDAGISel::tryFP_TO_INT(SDNode *
N, SDLoc dl) {
3262 if (!Subtarget->hasMVEFloatOps())
3264 EVT
Type =
N->getValueType(0);
3265 if (!
Type.isVector())
3267 unsigned int ScalarBits =
Type.getScalarSizeInBits();
3271 SDNode *
Node =
N->getOperand(0).getNode();
3276 if (
Node->getOperand(0) !=
Node->getOperand(1))
3281 if (ScalarBits == 16 && !
Flags.hasNoInfs() && IsUnsigned)
3285 switch (ScalarBits) {
3287 Opcode = IsUnsigned ? ARM::MVE_VCVTu16f16_fix : ARM::MVE_VCVTs16f16_fix;
3290 Opcode = IsUnsigned ? ARM::MVE_VCVTu32f32_fix : ARM::MVE_VCVTs32f32_fix;
3294 CurDAG->getConstant(1, dl, MVT::i32)};
3295 AddEmptyMVEPredicateToOps(
Ops, dl,
Type);
3297 ReplaceNode(
N, CurDAG->getMachineNode(Opcode, dl,
Type,
Ops));
3304 return transformFixedFloatingPointConversion(
N, Node, IsUnsigned,
false);
3307bool ARMDAGToDAGISel::tryFMULFixed(SDNode *
N, SDLoc dl) {
3309 if (!Subtarget->hasMVEFloatOps())
3311 auto Type =
N->getValueType(0);
3312 if (!
Type.isVector())
3315 auto LHS =
N->getOperand(0);
3319 return transformFixedFloatingPointConversion(
3323bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *
N,
bool isSigned) {
3324 if (!Subtarget->hasV6T2Ops())
3328 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
3333 unsigned And_imm = 0;
3338 if (And_imm & (And_imm + 1))
3341 unsigned Srl_imm = 0;
3344 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3349 And_imm &= -1U >> Srl_imm;
3353 unsigned LSB = Srl_imm;
3355 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3357 if ((LSB + Width + 1) ==
N->getValueType(0).getSizeInBits()) {
3359 if (Subtarget->isThumb()) {
3362 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3363 getAL(CurDAG, dl), Reg0, Reg0 };
3364 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3373 SDValue Ops[] = {
N->getOperand(0).getOperand(0), ShOpc,
3374 getAL(CurDAG, dl), Reg0, Reg0 };
3375 CurDAG->SelectNodeTo(
N, ARM::MOVsi, MVT::i32,
Ops);
3379 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3381 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3382 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3383 getAL(CurDAG, dl), Reg0 };
3384 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3392 unsigned Shl_imm = 0;
3394 assert(Shl_imm > 0 && Shl_imm < 32 &&
"bad amount in shift node!");
3395 unsigned Srl_imm = 0;
3397 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3399 unsigned Width = 32 - Srl_imm - 1;
3400 int LSB = Srl_imm - Shl_imm;
3403 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3404 assert(LSB + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3406 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3407 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3408 getAL(CurDAG, dl), Reg0 };
3409 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3417 unsigned Srl_imm = 0;
3421 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
3424 unsigned Width = MSB - LSB;
3425 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3426 assert(Srl_imm + Width + 1 <= 32 &&
"Shouldn't create an invalid ubfx");
3428 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
3429 CurDAG->getTargetConstant(Width, dl, MVT::i32),
3430 getAL(CurDAG, dl), Reg0 };
3431 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3437 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
3443 if (LSB + Width > 32)
3446 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3447 assert(LSB + Width <= 32 &&
"Shouldn't create an invalid ubfx");
3449 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
3450 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
3451 getAL(CurDAG, dl), Reg0 };
3452 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3460void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *
N) {
3463 if (MemTy == MVT::i8)
3464 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_8 : ARM::CMP_SWAP_8;
3465 else if (MemTy == MVT::i16)
3466 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_16 : ARM::CMP_SWAP_16;
3467 else if (MemTy == MVT::i32)
3468 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_32 : ARM::CMP_SWAP_32;
3472 SDValue Ops[] = {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3),
3474 SDNode *CmpSwap = CurDAG->getMachineNode(
3476 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other),
Ops);
3483 CurDAG->RemoveDeadNode(
N);
3486static std::optional<std::pair<unsigned, unsigned>>
3488 unsigned FirstOne =
A.getBitWidth() -
A.countl_zero() - 1;
3489 unsigned LastOne =
A.countr_zero();
3490 if (
A.popcount() != (FirstOne - LastOne + 1))
3491 return std::nullopt;
3492 return std::make_pair(FirstOne, LastOne);
3495void ARMDAGToDAGISel::SelectCMPZ(SDNode *
N,
bool &SwitchEQNEToPLMI) {
3497 SwitchEQNEToPLMI =
false;
3499 if (!Subtarget->isThumb())
3506 if (!
And->hasOneUse())
3525 auto EmitShift = [&](
unsigned Opc,
SDValue Src,
unsigned Imm) -> SDNode* {
3527 Opc = (
Opc == ARM::tLSLri) ? ARM::t2LSLri :
ARM::t2LSRri;
3528 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3529 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3530 CurDAG->getRegister(0, MVT::i32) };
3531 return CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
3533 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
3534 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
3535 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3536 return CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
3540 if (
Range->second == 0) {
3542 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3543 ReplaceNode(
And.getNode(), NewN);
3544 }
else if (
Range->first == 31) {
3546 NewN = EmitShift(ARM::tLSRri,
X,
Range->second);
3547 ReplaceNode(
And.getNode(), NewN);
3553 if (!
N->hasOneUse())
3555 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3556 ReplaceNode(
And.getNode(), NewN);
3558 SwitchEQNEToPLMI =
true;
3559 }
else if (!Subtarget->hasV6T2Ops()) {
3562 NewN = EmitShift(ARM::tLSLri,
X, 31 -
Range->first);
3563 NewN = EmitShift(ARM::tLSRri,
SDValue(NewN, 0),
3565 ReplaceNode(
And.getNode(), NewN);
3570 unsigned Opc128[3]) {
3572 "Unexpected vector shuffle length");
3585void ARMDAGToDAGISel::Select(SDNode *
N) {
3588 if (
N->isMachineOpcode()) {
3593 switch (
N->getOpcode()) {
3616 Ptr.getOperand(0) ==
ST->getChain()) {
3618 CurDAG->getRegister(ARM::SP, MVT::i32),
3619 CurDAG->getTargetConstant(RHSC, dl, MVT::i32),
3621 CurDAG->getRegister(0, MVT::i32),
3623 MachineSDNode *ResNode =
3624 CurDAG->getMachineNode(ARM::tSTRspi, dl, MVT::Other,
Ops);
3625 MachineMemOperand *MemOp =
ST->getMemOperand();
3627 ReplaceNode(
N, ResNode);
3634 if (tryWriteRegister(
N))
3638 if (tryReadRegister(
N))
3641 case ISD::INLINEASM:
3642 case ISD::INLINEASM_BR:
3643 if (tryInlineAsm(
N))
3647 unsigned Val =
N->getAsZExtVal();
3650 !Subtarget->genExecuteOnly()) {
3651 SDValue CPIdx = CurDAG->getTargetConstantPool(
3652 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
3653 TLI->getPointerTy(CurDAG->getDataLayout()));
3656 if (Subtarget->isThumb()) {
3660 CurDAG->getRegister(0, MVT::i32),
3661 CurDAG->getEntryNode()
3663 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
3668 CurDAG->getTargetConstant(0, dl, MVT::i32),
3670 CurDAG->getRegister(0, MVT::i32),
3671 CurDAG->getEntryNode()
3673 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
3679 MachineFunction& MF = CurDAG->getMachineFunction();
3680 MachineMemOperand *MemOp =
3686 ReplaceNode(
N, ResNode);
3696 SDValue TFI = CurDAG->getTargetFrameIndex(
3697 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
3704 CurDAG->SelectNodeTo(
N, ARM::tADDframe, MVT::i32, TFI,
3705 CurDAG->getTargetConstant(0, dl, MVT::i32));
3708 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
3709 ARM::t2ADDri : ARM::ADDri);
3710 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
3711 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3712 CurDAG->getRegister(0, MVT::i32) };
3713 CurDAG->SelectNodeTo(
N,
Opc, MVT::i32,
Ops);
3718 if (tryInsertVectorElt(
N))
3723 if (tryV6T2BitfieldExtractOp(
N,
false))
3728 if (tryV6T2BitfieldExtractOp(
N,
true))
3735 if (tryFP_TO_INT(
N, dl))
3739 if (tryFMULFixed(
N, dl))
3746 unsigned RHSV =
C->getZExtValue();
3749 unsigned ShImm =
Log2_32(RHSV-1);
3754 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3755 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3756 if (Subtarget->isThumb()) {
3758 CurDAG->SelectNodeTo(
N, ARM::t2ADDrs, MVT::i32,
Ops);
3763 CurDAG->SelectNodeTo(
N, ARM::ADDrsi, MVT::i32,
Ops);
3768 unsigned ShImm =
Log2_32(RHSV+1);
3773 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
3774 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
3775 if (Subtarget->isThumb()) {
3777 CurDAG->SelectNodeTo(
N, ARM::t2RSBrs, MVT::i32,
Ops);
3782 CurDAG->SelectNodeTo(
N, ARM::RSBrsi, MVT::i32,
Ops);
3790 if (tryV6T2BitfieldExtractOp(
N,
false))
3797 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
3798 uint32_t
Imm = (uint32_t) N1C->getZExtValue();
3804 bool PreferImmediateEncoding =
3805 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
3806 if (!PreferImmediateEncoding &&
3811 SDValue NewImm = CurDAG->getConstant(~Imm, dl, MVT::i32);
3815 CurDAG->RepositionNode(
N->getIterator(), NewImm.
getNode());
3817 if (!Subtarget->hasThumb2()) {
3818 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
3819 N->getOperand(0), NewImm,
getAL(CurDAG, dl),
3820 CurDAG->getRegister(0, MVT::i32)};
3821 ReplaceNode(
N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32,
Ops));
3825 CurDAG->getRegister(0, MVT::i32),
3826 CurDAG->getRegister(0, MVT::i32)};
3828 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32,
Ops));
3839 EVT VT =
N->getValueType(0);
3842 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
3844 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
3856 unsigned N1CVal = N1C->getZExtValue();
3858 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
3859 (N1CVal & 0xffffU) == 0xffffU &&
3860 (N2CVal & 0xffffU) == 0x0U) {
3861 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
3864 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
3865 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT,
Ops));
3873 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3875 N->getOperand(2),
N->getOperand(3),
3877 CurDAG->getRegister(0, MVT::i32) };
3878 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, MVT::i32, MVT::i32,
Ops));
3882 if (Subtarget->isThumb()) {
3883 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3884 N->getOperand(3),
getAL(CurDAG, dl),
3885 CurDAG->getRegister(0, MVT::i32)};
3887 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32,
Ops));
3890 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3891 N->getOperand(3),
getAL(CurDAG, dl),
3892 CurDAG->getRegister(0, MVT::i32),
3893 CurDAG->getRegister(0, MVT::i32) };
3894 ReplaceNode(
N, CurDAG->getMachineNode(
3895 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3896 MVT::i32, MVT::i32,
Ops));
3901 if (Subtarget->isThumb()) {
3902 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3903 N->getOperand(3),
getAL(CurDAG, dl),
3904 CurDAG->getRegister(0, MVT::i32)};
3906 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32,
Ops));
3909 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
3910 N->getOperand(3),
getAL(CurDAG, dl),
3911 CurDAG->getRegister(0, MVT::i32),
3912 CurDAG->getRegister(0, MVT::i32) };
3913 ReplaceNode(
N, CurDAG->getMachineNode(
3914 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
3915 MVT::i32, MVT::i32,
Ops));
3920 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
3929 if (Subtarget->isThumb())
3930 assert(Subtarget->hasThumb2() &&
3931 "This pattern should not be generated for Thumb");
3933 SDValue SmulLoHi =
N->getOperand(1);
3942 unsigned Opc = Subtarget->
isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
3945 CurDAG->getRegister(0, MVT::i32) };
3946 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops));
3950 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
3952 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
3953 if (tryT2IndexedLoad(
N))
3955 }
else if (Subtarget->isThumb()) {
3956 if (tryT1IndexedLoad(
N))
3958 }
else if (tryARMIndexedLoad(
N))
3964 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(
N))
3969 SDNode *
New = CurDAG->getMachineNode(ARM::t2WhileLoopSetup, dl, MVT::i32,
3971 ReplaceUses(
N, New);
3972 CurDAG->RemoveDeadNode(
N);
3976 SDNode *
New = CurDAG->getMachineNode(ARM::t2WhileLoopStart, dl, MVT::Other,
3977 N->getOperand(1),
N->getOperand(2),
3979 ReplaceUses(
N, New);
3980 CurDAG->RemoveDeadNode(
N);
3987 unsigned Opc = ARM::t2LoopEnd;
3988 SDNode *
New = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
3989 ReplaceUses(
N, New);
3990 CurDAG->RemoveDeadNode(
N);
3999 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
4000 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4006 RegOffset = CurDAG->getRegister(0, MVT::i32);
4009 SDNode *
New = CurDAG->getMachineNode(ARM::LOADDUAL, dl,
4010 {MVT::Untyped, MVT::Other},
Ops);
4011 SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4013 SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4015 transferMemOperands(
N, New);
4019 CurDAG->RemoveDeadNode(
N);
4028 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
4029 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4035 RegOffset = CurDAG->getRegister(0, MVT::i32);
4040 SDNode *
New = CurDAG->getMachineNode(ARM::STOREDUAL, dl, MVT::Other,
Ops);
4041 transferMemOperands(
N, New);
4043 CurDAG->RemoveDeadNode(
N);
4051 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4052 CurDAG->getVTList(MVT::i32, MVT::Other),
Ops);
4053 ReplaceUses(
N, Dec);
4054 CurDAG->RemoveDeadNode(
N);
4070 unsigned Opc = Subtarget->isThumb() ?
4071 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
4084 uint64_t
ID =
Int->getConstantOperandVal(1);
4087 if (
ID == Intrinsic::loop_decrement_reg) {
4089 SDValue Size = CurDAG->getTargetConstant(
Int.getConstantOperandVal(3),
4094 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4095 CurDAG->getVTList(MVT::i32, MVT::Other),
4097 ReplaceUses(
Int.getNode(), LoopDec);
4101 CurDAG->getMachineNode(ARM::t2LoopEnd, dl, MVT::Other, EndArgs);
4103 ReplaceUses(
N, LoopEnd);
4104 CurDAG->RemoveDeadNode(
N);
4105 CurDAG->RemoveDeadNode(
Flags.getNode());
4106 CurDAG->RemoveDeadNode(
Int.getNode());
4111 bool SwitchEQNEToPLMI;
4112 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4113 Flags =
N->getOperand(3);
4115 if (SwitchEQNEToPLMI) {
4128 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
4129 Chain = CurDAG->getCopyToReg(Chain, dl, ARM::CPSR, Flags,
SDValue());
4130 SDValue Ops[] = {N1, Tmp2, CurDAG->getRegister(ARM::CPSR, MVT::i32), Chain,
4132 CurDAG->SelectNodeTo(
N,
Opc, MVT::Other,
Ops);
4143 if (
C &&
C->getSExtValue() < 0 && Subtarget->isThumb()) {
4144 int64_t Addend = -
C->getSExtValue();
4146 SDNode *
Add =
nullptr;
4151 if (Addend < 1<<8) {
4153 SDValue Ops[] = {
X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4154 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
4155 CurDAG->getRegister(0, MVT::i32) };
4156 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32,
Ops);
4158 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 :
ARM::tADDi8;
4159 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
X,
4160 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4161 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
4162 Add = CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
4178 bool SwitchEQNEToPLMI;
4179 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4181 if (SwitchEQNEToPLMI) {
4194 SDValue NewARMcc = CurDAG->getConstant((
unsigned)CC, dl, MVT::i32);
4195 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), NewARMcc,
4204 EVT VT =
N->getValueType(0);
4206 unsigned Opc64[] = {ARM::VZIPd8, ARM::VZIPd16, ARM::VTRNd32};
4207 unsigned Opc128[] = {ARM::VZIPq8, ARM::VZIPq16, ARM::VZIPq32};
4210 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4211 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4212 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4216 EVT VT =
N->getValueType(0);
4218 unsigned Opc64[] = {ARM::VUZPd8, ARM::VUZPd16, ARM::VTRNd32};
4219 unsigned Opc128[] = {ARM::VUZPq8, ARM::VUZPq16, ARM::VUZPq32};
4222 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4223 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4224 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4228 EVT VT =
N->getValueType(0);
4229 unsigned Opc64[] = {ARM::VTRNd8, ARM::VTRNd16, ARM::VTRNd32};
4230 unsigned Opc128[] = {ARM::VTRNq8, ARM::VTRNq16, ARM::VTRNq32};
4233 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4234 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4235 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4239 EVT VecVT =
N->getValueType(0);
4242 if (EltVT == MVT::f64) {
4243 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
4245 N, createDRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4248 assert(EltVT == MVT::f32 &&
"unexpected type for BUILD_VECTOR");
4251 N, createSRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4254 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
4256 createQuadSRegsNode(VecVT,
N->getOperand(0),
N->getOperand(1),
4257 N->getOperand(2),
N->getOperand(3)));
4262 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
4264 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
4266 SelectVLDDup(
N,
false,
false, 1, DOpcodes, QOpcodes);
4271 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4273 SelectVLDDup(
N,
false,
false, 2, Opcodes);
4278 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
4279 ARM::VLD3DUPd16Pseudo,
4280 ARM::VLD3DUPd32Pseudo };
4281 SelectVLDDup(
N,
false,
false, 3, Opcodes);
4286 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
4287 ARM::VLD4DUPd16Pseudo,
4288 ARM::VLD4DUPd32Pseudo };
4289 SelectVLDDup(
N,
false,
false, 4, Opcodes);
4294 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
4295 ARM::VLD1DUPd16wb_fixed,
4296 ARM::VLD1DUPd32wb_fixed };
4297 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
4298 ARM::VLD1DUPq16wb_fixed,
4299 ARM::VLD1DUPq32wb_fixed };
4300 SelectVLDDup(
N,
false,
true, 1, DOpcodes, QOpcodes);
4305 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8wb_fixed,
4306 ARM::VLD2DUPd16wb_fixed,
4307 ARM::VLD2DUPd32wb_fixed,
4308 ARM::VLD1q64wb_fixed };
4309 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4310 ARM::VLD2DUPq16EvenPseudo,
4311 ARM::VLD2DUPq32EvenPseudo };
4312 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudoWB_fixed,
4313 ARM::VLD2DUPq16OddPseudoWB_fixed,
4314 ARM::VLD2DUPq32OddPseudoWB_fixed };
4315 SelectVLDDup(
N,
false,
true, 2, DOpcodes, QOpcodes0, QOpcodes1);
4320 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
4321 ARM::VLD3DUPd16Pseudo_UPD,
4322 ARM::VLD3DUPd32Pseudo_UPD,
4323 ARM::VLD1d64TPseudoWB_fixed };
4324 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4325 ARM::VLD3DUPq16EvenPseudo,
4326 ARM::VLD3DUPq32EvenPseudo };
4327 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo_UPD,
4328 ARM::VLD3DUPq16OddPseudo_UPD,
4329 ARM::VLD3DUPq32OddPseudo_UPD };
4330 SelectVLDDup(
N,
false,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4335 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
4336 ARM::VLD4DUPd16Pseudo_UPD,
4337 ARM::VLD4DUPd32Pseudo_UPD,
4338 ARM::VLD1d64QPseudoWB_fixed };
4339 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4340 ARM::VLD4DUPq16EvenPseudo,
4341 ARM::VLD4DUPq32EvenPseudo };
4342 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo_UPD,
4343 ARM::VLD4DUPq16OddPseudo_UPD,
4344 ARM::VLD4DUPq32OddPseudo_UPD };
4345 SelectVLDDup(
N,
false,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4350 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
4351 ARM::VLD1d16wb_fixed,
4352 ARM::VLD1d32wb_fixed,
4353 ARM::VLD1d64wb_fixed };
4354 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
4355 ARM::VLD1q16wb_fixed,
4356 ARM::VLD1q32wb_fixed,
4357 ARM::VLD1q64wb_fixed };
4358 SelectVLD(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4363 if (Subtarget->hasNEON()) {
4364 static const uint16_t DOpcodes[] = {
4365 ARM::VLD2d8wb_fixed, ARM::VLD2d16wb_fixed, ARM::VLD2d32wb_fixed,
4366 ARM::VLD1q64wb_fixed};
4367 static const uint16_t QOpcodes[] = {ARM::VLD2q8PseudoWB_fixed,
4368 ARM::VLD2q16PseudoWB_fixed,
4369 ARM::VLD2q32PseudoWB_fixed};
4370 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4372 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8,
4373 ARM::MVE_VLD21_8_wb};
4374 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
4375 ARM::MVE_VLD21_16_wb};
4376 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
4377 ARM::MVE_VLD21_32_wb};
4378 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4379 SelectMVE_VLD(
N, 2, Opcodes,
true);
4385 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
4386 ARM::VLD3d16Pseudo_UPD,
4387 ARM::VLD3d32Pseudo_UPD,
4388 ARM::VLD1d64TPseudoWB_fixed};
4389 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4390 ARM::VLD3q16Pseudo_UPD,
4391 ARM::VLD3q32Pseudo_UPD };
4392 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
4393 ARM::VLD3q16oddPseudo_UPD,
4394 ARM::VLD3q32oddPseudo_UPD };
4395 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4400 if (Subtarget->hasNEON()) {
4401 static const uint16_t DOpcodes[] = {
4402 ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, ARM::VLD4d32Pseudo_UPD,
4403 ARM::VLD1d64QPseudoWB_fixed};
4404 static const uint16_t QOpcodes0[] = {ARM::VLD4q8Pseudo_UPD,
4405 ARM::VLD4q16Pseudo_UPD,
4406 ARM::VLD4q32Pseudo_UPD};
4407 static const uint16_t QOpcodes1[] = {ARM::VLD4q8oddPseudo_UPD,
4408 ARM::VLD4q16oddPseudo_UPD,
4409 ARM::VLD4q32oddPseudo_UPD};
4410 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4412 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
4414 ARM::MVE_VLD43_8_wb};
4415 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
4417 ARM::MVE_VLD43_16_wb};
4418 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
4420 ARM::MVE_VLD43_32_wb};
4421 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4422 SelectMVE_VLD(
N, 4, Opcodes,
true);
4428 if (Subtarget->hasNEON()) {
4429 static const uint16_t DOpcodes[] = {
4430 ARM::VLD1q8wb_fixed, ARM::VLD1q16wb_fixed, ARM::VLD1q32wb_fixed,
4431 ARM::VLD1q64wb_fixed};
4432 static const uint16_t QOpcodes[] = {
4433 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4434 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4435 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4442 if (Subtarget->hasNEON()) {
4443 static const uint16_t DOpcodes[] = {
4444 ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d16TPseudoWB_fixed,
4445 ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d64TPseudoWB_fixed};
4446 static const uint16_t QOpcodes0[] = {
4447 ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1q16LowTPseudo_UPD,
4448 ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1q64LowTPseudo_UPD};
4449 static const uint16_t QOpcodes1[] = {
4450 ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1q16HighTPseudo_UPD,
4451 ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1q64HighTPseudo_UPD};
4452 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4459 if (Subtarget->hasNEON()) {
4460 static const uint16_t DOpcodes[] = {
4461 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4462 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4463 static const uint16_t QOpcodes0[] = {
4464 ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1q16LowQPseudo_UPD,
4465 ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1q64LowQPseudo_UPD};
4466 static const uint16_t QOpcodes1[] = {
4467 ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1q16HighQPseudo_UPD,
4468 ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1q64HighQPseudo_UPD};
4469 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4476 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
4477 ARM::VLD2LNd16Pseudo_UPD,
4478 ARM::VLD2LNd32Pseudo_UPD };
4479 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
4480 ARM::VLD2LNq32Pseudo_UPD };
4481 SelectVLDSTLane(
N,
true,
true, 2, DOpcodes, QOpcodes);
4486 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
4487 ARM::VLD3LNd16Pseudo_UPD,
4488 ARM::VLD3LNd32Pseudo_UPD };
4489 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
4490 ARM::VLD3LNq32Pseudo_UPD };
4491 SelectVLDSTLane(
N,
true,
true, 3, DOpcodes, QOpcodes);
4496 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
4497 ARM::VLD4LNd16Pseudo_UPD,
4498 ARM::VLD4LNd32Pseudo_UPD };
4499 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
4500 ARM::VLD4LNq32Pseudo_UPD };
4501 SelectVLDSTLane(
N,
true,
true, 4, DOpcodes, QOpcodes);
4506 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
4507 ARM::VST1d16wb_fixed,
4508 ARM::VST1d32wb_fixed,
4509 ARM::VST1d64wb_fixed };
4510 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
4511 ARM::VST1q16wb_fixed,
4512 ARM::VST1q32wb_fixed,
4513 ARM::VST1q64wb_fixed };
4514 SelectVST(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4519 if (Subtarget->hasNEON()) {
4520 static const uint16_t DOpcodes[] = {
4521 ARM::VST2d8wb_fixed, ARM::VST2d16wb_fixed, ARM::VST2d32wb_fixed,
4522 ARM::VST1q64wb_fixed};
4523 static const uint16_t QOpcodes[] = {ARM::VST2q8PseudoWB_fixed,
4524 ARM::VST2q16PseudoWB_fixed,
4525 ARM::VST2q32PseudoWB_fixed};
4526 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4533 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
4534 ARM::VST3d16Pseudo_UPD,
4535 ARM::VST3d32Pseudo_UPD,
4536 ARM::VST1d64TPseudoWB_fixed};
4537 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
4538 ARM::VST3q16Pseudo_UPD,
4539 ARM::VST3q32Pseudo_UPD };
4540 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
4541 ARM::VST3q16oddPseudo_UPD,
4542 ARM::VST3q32oddPseudo_UPD };
4543 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4548 if (Subtarget->hasNEON()) {
4549 static const uint16_t DOpcodes[] = {
4550 ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, ARM::VST4d32Pseudo_UPD,
4551 ARM::VST1d64QPseudoWB_fixed};
4552 static const uint16_t QOpcodes0[] = {ARM::VST4q8Pseudo_UPD,
4553 ARM::VST4q16Pseudo_UPD,
4554 ARM::VST4q32Pseudo_UPD};
4555 static const uint16_t QOpcodes1[] = {ARM::VST4q8oddPseudo_UPD,
4556 ARM::VST4q16oddPseudo_UPD,
4557 ARM::VST4q32oddPseudo_UPD};
4558 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4565 if (Subtarget->hasNEON()) {
4566 static const uint16_t DOpcodes[] = { ARM::VST1q8wb_fixed,
4567 ARM::VST1q16wb_fixed,
4568 ARM::VST1q32wb_fixed,
4569 ARM::VST1q64wb_fixed};
4570 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4571 ARM::VST1d16QPseudoWB_fixed,
4572 ARM::VST1d32QPseudoWB_fixed,
4573 ARM::VST1d64QPseudoWB_fixed };
4574 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4581 if (Subtarget->hasNEON()) {
4582 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudoWB_fixed,
4583 ARM::VST1d16TPseudoWB_fixed,
4584 ARM::VST1d32TPseudoWB_fixed,
4585 ARM::VST1d64TPseudoWB_fixed };
4586 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4587 ARM::VST1q16LowTPseudo_UPD,
4588 ARM::VST1q32LowTPseudo_UPD,
4589 ARM::VST1q64LowTPseudo_UPD };
4590 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo_UPD,
4591 ARM::VST1q16HighTPseudo_UPD,
4592 ARM::VST1q32HighTPseudo_UPD,
4593 ARM::VST1q64HighTPseudo_UPD };
4594 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4601 if (Subtarget->hasNEON()) {
4602 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4603 ARM::VST1d16QPseudoWB_fixed,
4604 ARM::VST1d32QPseudoWB_fixed,
4605 ARM::VST1d64QPseudoWB_fixed };
4606 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4607 ARM::VST1q16LowQPseudo_UPD,
4608 ARM::VST1q32LowQPseudo_UPD,
4609 ARM::VST1q64LowQPseudo_UPD };
4610 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo_UPD,
4611 ARM::VST1q16HighQPseudo_UPD,
4612 ARM::VST1q32HighQPseudo_UPD,
4613 ARM::VST1q64HighQPseudo_UPD };
4614 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4620 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
4621 ARM::VST2LNd16Pseudo_UPD,
4622 ARM::VST2LNd32Pseudo_UPD };
4623 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
4624 ARM::VST2LNq32Pseudo_UPD };
4625 SelectVLDSTLane(
N,
false,
true, 2, DOpcodes, QOpcodes);
4630 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
4631 ARM::VST3LNd16Pseudo_UPD,
4632 ARM::VST3LNd32Pseudo_UPD };
4633 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
4634 ARM::VST3LNq32Pseudo_UPD };
4635 SelectVLDSTLane(
N,
false,
true, 3, DOpcodes, QOpcodes);
4640 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
4641 ARM::VST4LNd16Pseudo_UPD,
4642 ARM::VST4LNd32Pseudo_UPD };
4643 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
4644 ARM::VST4LNq32Pseudo_UPD };
4645 SelectVLDSTLane(
N,
false,
true, 4, DOpcodes, QOpcodes);
4651 unsigned IntNo =
N->getConstantOperandVal(1);
4656 case Intrinsic::arm_mrrc:
4657 case Intrinsic::arm_mrrc2: {
4662 if (Subtarget->isThumb())
4663 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
4665 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
4668 Ops.push_back(getI32Imm(
N->getConstantOperandVal(2), dl));
4669 Ops.push_back(getI32Imm(
N->getConstantOperandVal(3), dl));
4670 Ops.push_back(getI32Imm(
N->getConstantOperandVal(4), dl));
4675 if (
Opc != ARM::MRRC2) {
4677 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4680 Ops.push_back(Chain);
4683 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
4685 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, RetType,
Ops));
4688 case Intrinsic::arm_ldaexd:
4689 case Intrinsic::arm_ldrexd: {
4693 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
4695 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
4696 unsigned NewOpc =
isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
4697 : (IsAcquire ?
ARM::LDAEXD :
ARM::LDREXD);
4700 std::vector<EVT> ResTys;
4702 ResTys.push_back(MVT::i32);
4703 ResTys.push_back(MVT::i32);
4705 ResTys.push_back(MVT::Untyped);
4706 ResTys.push_back(MVT::Other);
4710 CurDAG->getRegister(0, MVT::i32), Chain};
4711 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4724 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
4725 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4726 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4729 ReplaceUses(
SDValue(
N, 0), Result);
4737 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
4738 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4739 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4742 ReplaceUses(
SDValue(
N, 1), Result);
4744 ReplaceUses(
SDValue(
N, 2), OutChain);
4745 CurDAG->RemoveDeadNode(
N);
4748 case Intrinsic::arm_stlexd:
4749 case Intrinsic::arm_strexd: {
4758 const EVT ResTys[] = {MVT::i32, MVT::Other};
4760 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
4764 Ops.push_back(Val0);
4765 Ops.push_back(Val1);
4769 Ops.push_back(MemAddr);
4771 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4772 Ops.push_back(Chain);
4774 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
4775 unsigned NewOpc =
isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
4776 : (IsRelease ?
ARM::STLEXD :
ARM::STREXD);
4778 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4787 case Intrinsic::arm_neon_vld1: {
4788 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
4789 ARM::VLD1d32, ARM::VLD1d64 };
4790 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4791 ARM::VLD1q32, ARM::VLD1q64};
4792 SelectVLD(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4796 case Intrinsic::arm_neon_vld1x2: {
4797 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4798 ARM::VLD1q32, ARM::VLD1q64 };
4799 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
4800 ARM::VLD1d16QPseudo,
4801 ARM::VLD1d32QPseudo,
4802 ARM::VLD1d64QPseudo };
4803 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4807 case Intrinsic::arm_neon_vld1x3: {
4808 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
4809 ARM::VLD1d16TPseudo,
4810 ARM::VLD1d32TPseudo,
4811 ARM::VLD1d64TPseudo };
4812 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
4813 ARM::VLD1q16LowTPseudo_UPD,
4814 ARM::VLD1q32LowTPseudo_UPD,
4815 ARM::VLD1q64LowTPseudo_UPD };
4816 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
4817 ARM::VLD1q16HighTPseudo,
4818 ARM::VLD1q32HighTPseudo,
4819 ARM::VLD1q64HighTPseudo };
4820 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4824 case Intrinsic::arm_neon_vld1x4: {
4825 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
4826 ARM::VLD1d16QPseudo,
4827 ARM::VLD1d32QPseudo,
4828 ARM::VLD1d64QPseudo };
4829 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
4830 ARM::VLD1q16LowQPseudo_UPD,
4831 ARM::VLD1q32LowQPseudo_UPD,
4832 ARM::VLD1q64LowQPseudo_UPD };
4833 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
4834 ARM::VLD1q16HighQPseudo,
4835 ARM::VLD1q32HighQPseudo,
4836 ARM::VLD1q64HighQPseudo };
4837 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4841 case Intrinsic::arm_neon_vld2: {
4842 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
4843 ARM::VLD2d32, ARM::VLD1q64 };
4844 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
4845 ARM::VLD2q32Pseudo };
4846 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4850 case Intrinsic::arm_neon_vld3: {
4851 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
4854 ARM::VLD1d64TPseudo };
4855 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4856 ARM::VLD3q16Pseudo_UPD,
4857 ARM::VLD3q32Pseudo_UPD };
4858 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
4859 ARM::VLD3q16oddPseudo,
4860 ARM::VLD3q32oddPseudo };
4861 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4865 case Intrinsic::arm_neon_vld4: {
4866 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
4869 ARM::VLD1d64QPseudo };
4870 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
4871 ARM::VLD4q16Pseudo_UPD,
4872 ARM::VLD4q32Pseudo_UPD };
4873 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
4874 ARM::VLD4q16oddPseudo,
4875 ARM::VLD4q32oddPseudo };
4876 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4880 case Intrinsic::arm_neon_vld2dup: {
4881 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4882 ARM::VLD2DUPd32, ARM::VLD1q64 };
4883 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4884 ARM::VLD2DUPq16EvenPseudo,
4885 ARM::VLD2DUPq32EvenPseudo };
4886 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo,
4887 ARM::VLD2DUPq16OddPseudo,
4888 ARM::VLD2DUPq32OddPseudo };
4889 SelectVLDDup(
N,
true,
false, 2,
4890 DOpcodes, QOpcodes0, QOpcodes1);
4894 case Intrinsic::arm_neon_vld3dup: {
4895 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo,
4896 ARM::VLD3DUPd16Pseudo,
4897 ARM::VLD3DUPd32Pseudo,
4898 ARM::VLD1d64TPseudo };
4899 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4900 ARM::VLD3DUPq16EvenPseudo,
4901 ARM::VLD3DUPq32EvenPseudo };
4902 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo,
4903 ARM::VLD3DUPq16OddPseudo,
4904 ARM::VLD3DUPq32OddPseudo };
4905 SelectVLDDup(
N,
true,
false, 3,
4906 DOpcodes, QOpcodes0, QOpcodes1);
4910 case Intrinsic::arm_neon_vld4dup: {
4911 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo,
4912 ARM::VLD4DUPd16Pseudo,
4913 ARM::VLD4DUPd32Pseudo,
4914 ARM::VLD1d64QPseudo };
4915 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4916 ARM::VLD4DUPq16EvenPseudo,
4917 ARM::VLD4DUPq32EvenPseudo };
4918 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo,
4919 ARM::VLD4DUPq16OddPseudo,
4920 ARM::VLD4DUPq32OddPseudo };
4921 SelectVLDDup(
N,
true,
false, 4,
4922 DOpcodes, QOpcodes0, QOpcodes1);
4926 case Intrinsic::arm_neon_vld2lane: {
4927 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
4928 ARM::VLD2LNd16Pseudo,
4929 ARM::VLD2LNd32Pseudo };
4930 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
4931 ARM::VLD2LNq32Pseudo };
4932 SelectVLDSTLane(
N,
true,
false, 2, DOpcodes, QOpcodes);
4936 case Intrinsic::arm_neon_vld3lane: {
4937 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
4938 ARM::VLD3LNd16Pseudo,
4939 ARM::VLD3LNd32Pseudo };
4940 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
4941 ARM::VLD3LNq32Pseudo };
4942 SelectVLDSTLane(
N,
true,
false, 3, DOpcodes, QOpcodes);
4946 case Intrinsic::arm_neon_vld4lane: {
4947 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
4948 ARM::VLD4LNd16Pseudo,
4949 ARM::VLD4LNd32Pseudo };
4950 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
4951 ARM::VLD4LNq32Pseudo };
4952 SelectVLDSTLane(
N,
true,
false, 4, DOpcodes, QOpcodes);
4956 case Intrinsic::arm_neon_vst1: {
4957 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
4958 ARM::VST1d32, ARM::VST1d64 };
4959 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
4960 ARM::VST1q32, ARM::VST1q64 };
4961 SelectVST(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4965 case Intrinsic::arm_neon_vst1x2: {
4966 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
4967 ARM::VST1q32, ARM::VST1q64 };
4968 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
4969 ARM::VST1d16QPseudo,
4970 ARM::VST1d32QPseudo,
4971 ARM::VST1d64QPseudo };
4972 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4976 case Intrinsic::arm_neon_vst1x3: {
4977 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
4978 ARM::VST1d16TPseudo,
4979 ARM::VST1d32TPseudo,
4980 ARM::VST1d64TPseudo };
4981 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4982 ARM::VST1q16LowTPseudo_UPD,
4983 ARM::VST1q32LowTPseudo_UPD,
4984 ARM::VST1q64LowTPseudo_UPD };
4985 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
4986 ARM::VST1q16HighTPseudo,
4987 ARM::VST1q32HighTPseudo,
4988 ARM::VST1q64HighTPseudo };
4989 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4993 case Intrinsic::arm_neon_vst1x4: {
4994 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
4995 ARM::VST1d16QPseudo,
4996 ARM::VST1d32QPseudo,
4997 ARM::VST1d64QPseudo };
4998 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4999 ARM::VST1q16LowQPseudo_UPD,
5000 ARM::VST1q32LowQPseudo_UPD,
5001 ARM::VST1q64LowQPseudo_UPD };
5002 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
5003 ARM::VST1q16HighQPseudo,
5004 ARM::VST1q32HighQPseudo,
5005 ARM::VST1q64HighQPseudo };
5006 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5010 case Intrinsic::arm_neon_vst2: {
5011 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
5012 ARM::VST2d32, ARM::VST1q64 };
5013 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
5014 ARM::VST2q32Pseudo };
5015 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
5019 case Intrinsic::arm_neon_vst3: {
5020 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
5023 ARM::VST1d64TPseudo };
5024 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
5025 ARM::VST3q16Pseudo_UPD,
5026 ARM::VST3q32Pseudo_UPD };
5027 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
5028 ARM::VST3q16oddPseudo,
5029 ARM::VST3q32oddPseudo };
5030 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
5034 case Intrinsic::arm_neon_vst4: {
5035 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
5038 ARM::VST1d64QPseudo };
5039 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
5040 ARM::VST4q16Pseudo_UPD,
5041 ARM::VST4q32Pseudo_UPD };
5042 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
5043 ARM::VST4q16oddPseudo,
5044 ARM::VST4q32oddPseudo };
5045 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5049 case Intrinsic::arm_neon_vst2lane: {
5050 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
5051 ARM::VST2LNd16Pseudo,
5052 ARM::VST2LNd32Pseudo };
5053 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
5054 ARM::VST2LNq32Pseudo };
5055 SelectVLDSTLane(
N,
false,
false, 2, DOpcodes, QOpcodes);
5059 case Intrinsic::arm_neon_vst3lane: {
5060 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
5061 ARM::VST3LNd16Pseudo,
5062 ARM::VST3LNd32Pseudo };
5063 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
5064 ARM::VST3LNq32Pseudo };
5065 SelectVLDSTLane(
N,
false,
false, 3, DOpcodes, QOpcodes);
5069 case Intrinsic::arm_neon_vst4lane: {
5070 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
5071 ARM::VST4LNd16Pseudo,
5072 ARM::VST4LNd32Pseudo };
5073 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
5074 ARM::VST4LNq32Pseudo };
5075 SelectVLDSTLane(
N,
false,
false, 4, DOpcodes, QOpcodes);
5079 case Intrinsic::arm_mve_vldr_gather_base_wb:
5080 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
5081 static const uint16_t Opcodes[] = {ARM::MVE_VLDRWU32_qi_pre,
5082 ARM::MVE_VLDRDU64_qi_pre};
5083 SelectMVE_WB(
N, Opcodes,
5084 IntNo == Intrinsic::arm_mve_vldr_gather_base_wb_predicated);
5088 case Intrinsic::arm_mve_vld2q: {
5089 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, ARM::MVE_VLD21_8};
5090 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
5092 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
5094 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5095 SelectMVE_VLD(
N, 2, Opcodes,
false);
5099 case Intrinsic::arm_mve_vld4q: {
5100 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
5101 ARM::MVE_VLD42_8, ARM::MVE_VLD43_8};
5102 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
5105 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
5108 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5109 SelectMVE_VLD(
N, 4, Opcodes,
false);
5117 unsigned IntNo =
N->getConstantOperandVal(0);
5123 case Intrinsic::arm_neon_vcvtbfp2bf: {
5125 const SDValue &Src =
N->getOperand(1);
5126 llvm::EVT DestTy =
N->getValueType(0);
5128 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5130 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVTB, DestTy,
Ops);
5135 case Intrinsic::arm_neon_vcvtfp2bf: {
5137 const SDValue &Src =
N->getOperand(1);
5139 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5141 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVT, MVT::v4bf16,
Ops);
5145 case Intrinsic::arm_mve_urshrl:
5146 SelectMVE_LongShift(
N, ARM::MVE_URSHRL,
true,
false);
5148 case Intrinsic::arm_mve_uqshll:
5149 SelectMVE_LongShift(
N, ARM::MVE_UQSHLL,
true,
false);
5151 case Intrinsic::arm_mve_srshrl:
5152 SelectMVE_LongShift(
N, ARM::MVE_SRSHRL,
true,
false);
5154 case Intrinsic::arm_mve_sqshll:
5155 SelectMVE_LongShift(
N, ARM::MVE_SQSHLL,
true,
false);
5157 case Intrinsic::arm_mve_uqrshll:
5158 SelectMVE_LongShift(
N, ARM::MVE_UQRSHLL,
false,
true);
5160 case Intrinsic::arm_mve_sqrshrl:
5161 SelectMVE_LongShift(
N, ARM::MVE_SQRSHRL,
false,
true);
5164 case Intrinsic::arm_mve_vadc:
5165 case Intrinsic::arm_mve_vadc_predicated:
5166 SelectMVE_VADCSBC(
N, ARM::MVE_VADC, ARM::MVE_VADCI,
true,
5167 IntNo == Intrinsic::arm_mve_vadc_predicated);
5169 case Intrinsic::arm_mve_vsbc:
5170 case Intrinsic::arm_mve_vsbc_predicated:
5171 SelectMVE_VADCSBC(
N, ARM::MVE_VSBC, ARM::MVE_VSBCI,
false,
5172 IntNo == Intrinsic::arm_mve_vsbc_predicated);
5174 case Intrinsic::arm_mve_vshlc:
5175 case Intrinsic::arm_mve_vshlc_predicated:
5176 SelectMVE_VSHLC(
N, IntNo == Intrinsic::arm_mve_vshlc_predicated);
5179 case Intrinsic::arm_mve_vmlldava:
5180 case Intrinsic::arm_mve_vmlldava_predicated: {
5181 static const uint16_t OpcodesU[] = {
5182 ARM::MVE_VMLALDAVu16, ARM::MVE_VMLALDAVu32,
5183 ARM::MVE_VMLALDAVau16, ARM::MVE_VMLALDAVau32,
5185 static const uint16_t OpcodesS[] = {
5186 ARM::MVE_VMLALDAVs16, ARM::MVE_VMLALDAVs32,
5187 ARM::MVE_VMLALDAVas16, ARM::MVE_VMLALDAVas32,
5188 ARM::MVE_VMLALDAVxs16, ARM::MVE_VMLALDAVxs32,
5189 ARM::MVE_VMLALDAVaxs16, ARM::MVE_VMLALDAVaxs32,
5190 ARM::MVE_VMLSLDAVs16, ARM::MVE_VMLSLDAVs32,
5191 ARM::MVE_VMLSLDAVas16, ARM::MVE_VMLSLDAVas32,
5192 ARM::MVE_VMLSLDAVxs16, ARM::MVE_VMLSLDAVxs32,
5193 ARM::MVE_VMLSLDAVaxs16, ARM::MVE_VMLSLDAVaxs32,
5195 SelectMVE_VMLLDAV(
N, IntNo == Intrinsic::arm_mve_vmlldava_predicated,
5196 OpcodesS, OpcodesU);
5200 case Intrinsic::arm_mve_vrmlldavha:
5201 case Intrinsic::arm_mve_vrmlldavha_predicated: {
5202 static const uint16_t OpcodesU[] = {
5203 ARM::MVE_VRMLALDAVHu32, ARM::MVE_VRMLALDAVHau32,
5205 static const uint16_t OpcodesS[] = {
5206 ARM::MVE_VRMLALDAVHs32, ARM::MVE_VRMLALDAVHas32,
5207 ARM::MVE_VRMLALDAVHxs32, ARM::MVE_VRMLALDAVHaxs32,
5208 ARM::MVE_VRMLSLDAVHs32, ARM::MVE_VRMLSLDAVHas32,
5209 ARM::MVE_VRMLSLDAVHxs32, ARM::MVE_VRMLSLDAVHaxs32,
5211 SelectMVE_VRMLLDAVH(
N, IntNo == Intrinsic::arm_mve_vrmlldavha_predicated,
5212 OpcodesS, OpcodesU);
5216 case Intrinsic::arm_mve_vidup:
5217 case Intrinsic::arm_mve_vidup_predicated: {
5218 static const uint16_t Opcodes[] = {
5219 ARM::MVE_VIDUPu8, ARM::MVE_VIDUPu16, ARM::MVE_VIDUPu32,
5221 SelectMVE_VxDUP(
N, Opcodes,
false,
5222 IntNo == Intrinsic::arm_mve_vidup_predicated);
5226 case Intrinsic::arm_mve_vddup:
5227 case Intrinsic::arm_mve_vddup_predicated: {
5228 static const uint16_t Opcodes[] = {
5229 ARM::MVE_VDDUPu8, ARM::MVE_VDDUPu16, ARM::MVE_VDDUPu32,
5231 SelectMVE_VxDUP(
N, Opcodes,
false,
5232 IntNo == Intrinsic::arm_mve_vddup_predicated);
5236 case Intrinsic::arm_mve_viwdup:
5237 case Intrinsic::arm_mve_viwdup_predicated: {
5238 static const uint16_t Opcodes[] = {
5239 ARM::MVE_VIWDUPu8, ARM::MVE_VIWDUPu16, ARM::MVE_VIWDUPu32,
5241 SelectMVE_VxDUP(
N, Opcodes,
true,
5242 IntNo == Intrinsic::arm_mve_viwdup_predicated);
5246 case Intrinsic::arm_mve_vdwdup:
5247 case Intrinsic::arm_mve_vdwdup_predicated: {
5248 static const uint16_t Opcodes[] = {
5249 ARM::MVE_VDWDUPu8, ARM::MVE_VDWDUPu16, ARM::MVE_VDWDUPu32,
5251 SelectMVE_VxDUP(
N, Opcodes,
true,
5252 IntNo == Intrinsic::arm_mve_vdwdup_predicated);
5256 case Intrinsic::arm_cde_cx1d:
5257 case Intrinsic::arm_cde_cx1da:
5258 case Intrinsic::arm_cde_cx2d:
5259 case Intrinsic::arm_cde_cx2da:
5260 case Intrinsic::arm_cde_cx3d:
5261 case Intrinsic::arm_cde_cx3da: {
5262 bool HasAccum = IntNo == Intrinsic::arm_cde_cx1da ||
5263 IntNo == Intrinsic::arm_cde_cx2da ||
5264 IntNo == Intrinsic::arm_cde_cx3da;
5268 case Intrinsic::arm_cde_cx1d:
5269 case Intrinsic::arm_cde_cx1da:
5271 Opcode = HasAccum ? ARM::CDE_CX1DA : ARM::CDE_CX1D;
5273 case Intrinsic::arm_cde_cx2d:
5274 case Intrinsic::arm_cde_cx2da:
5276 Opcode = HasAccum ? ARM::CDE_CX2DA : ARM::CDE_CX2D;
5278 case Intrinsic::arm_cde_cx3d:
5279 case Intrinsic::arm_cde_cx3da:
5281 Opcode = HasAccum ? ARM::CDE_CX3DA : ARM::CDE_CX3D;
5286 SelectCDE_CXxD(
N, Opcode, NumExtraOps, HasAccum);
5293 case ISD::ATOMIC_CMP_SWAP:
5309 std::vector<SDValue> &
Ops) {
5311 RegString.
split(Fields,
':');
5313 if (Fields.
size() > 1) {
5314 bool AllIntFields =
true;
5319 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
5324 "Unexpected non-integer value in special register string.");
5335 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.
lower());
5338 return TheReg->Encoding;
5350 .
Case(
"nzcvqg", 0x3)
5358 auto TheReg = ARMSysReg::lookupMClassSysRegByName(
Reg);
5359 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
5360 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
5362 return (
int)(TheReg->Encoding & 0xFFF);
5371 if (
Reg ==
"apsr") {
5381 if (
Reg !=
"cpsr" &&
Reg !=
"spsr") {
5386 if (Flags.empty() || Flags ==
"all")
5391 for (
char Flag : Flags) {
5411 if (!FlagVal || (Mask & FlagVal))
5426bool ARMDAGToDAGISel::tryReadRegister(SDNode *
N){
5428 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5429 bool IsThumb2 = Subtarget->
isThumb2();
5432 std::vector<SDValue>
Ops;
5442 if (
Ops.size() == 5){
5443 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
5444 ResTypes.
append({ MVT::i32, MVT::Other });
5447 "Invalid number of fields in special register string.");
5448 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
5449 ResTypes.
append({ MVT::i32, MVT::i32, MVT::Other });
5453 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5454 Ops.push_back(
N->getOperand(0));
5455 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, ResTypes,
Ops));
5459 std::string SpecialReg = RegString->getString().lower();
5462 if (BankedReg != -1) {
5463 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
5464 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5467 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
5468 DL, MVT::i32, MVT::Other,
Ops));
5475 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5476 .Case(
"fpscr", ARM::VMRS)
5477 .Case(
"fpexc", ARM::VMRS_FPEXC)
5478 .Case(
"fpsid", ARM::VMRS_FPSID)
5479 .Case(
"mvfr0", ARM::VMRS_MVFR0)
5480 .Case(
"mvfr1", ARM::VMRS_MVFR1)
5481 .Case(
"mvfr2", ARM::VMRS_MVFR2)
5482 .Case(
"fpinst", ARM::VMRS_FPINST)
5483 .Case(
"fpinst2", ARM::VMRS_FPINST2)
5493 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5496 CurDAG->getMachineNode(Opcode,
DL, MVT::i32, MVT::Other,
Ops));
5505 if (SYSmValue == -1)
5508 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5509 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5512 N, CurDAG->getMachineNode(ARM::t2MRS_M,
DL, MVT::i32, MVT::Other,
Ops));
5518 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
5519 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5521 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
5522 DL, MVT::i32, MVT::Other,
Ops));
5526 if (SpecialReg ==
"spsr") {
5527 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5530 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
DL,
5531 MVT::i32, MVT::Other,
Ops));
5541bool ARMDAGToDAGISel::tryWriteRegister(SDNode *
N){
5543 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5544 bool IsThumb2 = Subtarget->
isThumb2();
5547 std::vector<SDValue>
Ops;
5556 if (
Ops.size() == 5) {
5557 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
5558 Ops.insert(
Ops.begin()+2,
N->getOperand(2));
5561 "Invalid number of fields in special register string.");
5562 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
5563 SDValue WriteValue[] = {
N->getOperand(2),
N->getOperand(3) };
5564 Ops.insert(
Ops.begin()+2, WriteValue, WriteValue+2);
5568 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5569 Ops.push_back(
N->getOperand(0));
5571 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5575 std::string SpecialReg = RegString->getString().lower();
5577 if (BankedReg != -1) {
5578 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
N->getOperand(2),
5579 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5582 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
5583 DL, MVT::Other,
Ops));
5590 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5591 .Case(
"fpscr", ARM::VMSR)
5592 .Case(
"fpexc", ARM::VMSR_FPEXC)
5593 .Case(
"fpsid", ARM::VMSR_FPSID)
5594 .Case(
"fpinst", ARM::VMSR_FPINST)
5595 .Case(
"fpinst2", ARM::VMSR_FPINST2)
5602 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5603 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5607 std::pair<StringRef, StringRef> Fields;
5608 Fields = StringRef(SpecialReg).rsplit(
'_');
5609 std::string
Reg = Fields.first.str();
5610 StringRef
Flags = Fields.second;
5616 if (SYSmValue == -1)
5619 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5620 N->getOperand(2),
getAL(CurDAG,
DL),
5621 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5622 ReplaceNode(
N, CurDAG->getMachineNode(ARM::t2MSR_M,
DL, MVT::Other,
Ops));
5631 Ops = { CurDAG->getTargetConstant(Mask,
DL, MVT::i32),
N->getOperand(2),
5632 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5634 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
5635 DL, MVT::Other,
Ops));
5642bool ARMDAGToDAGISel::tryInlineAsm(SDNode *
N){
5643 std::vector<SDValue> AsmNodeOperands;
5644 InlineAsm::Flag
Flag;
5646 unsigned NumOps =
N->getNumOperands();
5661 for(
unsigned i = 0, e =
N->getGluedNode() ?
NumOps - 1 :
NumOps; i < e; ++i) {
5663 AsmNodeOperands.push_back(
op);
5669 Flag = InlineAsm::Flag(
C->getZExtValue());
5677 if (
Flag.isImmKind()) {
5679 AsmNodeOperands.push_back(
op);
5683 const unsigned NumRegs =
Flag.getNumOperandRegisters();
5687 unsigned DefIdx = 0;
5688 bool IsTiedToChangedOp =
false;
5691 if (
Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
5692 IsTiedToChangedOp = OpChanged[DefIdx];
5699 if (
Flag.isMemKind()) {
5701 AsmNodeOperands.push_back(
op);
5705 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
5706 !
Flag.isRegDefEarlyClobberKind())
5710 const bool HasRC =
Flag.hasRegClassConstraint(RC);
5711 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
5715 assert((i+2 <
NumOps) &&
"Invalid number of operands in inline asm");
5723 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
5727 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5728 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5731 SDNode *GU =
N->getGluedUser();
5732 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
5736 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
5738 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
5740 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
5746 Ops.push_back(
T1.getValue(1));
5747 CurDAG->UpdateNodeOperands(GU,
Ops);
5754 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
5756 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
5762 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5763 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5764 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
5773 OpChanged[OpChanged.
size() -1 ] =
true;
5774 Flag = InlineAsm::Flag(
Flag.getKind(), 1 );
5775 if (IsTiedToChangedOp)
5776 Flag.setMatchingOp(DefIdx);
5778 Flag.setRegClass(ARM::GPRPairRegClassID);
5780 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
5781 Flag, dl, MVT::i32);
5783 AsmNodeOperands.push_back(PairedReg);
5790 AsmNodeOperands.push_back(Glue);
5794 SDValue New = CurDAG->getNode(
N->getOpcode(), SDLoc(
N),
5795 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
5797 ReplaceNode(
N,
New.getNode());
5801bool ARMDAGToDAGISel::SelectInlineAsmMemoryOperand(
5803 std::vector<SDValue> &OutOps) {
5804 switch(ConstraintID) {
5807 case InlineAsm::ConstraintCode::m:
5808 case InlineAsm::ConstraintCode::o:
5809 case InlineAsm::ConstraintCode::Q:
5810 case InlineAsm::ConstraintCode::Um:
5811 case InlineAsm::ConstraintCode::Un:
5812 case InlineAsm::ConstraintCode::Uq:
5813 case InlineAsm::ConstraintCode::Us:
5814 case InlineAsm::ConstraintCode::Ut:
5815 case InlineAsm::ConstraintCode::Uv:
5816 case InlineAsm::ConstraintCode::Uy:
5820 OutOps.push_back(
Op);
5831 return new ARMDAGToDAGISelLegacy(TM, OptLevel);
unsigned const MachineRegisterInfo * MRI
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...
static bool isSigned(unsigned int Opcode)
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...
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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.
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.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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.
@ 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.
@ 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.
@ 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,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ 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 ...
@ 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.
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.