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);
680 if (
N.getOpcode() == ARMISD::Wrapper &&
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()));
989 }
else if (
N.getOpcode() == ARMISD::Wrapper &&
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,
1095 if (
N.getOpcode() == ARMISD::PIC_ADD &&
N.hasOneUse()) {
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)) {
1158 }
else if (
N.getOpcode() == ARMISD::Wrapper &&
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);
1292 if (
N.getOpcode() == ARMISD::Wrapper &&
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)
3099 Val1.
getOpcode() == ARMISD::VGETLANEu) &&
3101 Val2.
getOpcode() == ARMISD::VGETLANEu) &&
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) {
3193 case ARMISD::VMOVIMM:
3194 case ARMISD::VDUP: {
3198 if (ImmNode.
getOpcode() == ARMISD::VMOVIMM)
3201 APFloat(ScalarBits == 32 ? APFloat::IEEEsingle() : APFloat::IEEEhalf(),
3202 APInt(ScalarBits, Imm));
3205 case ARMISD::VMOVFPIMM: {
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) {
3496 assert(
N->getOpcode() == ARMISD::CMPZ);
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()) {
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));
3872 case ARMISD::UMAAL: {
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));
3881 case ARMISD::UMLAL:{
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));
3900 case ARMISD::SMLAL:{
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));
3919 case ARMISD::SUBE: {
3920 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
3925 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
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))
3968 case ARMISD::LDRD: {
3974 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
3975 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
3981 RegOffset = CurDAG->getRegister(0, MVT::i32);
3984 SDNode *
New = CurDAG->getMachineNode(ARM::LOADDUAL, dl,
3985 {MVT::Untyped, MVT::Other},
Ops);
3986 SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3988 SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3990 transferMemOperands(
N, New);
3994 CurDAG->RemoveDeadNode(
N);
3997 case ARMISD::STRD: {
4003 SelectAddrMode3(Addr,
Base, RegOffset, ImmOffset);
4004 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) {
4010 RegOffset = CurDAG->getRegister(0, MVT::i32);
4015 SDNode *
New = CurDAG->getMachineNode(ARM::STOREDUAL, dl, MVT::Other,
Ops);
4016 transferMemOperands(
N, New);
4018 CurDAG->RemoveDeadNode(
N);
4021 case ARMISD::BRCOND: {
4034 unsigned Opc = Subtarget->isThumb() ?
4035 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
4045 if (
Flags.getOpcode() == ARMISD::CMPZ) {
4048 uint64_t
ID =
Int->getConstantOperandVal(1);
4051 if (
ID == Intrinsic::loop_decrement_reg) {
4053 SDValue Size = CurDAG->getTargetConstant(
Int.getConstantOperandVal(3),
4058 CurDAG->getMachineNode(ARM::t2LoopDec, dl,
4059 CurDAG->getVTList(MVT::i32, MVT::Other),
4061 ReplaceUses(
Int.getNode(), LoopDec);
4065 CurDAG->getMachineNode(ARM::t2LoopEnd, dl, MVT::Other, EndArgs);
4067 ReplaceUses(
N, LoopEnd);
4068 CurDAG->RemoveDeadNode(
N);
4069 CurDAG->RemoveDeadNode(
Flags.getNode());
4070 CurDAG->RemoveDeadNode(
Int.getNode());
4075 bool SwitchEQNEToPLMI;
4076 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4077 Flags =
N->getOperand(3);
4079 if (SwitchEQNEToPLMI) {
4092 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
4093 Chain = CurDAG->getCopyToReg(Chain, dl, ARM::CPSR, Flags,
SDValue());
4094 SDValue Ops[] = {N1, Tmp2, CurDAG->getRegister(ARM::CPSR, MVT::i32), Chain,
4096 CurDAG->SelectNodeTo(
N,
Opc, MVT::Other,
Ops);
4100 case ARMISD::CMPZ: {
4107 if (
C &&
C->getSExtValue() < 0 && Subtarget->isThumb()) {
4108 int64_t Addend = -
C->getSExtValue();
4110 SDNode *
Add =
nullptr;
4115 if (Addend < 1<<8) {
4117 SDValue Ops[] = {
X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4118 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
4119 CurDAG->getRegister(0, MVT::i32) };
4120 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32,
Ops);
4122 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 :
ARM::tADDi8;
4123 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
X,
4124 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
4125 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
4126 Add = CurDAG->getMachineNode(
Opc, dl, MVT::i32,
Ops);
4131 CurDAG->MorphNodeTo(
N, ARMISD::CMPZ,
N->getVTList(), Ops2);
4138 case ARMISD::CMOV: {
4141 if (
Flags.getOpcode() == ARMISD::CMPZ) {
4142 bool SwitchEQNEToPLMI;
4143 SelectCMPZ(
Flags.getNode(), SwitchEQNEToPLMI);
4145 if (SwitchEQNEToPLMI) {
4158 SDValue NewARMcc = CurDAG->getConstant((
unsigned)CC, dl, MVT::i32);
4159 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), NewARMcc,
4161 CurDAG->MorphNodeTo(
N, ARMISD::CMOV,
N->getVTList(),
Ops);
4167 case ARMISD::VZIP: {
4168 EVT VT =
N->getValueType(0);
4170 unsigned Opc64[] = {ARM::VZIPd8, ARM::VZIPd16, ARM::VTRNd32};
4171 unsigned Opc128[] = {ARM::VZIPq8, ARM::VZIPq16, ARM::VZIPq32};
4174 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4175 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4176 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4179 case ARMISD::VUZP: {
4180 EVT VT =
N->getValueType(0);
4182 unsigned Opc64[] = {ARM::VUZPd8, ARM::VUZPd16, ARM::VTRNd32};
4183 unsigned Opc128[] = {ARM::VUZPq8, ARM::VUZPq16, ARM::VUZPq32};
4186 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4187 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4188 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4191 case ARMISD::VTRN: {
4192 EVT VT =
N->getValueType(0);
4193 unsigned Opc64[] = {ARM::VTRNd8, ARM::VTRNd16, ARM::VTRNd32};
4194 unsigned Opc128[] = {ARM::VTRNq8, ARM::VTRNq16, ARM::VTRNq32};
4197 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
4198 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), Pred, PredReg};
4199 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, VT, VT,
Ops));
4203 EVT VecVT =
N->getValueType(0);
4206 if (EltVT == MVT::f64) {
4207 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
4209 N, createDRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4212 assert(EltVT == MVT::f32 &&
"unexpected type for BUILD_VECTOR");
4215 N, createSRegPairNode(VecVT,
N->getOperand(0),
N->getOperand(1)));
4218 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
4220 createQuadSRegsNode(VecVT,
N->getOperand(0),
N->getOperand(1),
4221 N->getOperand(2),
N->getOperand(3)));
4226 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
4228 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
4230 SelectVLDDup(
N,
false,
false, 1, DOpcodes, QOpcodes);
4235 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4237 SelectVLDDup(
N,
false,
false, 2, Opcodes);
4242 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
4243 ARM::VLD3DUPd16Pseudo,
4244 ARM::VLD3DUPd32Pseudo };
4245 SelectVLDDup(
N,
false,
false, 3, Opcodes);
4250 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
4251 ARM::VLD4DUPd16Pseudo,
4252 ARM::VLD4DUPd32Pseudo };
4253 SelectVLDDup(
N,
false,
false, 4, Opcodes);
4258 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
4259 ARM::VLD1DUPd16wb_fixed,
4260 ARM::VLD1DUPd32wb_fixed };
4261 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
4262 ARM::VLD1DUPq16wb_fixed,
4263 ARM::VLD1DUPq32wb_fixed };
4264 SelectVLDDup(
N,
false,
true, 1, DOpcodes, QOpcodes);
4269 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8wb_fixed,
4270 ARM::VLD2DUPd16wb_fixed,
4271 ARM::VLD2DUPd32wb_fixed,
4272 ARM::VLD1q64wb_fixed };
4273 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4274 ARM::VLD2DUPq16EvenPseudo,
4275 ARM::VLD2DUPq32EvenPseudo };
4276 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudoWB_fixed,
4277 ARM::VLD2DUPq16OddPseudoWB_fixed,
4278 ARM::VLD2DUPq32OddPseudoWB_fixed };
4279 SelectVLDDup(
N,
false,
true, 2, DOpcodes, QOpcodes0, QOpcodes1);
4284 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
4285 ARM::VLD3DUPd16Pseudo_UPD,
4286 ARM::VLD3DUPd32Pseudo_UPD,
4287 ARM::VLD1d64TPseudoWB_fixed };
4288 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4289 ARM::VLD3DUPq16EvenPseudo,
4290 ARM::VLD3DUPq32EvenPseudo };
4291 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo_UPD,
4292 ARM::VLD3DUPq16OddPseudo_UPD,
4293 ARM::VLD3DUPq32OddPseudo_UPD };
4294 SelectVLDDup(
N,
false,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4299 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
4300 ARM::VLD4DUPd16Pseudo_UPD,
4301 ARM::VLD4DUPd32Pseudo_UPD,
4302 ARM::VLD1d64QPseudoWB_fixed };
4303 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4304 ARM::VLD4DUPq16EvenPseudo,
4305 ARM::VLD4DUPq32EvenPseudo };
4306 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo_UPD,
4307 ARM::VLD4DUPq16OddPseudo_UPD,
4308 ARM::VLD4DUPq32OddPseudo_UPD };
4309 SelectVLDDup(
N,
false,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4314 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
4315 ARM::VLD1d16wb_fixed,
4316 ARM::VLD1d32wb_fixed,
4317 ARM::VLD1d64wb_fixed };
4318 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
4319 ARM::VLD1q16wb_fixed,
4320 ARM::VLD1q32wb_fixed,
4321 ARM::VLD1q64wb_fixed };
4322 SelectVLD(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4327 if (Subtarget->hasNEON()) {
4328 static const uint16_t DOpcodes[] = {
4329 ARM::VLD2d8wb_fixed, ARM::VLD2d16wb_fixed, ARM::VLD2d32wb_fixed,
4330 ARM::VLD1q64wb_fixed};
4331 static const uint16_t QOpcodes[] = {ARM::VLD2q8PseudoWB_fixed,
4332 ARM::VLD2q16PseudoWB_fixed,
4333 ARM::VLD2q32PseudoWB_fixed};
4334 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4336 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8,
4337 ARM::MVE_VLD21_8_wb};
4338 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
4339 ARM::MVE_VLD21_16_wb};
4340 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
4341 ARM::MVE_VLD21_32_wb};
4342 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4343 SelectMVE_VLD(
N, 2, Opcodes,
true);
4349 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
4350 ARM::VLD3d16Pseudo_UPD,
4351 ARM::VLD3d32Pseudo_UPD,
4352 ARM::VLD1d64TPseudoWB_fixed};
4353 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4354 ARM::VLD3q16Pseudo_UPD,
4355 ARM::VLD3q32Pseudo_UPD };
4356 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
4357 ARM::VLD3q16oddPseudo_UPD,
4358 ARM::VLD3q32oddPseudo_UPD };
4359 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4364 if (Subtarget->hasNEON()) {
4365 static const uint16_t DOpcodes[] = {
4366 ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, ARM::VLD4d32Pseudo_UPD,
4367 ARM::VLD1d64QPseudoWB_fixed};
4368 static const uint16_t QOpcodes0[] = {ARM::VLD4q8Pseudo_UPD,
4369 ARM::VLD4q16Pseudo_UPD,
4370 ARM::VLD4q32Pseudo_UPD};
4371 static const uint16_t QOpcodes1[] = {ARM::VLD4q8oddPseudo_UPD,
4372 ARM::VLD4q16oddPseudo_UPD,
4373 ARM::VLD4q32oddPseudo_UPD};
4374 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4376 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
4378 ARM::MVE_VLD43_8_wb};
4379 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
4381 ARM::MVE_VLD43_16_wb};
4382 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
4384 ARM::MVE_VLD43_32_wb};
4385 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
4386 SelectMVE_VLD(
N, 4, Opcodes,
true);
4392 if (Subtarget->hasNEON()) {
4393 static const uint16_t DOpcodes[] = {
4394 ARM::VLD1q8wb_fixed, ARM::VLD1q16wb_fixed, ARM::VLD1q32wb_fixed,
4395 ARM::VLD1q64wb_fixed};
4396 static const uint16_t QOpcodes[] = {
4397 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4398 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4399 SelectVLD(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4406 if (Subtarget->hasNEON()) {
4407 static const uint16_t DOpcodes[] = {
4408 ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d16TPseudoWB_fixed,
4409 ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d64TPseudoWB_fixed};
4410 static const uint16_t QOpcodes0[] = {
4411 ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1q16LowTPseudo_UPD,
4412 ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1q64LowTPseudo_UPD};
4413 static const uint16_t QOpcodes1[] = {
4414 ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1q16HighTPseudo_UPD,
4415 ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1q64HighTPseudo_UPD};
4416 SelectVLD(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4423 if (Subtarget->hasNEON()) {
4424 static const uint16_t DOpcodes[] = {
4425 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed,
4426 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed};
4427 static const uint16_t QOpcodes0[] = {
4428 ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1q16LowQPseudo_UPD,
4429 ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1q64LowQPseudo_UPD};
4430 static const uint16_t QOpcodes1[] = {
4431 ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1q16HighQPseudo_UPD,
4432 ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1q64HighQPseudo_UPD};
4433 SelectVLD(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4440 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
4441 ARM::VLD2LNd16Pseudo_UPD,
4442 ARM::VLD2LNd32Pseudo_UPD };
4443 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
4444 ARM::VLD2LNq32Pseudo_UPD };
4445 SelectVLDSTLane(
N,
true,
true, 2, DOpcodes, QOpcodes);
4450 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
4451 ARM::VLD3LNd16Pseudo_UPD,
4452 ARM::VLD3LNd32Pseudo_UPD };
4453 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
4454 ARM::VLD3LNq32Pseudo_UPD };
4455 SelectVLDSTLane(
N,
true,
true, 3, DOpcodes, QOpcodes);
4460 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
4461 ARM::VLD4LNd16Pseudo_UPD,
4462 ARM::VLD4LNd32Pseudo_UPD };
4463 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
4464 ARM::VLD4LNq32Pseudo_UPD };
4465 SelectVLDSTLane(
N,
true,
true, 4, DOpcodes, QOpcodes);
4470 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
4471 ARM::VST1d16wb_fixed,
4472 ARM::VST1d32wb_fixed,
4473 ARM::VST1d64wb_fixed };
4474 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
4475 ARM::VST1q16wb_fixed,
4476 ARM::VST1q32wb_fixed,
4477 ARM::VST1q64wb_fixed };
4478 SelectVST(
N,
true, 1, DOpcodes, QOpcodes,
nullptr);
4482 case ARMISD::VST2_UPD: {
4483 if (Subtarget->hasNEON()) {
4484 static const uint16_t DOpcodes[] = {
4485 ARM::VST2d8wb_fixed, ARM::VST2d16wb_fixed, ARM::VST2d32wb_fixed,
4486 ARM::VST1q64wb_fixed};
4487 static const uint16_t QOpcodes[] = {ARM::VST2q8PseudoWB_fixed,
4488 ARM::VST2q16PseudoWB_fixed,
4489 ARM::VST2q32PseudoWB_fixed};
4490 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4497 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
4498 ARM::VST3d16Pseudo_UPD,
4499 ARM::VST3d32Pseudo_UPD,
4500 ARM::VST1d64TPseudoWB_fixed};
4501 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
4502 ARM::VST3q16Pseudo_UPD,
4503 ARM::VST3q32Pseudo_UPD };
4504 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
4505 ARM::VST3q16oddPseudo_UPD,
4506 ARM::VST3q32oddPseudo_UPD };
4507 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4511 case ARMISD::VST4_UPD: {
4512 if (Subtarget->hasNEON()) {
4513 static const uint16_t DOpcodes[] = {
4514 ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, ARM::VST4d32Pseudo_UPD,
4515 ARM::VST1d64QPseudoWB_fixed};
4516 static const uint16_t QOpcodes0[] = {ARM::VST4q8Pseudo_UPD,
4517 ARM::VST4q16Pseudo_UPD,
4518 ARM::VST4q32Pseudo_UPD};
4519 static const uint16_t QOpcodes1[] = {ARM::VST4q8oddPseudo_UPD,
4520 ARM::VST4q16oddPseudo_UPD,
4521 ARM::VST4q32oddPseudo_UPD};
4522 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4529 if (Subtarget->hasNEON()) {
4530 static const uint16_t DOpcodes[] = { ARM::VST1q8wb_fixed,
4531 ARM::VST1q16wb_fixed,
4532 ARM::VST1q32wb_fixed,
4533 ARM::VST1q64wb_fixed};
4534 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4535 ARM::VST1d16QPseudoWB_fixed,
4536 ARM::VST1d32QPseudoWB_fixed,
4537 ARM::VST1d64QPseudoWB_fixed };
4538 SelectVST(
N,
true, 2, DOpcodes, QOpcodes,
nullptr);
4545 if (Subtarget->hasNEON()) {
4546 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudoWB_fixed,
4547 ARM::VST1d16TPseudoWB_fixed,
4548 ARM::VST1d32TPseudoWB_fixed,
4549 ARM::VST1d64TPseudoWB_fixed };
4550 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4551 ARM::VST1q16LowTPseudo_UPD,
4552 ARM::VST1q32LowTPseudo_UPD,
4553 ARM::VST1q64LowTPseudo_UPD };
4554 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo_UPD,
4555 ARM::VST1q16HighTPseudo_UPD,
4556 ARM::VST1q32HighTPseudo_UPD,
4557 ARM::VST1q64HighTPseudo_UPD };
4558 SelectVST(
N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
4565 if (Subtarget->hasNEON()) {
4566 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudoWB_fixed,
4567 ARM::VST1d16QPseudoWB_fixed,
4568 ARM::VST1d32QPseudoWB_fixed,
4569 ARM::VST1d64QPseudoWB_fixed };
4570 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4571 ARM::VST1q16LowQPseudo_UPD,
4572 ARM::VST1q32LowQPseudo_UPD,
4573 ARM::VST1q64LowQPseudo_UPD };
4574 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo_UPD,
4575 ARM::VST1q16HighQPseudo_UPD,
4576 ARM::VST1q32HighQPseudo_UPD,
4577 ARM::VST1q64HighQPseudo_UPD };
4578 SelectVST(
N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
4584 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
4585 ARM::VST2LNd16Pseudo_UPD,
4586 ARM::VST2LNd32Pseudo_UPD };
4587 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
4588 ARM::VST2LNq32Pseudo_UPD };
4589 SelectVLDSTLane(
N,
false,
true, 2, DOpcodes, QOpcodes);
4594 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
4595 ARM::VST3LNd16Pseudo_UPD,
4596 ARM::VST3LNd32Pseudo_UPD };
4597 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
4598 ARM::VST3LNq32Pseudo_UPD };
4599 SelectVLDSTLane(
N,
false,
true, 3, DOpcodes, QOpcodes);
4604 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
4605 ARM::VST4LNd16Pseudo_UPD,
4606 ARM::VST4LNd32Pseudo_UPD };
4607 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
4608 ARM::VST4LNq32Pseudo_UPD };
4609 SelectVLDSTLane(
N,
false,
true, 4, DOpcodes, QOpcodes);
4615 unsigned IntNo =
N->getConstantOperandVal(1);
4620 case Intrinsic::arm_mrrc:
4621 case Intrinsic::arm_mrrc2: {
4626 if (Subtarget->isThumb())
4627 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
4629 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
4632 Ops.push_back(getI32Imm(
N->getConstantOperandVal(2), dl));
4633 Ops.push_back(getI32Imm(
N->getConstantOperandVal(3), dl));
4634 Ops.push_back(getI32Imm(
N->getConstantOperandVal(4), dl));
4639 if (
Opc != ARM::MRRC2) {
4641 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4644 Ops.push_back(Chain);
4647 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
4649 ReplaceNode(
N, CurDAG->getMachineNode(
Opc, dl, RetType,
Ops));
4652 case Intrinsic::arm_ldaexd:
4653 case Intrinsic::arm_ldrexd: {
4657 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
4659 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
4660 unsigned NewOpc =
isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
4661 : (IsAcquire ?
ARM::LDAEXD :
ARM::LDREXD);
4664 std::vector<EVT> ResTys;
4666 ResTys.push_back(MVT::i32);
4667 ResTys.push_back(MVT::i32);
4669 ResTys.push_back(MVT::Untyped);
4670 ResTys.push_back(MVT::Other);
4674 CurDAG->getRegister(0, MVT::i32), Chain};
4675 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4688 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
4689 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4690 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4693 ReplaceUses(
SDValue(
N, 0), Result);
4701 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
4702 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
4703 dl, MVT::i32,
SDValue(Ld, 0), SubRegIdx);
4706 ReplaceUses(
SDValue(
N, 1), Result);
4708 ReplaceUses(
SDValue(
N, 2), OutChain);
4709 CurDAG->RemoveDeadNode(
N);
4712 case Intrinsic::arm_stlexd:
4713 case Intrinsic::arm_strexd: {
4722 const EVT ResTys[] = {MVT::i32, MVT::Other};
4724 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
4728 Ops.push_back(Val0);
4729 Ops.push_back(Val1);
4733 Ops.push_back(MemAddr);
4735 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4736 Ops.push_back(Chain);
4738 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
4739 unsigned NewOpc =
isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
4740 : (IsRelease ?
ARM::STLEXD :
ARM::STREXD);
4742 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys,
Ops);
4751 case Intrinsic::arm_neon_vld1: {
4752 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
4753 ARM::VLD1d32, ARM::VLD1d64 };
4754 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4755 ARM::VLD1q32, ARM::VLD1q64};
4756 SelectVLD(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4760 case Intrinsic::arm_neon_vld1x2: {
4761 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
4762 ARM::VLD1q32, ARM::VLD1q64 };
4763 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
4764 ARM::VLD1d16QPseudo,
4765 ARM::VLD1d32QPseudo,
4766 ARM::VLD1d64QPseudo };
4767 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4771 case Intrinsic::arm_neon_vld1x3: {
4772 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
4773 ARM::VLD1d16TPseudo,
4774 ARM::VLD1d32TPseudo,
4775 ARM::VLD1d64TPseudo };
4776 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
4777 ARM::VLD1q16LowTPseudo_UPD,
4778 ARM::VLD1q32LowTPseudo_UPD,
4779 ARM::VLD1q64LowTPseudo_UPD };
4780 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
4781 ARM::VLD1q16HighTPseudo,
4782 ARM::VLD1q32HighTPseudo,
4783 ARM::VLD1q64HighTPseudo };
4784 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4788 case Intrinsic::arm_neon_vld1x4: {
4789 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
4790 ARM::VLD1d16QPseudo,
4791 ARM::VLD1d32QPseudo,
4792 ARM::VLD1d64QPseudo };
4793 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
4794 ARM::VLD1q16LowQPseudo_UPD,
4795 ARM::VLD1q32LowQPseudo_UPD,
4796 ARM::VLD1q64LowQPseudo_UPD };
4797 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
4798 ARM::VLD1q16HighQPseudo,
4799 ARM::VLD1q32HighQPseudo,
4800 ARM::VLD1q64HighQPseudo };
4801 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4805 case Intrinsic::arm_neon_vld2: {
4806 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
4807 ARM::VLD2d32, ARM::VLD1q64 };
4808 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
4809 ARM::VLD2q32Pseudo };
4810 SelectVLD(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4814 case Intrinsic::arm_neon_vld3: {
4815 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
4818 ARM::VLD1d64TPseudo };
4819 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
4820 ARM::VLD3q16Pseudo_UPD,
4821 ARM::VLD3q32Pseudo_UPD };
4822 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
4823 ARM::VLD3q16oddPseudo,
4824 ARM::VLD3q32oddPseudo };
4825 SelectVLD(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4829 case Intrinsic::arm_neon_vld4: {
4830 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
4833 ARM::VLD1d64QPseudo };
4834 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
4835 ARM::VLD4q16Pseudo_UPD,
4836 ARM::VLD4q32Pseudo_UPD };
4837 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
4838 ARM::VLD4q16oddPseudo,
4839 ARM::VLD4q32oddPseudo };
4840 SelectVLD(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4844 case Intrinsic::arm_neon_vld2dup: {
4845 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
4846 ARM::VLD2DUPd32, ARM::VLD1q64 };
4847 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
4848 ARM::VLD2DUPq16EvenPseudo,
4849 ARM::VLD2DUPq32EvenPseudo };
4850 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo,
4851 ARM::VLD2DUPq16OddPseudo,
4852 ARM::VLD2DUPq32OddPseudo };
4853 SelectVLDDup(
N,
true,
false, 2,
4854 DOpcodes, QOpcodes0, QOpcodes1);
4858 case Intrinsic::arm_neon_vld3dup: {
4859 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo,
4860 ARM::VLD3DUPd16Pseudo,
4861 ARM::VLD3DUPd32Pseudo,
4862 ARM::VLD1d64TPseudo };
4863 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
4864 ARM::VLD3DUPq16EvenPseudo,
4865 ARM::VLD3DUPq32EvenPseudo };
4866 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo,
4867 ARM::VLD3DUPq16OddPseudo,
4868 ARM::VLD3DUPq32OddPseudo };
4869 SelectVLDDup(
N,
true,
false, 3,
4870 DOpcodes, QOpcodes0, QOpcodes1);
4874 case Intrinsic::arm_neon_vld4dup: {
4875 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo,
4876 ARM::VLD4DUPd16Pseudo,
4877 ARM::VLD4DUPd32Pseudo,
4878 ARM::VLD1d64QPseudo };
4879 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
4880 ARM::VLD4DUPq16EvenPseudo,
4881 ARM::VLD4DUPq32EvenPseudo };
4882 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo,
4883 ARM::VLD4DUPq16OddPseudo,
4884 ARM::VLD4DUPq32OddPseudo };
4885 SelectVLDDup(
N,
true,
false, 4,
4886 DOpcodes, QOpcodes0, QOpcodes1);
4890 case Intrinsic::arm_neon_vld2lane: {
4891 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
4892 ARM::VLD2LNd16Pseudo,
4893 ARM::VLD2LNd32Pseudo };
4894 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
4895 ARM::VLD2LNq32Pseudo };
4896 SelectVLDSTLane(
N,
true,
false, 2, DOpcodes, QOpcodes);
4900 case Intrinsic::arm_neon_vld3lane: {
4901 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
4902 ARM::VLD3LNd16Pseudo,
4903 ARM::VLD3LNd32Pseudo };
4904 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
4905 ARM::VLD3LNq32Pseudo };
4906 SelectVLDSTLane(
N,
true,
false, 3, DOpcodes, QOpcodes);
4910 case Intrinsic::arm_neon_vld4lane: {
4911 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
4912 ARM::VLD4LNd16Pseudo,
4913 ARM::VLD4LNd32Pseudo };
4914 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
4915 ARM::VLD4LNq32Pseudo };
4916 SelectVLDSTLane(
N,
true,
false, 4, DOpcodes, QOpcodes);
4920 case Intrinsic::arm_neon_vst1: {
4921 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
4922 ARM::VST1d32, ARM::VST1d64 };
4923 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
4924 ARM::VST1q32, ARM::VST1q64 };
4925 SelectVST(
N,
false, 1, DOpcodes, QOpcodes,
nullptr);
4929 case Intrinsic::arm_neon_vst1x2: {
4930 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
4931 ARM::VST1q32, ARM::VST1q64 };
4932 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
4933 ARM::VST1d16QPseudo,
4934 ARM::VST1d32QPseudo,
4935 ARM::VST1d64QPseudo };
4936 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4940 case Intrinsic::arm_neon_vst1x3: {
4941 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
4942 ARM::VST1d16TPseudo,
4943 ARM::VST1d32TPseudo,
4944 ARM::VST1d64TPseudo };
4945 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
4946 ARM::VST1q16LowTPseudo_UPD,
4947 ARM::VST1q32LowTPseudo_UPD,
4948 ARM::VST1q64LowTPseudo_UPD };
4949 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
4950 ARM::VST1q16HighTPseudo,
4951 ARM::VST1q32HighTPseudo,
4952 ARM::VST1q64HighTPseudo };
4953 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4957 case Intrinsic::arm_neon_vst1x4: {
4958 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
4959 ARM::VST1d16QPseudo,
4960 ARM::VST1d32QPseudo,
4961 ARM::VST1d64QPseudo };
4962 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
4963 ARM::VST1q16LowQPseudo_UPD,
4964 ARM::VST1q32LowQPseudo_UPD,
4965 ARM::VST1q64LowQPseudo_UPD };
4966 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
4967 ARM::VST1q16HighQPseudo,
4968 ARM::VST1q32HighQPseudo,
4969 ARM::VST1q64HighQPseudo };
4970 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
4974 case Intrinsic::arm_neon_vst2: {
4975 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
4976 ARM::VST2d32, ARM::VST1q64 };
4977 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
4978 ARM::VST2q32Pseudo };
4979 SelectVST(
N,
false, 2, DOpcodes, QOpcodes,
nullptr);
4983 case Intrinsic::arm_neon_vst3: {
4984 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
4987 ARM::VST1d64TPseudo };
4988 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
4989 ARM::VST3q16Pseudo_UPD,
4990 ARM::VST3q32Pseudo_UPD };
4991 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
4992 ARM::VST3q16oddPseudo,
4993 ARM::VST3q32oddPseudo };
4994 SelectVST(
N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
4998 case Intrinsic::arm_neon_vst4: {
4999 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
5002 ARM::VST1d64QPseudo };
5003 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
5004 ARM::VST4q16Pseudo_UPD,
5005 ARM::VST4q32Pseudo_UPD };
5006 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
5007 ARM::VST4q16oddPseudo,
5008 ARM::VST4q32oddPseudo };
5009 SelectVST(
N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
5013 case Intrinsic::arm_neon_vst2lane: {
5014 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
5015 ARM::VST2LNd16Pseudo,
5016 ARM::VST2LNd32Pseudo };
5017 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
5018 ARM::VST2LNq32Pseudo };
5019 SelectVLDSTLane(
N,
false,
false, 2, DOpcodes, QOpcodes);
5023 case Intrinsic::arm_neon_vst3lane: {
5024 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
5025 ARM::VST3LNd16Pseudo,
5026 ARM::VST3LNd32Pseudo };
5027 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
5028 ARM::VST3LNq32Pseudo };
5029 SelectVLDSTLane(
N,
false,
false, 3, DOpcodes, QOpcodes);
5033 case Intrinsic::arm_neon_vst4lane: {
5034 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
5035 ARM::VST4LNd16Pseudo,
5036 ARM::VST4LNd32Pseudo };
5037 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
5038 ARM::VST4LNq32Pseudo };
5039 SelectVLDSTLane(
N,
false,
false, 4, DOpcodes, QOpcodes);
5043 case Intrinsic::arm_mve_vldr_gather_base_wb:
5044 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
5045 static const uint16_t Opcodes[] = {ARM::MVE_VLDRWU32_qi_pre,
5046 ARM::MVE_VLDRDU64_qi_pre};
5047 SelectMVE_WB(
N, Opcodes,
5048 IntNo == Intrinsic::arm_mve_vldr_gather_base_wb_predicated);
5052 case Intrinsic::arm_mve_vld2q: {
5053 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, ARM::MVE_VLD21_8};
5054 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16,
5056 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32,
5058 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5059 SelectMVE_VLD(
N, 2, Opcodes,
false);
5063 case Intrinsic::arm_mve_vld4q: {
5064 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8,
5065 ARM::MVE_VLD42_8, ARM::MVE_VLD43_8};
5066 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16,
5069 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32,
5072 static const uint16_t *
const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32};
5073 SelectMVE_VLD(
N, 4, Opcodes,
false);
5081 unsigned IntNo =
N->getConstantOperandVal(0);
5087 case Intrinsic::arm_neon_vcvtbfp2bf: {
5089 const SDValue &Src =
N->getOperand(1);
5090 llvm::EVT DestTy =
N->getValueType(0);
5092 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5094 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVTB, DestTy,
Ops);
5099 case Intrinsic::arm_neon_vcvtfp2bf: {
5101 const SDValue &Src =
N->getOperand(1);
5103 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
5105 CurDAG->SelectNodeTo(
N, ARM::BF16_VCVT, MVT::v4bf16,
Ops);
5109 case Intrinsic::arm_mve_urshrl:
5110 SelectMVE_LongShift(
N, ARM::MVE_URSHRL,
true,
false);
5112 case Intrinsic::arm_mve_uqshll:
5113 SelectMVE_LongShift(
N, ARM::MVE_UQSHLL,
true,
false);
5115 case Intrinsic::arm_mve_srshrl:
5116 SelectMVE_LongShift(
N, ARM::MVE_SRSHRL,
true,
false);
5118 case Intrinsic::arm_mve_sqshll:
5119 SelectMVE_LongShift(
N, ARM::MVE_SQSHLL,
true,
false);
5121 case Intrinsic::arm_mve_uqrshll:
5122 SelectMVE_LongShift(
N, ARM::MVE_UQRSHLL,
false,
true);
5124 case Intrinsic::arm_mve_sqrshrl:
5125 SelectMVE_LongShift(
N, ARM::MVE_SQRSHRL,
false,
true);
5128 case Intrinsic::arm_mve_vadc:
5129 case Intrinsic::arm_mve_vadc_predicated:
5130 SelectMVE_VADCSBC(
N, ARM::MVE_VADC, ARM::MVE_VADCI,
true,
5131 IntNo == Intrinsic::arm_mve_vadc_predicated);
5133 case Intrinsic::arm_mve_vsbc:
5134 case Intrinsic::arm_mve_vsbc_predicated:
5135 SelectMVE_VADCSBC(
N, ARM::MVE_VSBC, ARM::MVE_VSBCI,
false,
5136 IntNo == Intrinsic::arm_mve_vsbc_predicated);
5138 case Intrinsic::arm_mve_vshlc:
5139 case Intrinsic::arm_mve_vshlc_predicated:
5140 SelectMVE_VSHLC(
N, IntNo == Intrinsic::arm_mve_vshlc_predicated);
5143 case Intrinsic::arm_mve_vmlldava:
5144 case Intrinsic::arm_mve_vmlldava_predicated: {
5145 static const uint16_t OpcodesU[] = {
5146 ARM::MVE_VMLALDAVu16, ARM::MVE_VMLALDAVu32,
5147 ARM::MVE_VMLALDAVau16, ARM::MVE_VMLALDAVau32,
5149 static const uint16_t OpcodesS[] = {
5150 ARM::MVE_VMLALDAVs16, ARM::MVE_VMLALDAVs32,
5151 ARM::MVE_VMLALDAVas16, ARM::MVE_VMLALDAVas32,
5152 ARM::MVE_VMLALDAVxs16, ARM::MVE_VMLALDAVxs32,
5153 ARM::MVE_VMLALDAVaxs16, ARM::MVE_VMLALDAVaxs32,
5154 ARM::MVE_VMLSLDAVs16, ARM::MVE_VMLSLDAVs32,
5155 ARM::MVE_VMLSLDAVas16, ARM::MVE_VMLSLDAVas32,
5156 ARM::MVE_VMLSLDAVxs16, ARM::MVE_VMLSLDAVxs32,
5157 ARM::MVE_VMLSLDAVaxs16, ARM::MVE_VMLSLDAVaxs32,
5159 SelectMVE_VMLLDAV(
N, IntNo == Intrinsic::arm_mve_vmlldava_predicated,
5160 OpcodesS, OpcodesU);
5164 case Intrinsic::arm_mve_vrmlldavha:
5165 case Intrinsic::arm_mve_vrmlldavha_predicated: {
5166 static const uint16_t OpcodesU[] = {
5167 ARM::MVE_VRMLALDAVHu32, ARM::MVE_VRMLALDAVHau32,
5169 static const uint16_t OpcodesS[] = {
5170 ARM::MVE_VRMLALDAVHs32, ARM::MVE_VRMLALDAVHas32,
5171 ARM::MVE_VRMLALDAVHxs32, ARM::MVE_VRMLALDAVHaxs32,
5172 ARM::MVE_VRMLSLDAVHs32, ARM::MVE_VRMLSLDAVHas32,
5173 ARM::MVE_VRMLSLDAVHxs32, ARM::MVE_VRMLSLDAVHaxs32,
5175 SelectMVE_VRMLLDAVH(
N, IntNo == Intrinsic::arm_mve_vrmlldavha_predicated,
5176 OpcodesS, OpcodesU);
5180 case Intrinsic::arm_mve_vidup:
5181 case Intrinsic::arm_mve_vidup_predicated: {
5182 static const uint16_t Opcodes[] = {
5183 ARM::MVE_VIDUPu8, ARM::MVE_VIDUPu16, ARM::MVE_VIDUPu32,
5185 SelectMVE_VxDUP(
N, Opcodes,
false,
5186 IntNo == Intrinsic::arm_mve_vidup_predicated);
5190 case Intrinsic::arm_mve_vddup:
5191 case Intrinsic::arm_mve_vddup_predicated: {
5192 static const uint16_t Opcodes[] = {
5193 ARM::MVE_VDDUPu8, ARM::MVE_VDDUPu16, ARM::MVE_VDDUPu32,
5195 SelectMVE_VxDUP(
N, Opcodes,
false,
5196 IntNo == Intrinsic::arm_mve_vddup_predicated);
5200 case Intrinsic::arm_mve_viwdup:
5201 case Intrinsic::arm_mve_viwdup_predicated: {
5202 static const uint16_t Opcodes[] = {
5203 ARM::MVE_VIWDUPu8, ARM::MVE_VIWDUPu16, ARM::MVE_VIWDUPu32,
5205 SelectMVE_VxDUP(
N, Opcodes,
true,
5206 IntNo == Intrinsic::arm_mve_viwdup_predicated);
5210 case Intrinsic::arm_mve_vdwdup:
5211 case Intrinsic::arm_mve_vdwdup_predicated: {
5212 static const uint16_t Opcodes[] = {
5213 ARM::MVE_VDWDUPu8, ARM::MVE_VDWDUPu16, ARM::MVE_VDWDUPu32,
5215 SelectMVE_VxDUP(
N, Opcodes,
true,
5216 IntNo == Intrinsic::arm_mve_vdwdup_predicated);
5220 case Intrinsic::arm_cde_cx1d:
5221 case Intrinsic::arm_cde_cx1da:
5222 case Intrinsic::arm_cde_cx2d:
5223 case Intrinsic::arm_cde_cx2da:
5224 case Intrinsic::arm_cde_cx3d:
5225 case Intrinsic::arm_cde_cx3da: {
5226 bool HasAccum = IntNo == Intrinsic::arm_cde_cx1da ||
5227 IntNo == Intrinsic::arm_cde_cx2da ||
5228 IntNo == Intrinsic::arm_cde_cx3da;
5232 case Intrinsic::arm_cde_cx1d:
5233 case Intrinsic::arm_cde_cx1da:
5235 Opcode = HasAccum ? ARM::CDE_CX1DA : ARM::CDE_CX1D;
5237 case Intrinsic::arm_cde_cx2d:
5238 case Intrinsic::arm_cde_cx2da:
5240 Opcode = HasAccum ? ARM::CDE_CX2DA : ARM::CDE_CX2D;
5242 case Intrinsic::arm_cde_cx3d:
5243 case Intrinsic::arm_cde_cx3da:
5245 Opcode = HasAccum ? ARM::CDE_CX3DA : ARM::CDE_CX3D;
5250 SelectCDE_CXxD(
N, Opcode, NumExtraOps, HasAccum);
5257 case ISD::ATOMIC_CMP_SWAP:
5273 std::vector<SDValue> &
Ops) {
5275 RegString.
split(Fields,
':');
5277 if (Fields.
size() > 1) {
5278 bool AllIntFields =
true;
5283 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
5288 "Unexpected non-integer value in special register string.");
5299 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.
lower());
5302 return TheReg->Encoding;
5314 .
Case(
"nzcvqg", 0x3)
5322 auto TheReg = ARMSysReg::lookupMClassSysRegByName(
Reg);
5323 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
5324 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
5326 return (
int)(TheReg->Encoding & 0xFFF);
5335 if (
Reg ==
"apsr") {
5345 if (
Reg !=
"cpsr" &&
Reg !=
"spsr") {
5350 if (Flags.empty() || Flags ==
"all")
5355 for (
char Flag : Flags) {
5375 if (!FlagVal || (Mask & FlagVal))
5390bool ARMDAGToDAGISel::tryReadRegister(SDNode *
N){
5392 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5393 bool IsThumb2 = Subtarget->
isThumb2();
5396 std::vector<SDValue>
Ops;
5406 if (
Ops.size() == 5){
5407 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
5408 ResTypes.
append({ MVT::i32, MVT::Other });
5411 "Invalid number of fields in special register string.");
5412 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
5413 ResTypes.
append({ MVT::i32, MVT::i32, MVT::Other });
5417 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5418 Ops.push_back(
N->getOperand(0));
5419 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, ResTypes,
Ops));
5423 std::string SpecialReg = RegString->getString().lower();
5426 if (BankedReg != -1) {
5427 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
5428 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5431 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
5432 DL, MVT::i32, MVT::Other,
Ops));
5439 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5440 .Case(
"fpscr", ARM::VMRS)
5441 .Case(
"fpexc", ARM::VMRS_FPEXC)
5442 .Case(
"fpsid", ARM::VMRS_FPSID)
5443 .Case(
"mvfr0", ARM::VMRS_MVFR0)
5444 .Case(
"mvfr1", ARM::VMRS_MVFR1)
5445 .Case(
"mvfr2", ARM::VMRS_MVFR2)
5446 .Case(
"fpinst", ARM::VMRS_FPINST)
5447 .Case(
"fpinst2", ARM::VMRS_FPINST2)
5457 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5460 CurDAG->getMachineNode(Opcode,
DL, MVT::i32, MVT::Other,
Ops));
5469 if (SYSmValue == -1)
5472 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5473 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5476 N, CurDAG->getMachineNode(ARM::t2MRS_M,
DL, MVT::i32, MVT::Other,
Ops));
5482 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
5483 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5485 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
5486 DL, MVT::i32, MVT::Other,
Ops));
5490 if (SpecialReg ==
"spsr") {
5491 Ops = {
getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5494 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
DL,
5495 MVT::i32, MVT::Other,
Ops));
5505bool ARMDAGToDAGISel::tryWriteRegister(SDNode *
N){
5507 const auto *RegString =
cast<MDString>(MD->getMD()->getOperand(0));
5508 bool IsThumb2 = Subtarget->
isThumb2();
5511 std::vector<SDValue>
Ops;
5520 if (
Ops.size() == 5) {
5521 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
5522 Ops.insert(
Ops.begin()+2,
N->getOperand(2));
5525 "Invalid number of fields in special register string.");
5526 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
5527 SDValue WriteValue[] = {
N->getOperand(2),
N->getOperand(3) };
5528 Ops.insert(
Ops.begin()+2, WriteValue, WriteValue+2);
5532 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
5533 Ops.push_back(
N->getOperand(0));
5535 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5539 std::string SpecialReg = RegString->getString().lower();
5541 if (BankedReg != -1) {
5542 Ops = { CurDAG->getTargetConstant(BankedReg,
DL, MVT::i32),
N->getOperand(2),
5543 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5546 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
5547 DL, MVT::Other,
Ops));
5554 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
5555 .Case(
"fpscr", ARM::VMSR)
5556 .Case(
"fpexc", ARM::VMSR_FPEXC)
5557 .Case(
"fpsid", ARM::VMSR_FPSID)
5558 .Case(
"fpinst", ARM::VMSR_FPINST)
5559 .Case(
"fpinst2", ARM::VMSR_FPINST2)
5566 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5567 ReplaceNode(
N, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
5571 std::pair<StringRef, StringRef> Fields;
5572 Fields = StringRef(SpecialReg).rsplit(
'_');
5573 std::string
Reg = Fields.first.str();
5574 StringRef
Flags = Fields.second;
5580 if (SYSmValue == -1)
5583 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue,
DL, MVT::i32),
5584 N->getOperand(2),
getAL(CurDAG,
DL),
5585 CurDAG->getRegister(0, MVT::i32),
N->
getOperand(0) };
5586 ReplaceNode(
N, CurDAG->getMachineNode(ARM::t2MSR_M,
DL, MVT::Other,
Ops));
5595 Ops = { CurDAG->getTargetConstant(Mask,
DL, MVT::i32),
N->getOperand(2),
5596 getAL(CurDAG,
DL), CurDAG->getRegister(0, MVT::i32),
5598 ReplaceNode(
N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
5599 DL, MVT::Other,
Ops));
5606bool ARMDAGToDAGISel::tryInlineAsm(SDNode *
N){
5607 std::vector<SDValue> AsmNodeOperands;
5608 InlineAsm::Flag
Flag;
5610 unsigned NumOps =
N->getNumOperands();
5625 for(
unsigned i = 0, e =
N->getGluedNode() ?
NumOps - 1 :
NumOps; i < e; ++i) {
5627 AsmNodeOperands.push_back(
op);
5633 Flag = InlineAsm::Flag(
C->getZExtValue());
5641 if (
Flag.isImmKind()) {
5643 AsmNodeOperands.push_back(
op);
5647 const unsigned NumRegs =
Flag.getNumOperandRegisters();
5651 unsigned DefIdx = 0;
5652 bool IsTiedToChangedOp =
false;
5655 if (
Changed &&
Flag.isUseOperandTiedToDef(DefIdx))
5656 IsTiedToChangedOp = OpChanged[DefIdx];
5663 if (
Flag.isMemKind()) {
5665 AsmNodeOperands.push_back(
op);
5669 if (!
Flag.isRegUseKind() && !
Flag.isRegDefKind() &&
5670 !
Flag.isRegDefEarlyClobberKind())
5674 const bool HasRC =
Flag.hasRegClassConstraint(RC);
5675 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
5679 assert((i+2 <
NumOps) &&
"Invalid number of operands in inline asm");
5687 if (
Flag.isRegDefKind() ||
Flag.isRegDefEarlyClobberKind()) {
5691 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5692 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5695 SDNode *GU =
N->getGluedUser();
5696 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
5700 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
5702 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
5704 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
5710 Ops.push_back(
T1.getValue(1));
5711 CurDAG->UpdateNodeOperands(GU,
Ops);
5718 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
5720 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
5726 Register GPVR =
MRI.createVirtualRegister(&ARM::GPRPairRegClass);
5727 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
5728 Chain = CurDAG->getCopyToReg(
T1, dl, GPVR, Pair,
T1.getValue(1));
5737 OpChanged[OpChanged.
size() -1 ] =
true;
5738 Flag = InlineAsm::Flag(
Flag.getKind(), 1 );
5739 if (IsTiedToChangedOp)
5740 Flag.setMatchingOp(DefIdx);
5742 Flag.setRegClass(ARM::GPRPairRegClassID);
5744 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
5745 Flag, dl, MVT::i32);
5747 AsmNodeOperands.push_back(PairedReg);
5754 AsmNodeOperands.push_back(Glue);
5758 SDValue New = CurDAG->getNode(
N->getOpcode(), SDLoc(
N),
5759 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
5761 ReplaceNode(
N,
New.getNode());
5765bool ARMDAGToDAGISel::SelectInlineAsmMemoryOperand(
5767 std::vector<SDValue> &OutOps) {
5768 switch(ConstraintID) {
5771 case InlineAsm::ConstraintCode::m:
5772 case InlineAsm::ConstraintCode::o:
5773 case InlineAsm::ConstraintCode::Q:
5774 case InlineAsm::ConstraintCode::Um:
5775 case InlineAsm::ConstraintCode::Un:
5776 case InlineAsm::ConstraintCode::Uq:
5777 case InlineAsm::ConstraintCode::Us:
5778 case InlineAsm::ConstraintCode::Ut:
5779 case InlineAsm::ConstraintCode::Uv:
5780 case InlineAsm::ConstraintCode::Uy:
5784 OutOps.push_back(
Op);
5795 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.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.