40 #define DEBUG_TYPE "arm-isel"
44 cl::desc(
"Disable isel of shifter-op"),
49 cl::desc(
"Check fp vmla / vmls hazard at isel time"),
79 const char *getPassName()
const override {
80 return "ARM Instruction Selection";
83 void PreprocessISelDAG()
override;
88 return CurDAG->getTargetConstant(Imm, dl,
MVT::i32);
94 bool hasNoVMLxHazardUse(
SDNode *
N)
const;
95 bool isShifterOpProfitable(
const SDValue &Shift,
99 bool CheckProfitability =
true);
101 SDValue &B,
bool CheckProfitability =
true);
105 return SelectRegShifterOperand(N, A, B, C,
false);
110 return SelectImmShifterOperand(N, A, B,
false);
120 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
125 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
130 SelectAddrMode2Worker(N, Base, Offset, Opc);
139 Reg = CurDAG->getRegister(ARM::CPSR,
MVT::i32);
168 bool SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
SDValue &Base,
179 bool SelectT2ShifterOperandReg(
SDValue N,
190 inline bool is_so_imm(
unsigned Imm)
const {
194 inline bool is_so_imm_not(
unsigned Imm)
const {
198 inline bool is_t2_so_imm(
unsigned Imm)
const {
202 inline bool is_t2_so_imm_not(
unsigned Imm)
const {
207 #include "ARMGenDAGISel.inc"
219 SDNode *SelectVLD(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
220 const uint16_t *DOpcodes,
221 const uint16_t *QOpcodes0,
const uint16_t *QOpcodes1);
227 SDNode *SelectVST(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
228 const uint16_t *DOpcodes,
229 const uint16_t *QOpcodes0,
const uint16_t *QOpcodes1);
235 bool isUpdating,
unsigned NumVecs,
236 const uint16_t *DOpcodes,
const uint16_t *QOpcodes);
241 SDNode *SelectVLDDup(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
242 const uint16_t *Opcodes);
247 SDNode *SelectVTBL(
SDNode *N,
bool IsExt,
unsigned NumVecs,
unsigned Opc);
250 SDNode *SelectV6T2BitfieldExtractOp(
SDNode *N,
bool isSigned);
264 bool SelectInlineAsmMemoryOperand(
const SDValue &Op,
unsigned ConstraintID,
265 std::vector<SDValue> &OutOps)
override;
288 Imm = cast<ConstantSDNode>(
N)->getZExtValue();
313 int RangeMin,
int RangeMax,
314 int &ScaledConstant) {
315 assert(Scale > 0 &&
"Invalid scale!");
323 if ((ScaledConstant % Scale) != 0)
326 ScaledConstant /= Scale;
327 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
330 void ARMDAGToDAGISel::PreprocessISelDAG() {
331 if (!Subtarget->hasV6T2Ops())
334 bool isThumb2 = Subtarget->isThumb();
336 E = CurDAG->allnodes_end();
I != E; ) {
353 unsigned And_imm = 0;
363 if (TZ != 1 && TZ != 2)
375 if (And_imm & (And_imm + 1))
380 unsigned Srl_imm = 0;
391 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
394 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
395 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
402 CurDAG->getConstant(Srl_imm + TZ,
SDLoc(Srl),
409 CurDAG->UpdateNodeOperands(N, N0, N1);
416 bool ARMDAGToDAGISel::hasNoVMLxHazardUse(
SDNode *N)
const {
423 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
424 !Subtarget->isCortexA9() && !Subtarget->isSwift())
435 CurDAG->getSubtarget().getInstrInfo());
462 bool ARMDAGToDAGISel::isShifterOpProfitable(
const SDValue &Shift,
465 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
471 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
474 bool ARMDAGToDAGISel::SelectImmShifterOperand(
SDValue N,
477 bool CheckProfitability) {
488 unsigned ShImmVal = 0;
490 if (!RHS)
return false;
497 bool ARMDAGToDAGISel::SelectRegShifterOperand(
SDValue N,
501 bool CheckProfitability) {
512 unsigned ShImmVal = 0;
514 if (RHS)
return false;
517 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
525 bool ARMDAGToDAGISel::SelectAddrModeImm12(
SDValue N,
532 !CurDAG->isBaseWithConstantOffset(N)) {
535 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
536 Base = CurDAG->getTargetFrameIndex(
537 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
556 if (RHSC > -0x1000 && RHSC < 0x1000) {
559 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
560 Base = CurDAG->getTargetFrameIndex(
561 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
563 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
579 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.
hasOneUse())) {
591 unsigned ShAmt =
Log2_32(RHSC);
604 !CurDAG->isBaseWithConstantOffset(N))
611 -0x1000+1, 0x1000, RHSC))
629 ShAmt = Sh->getZExtValue();
630 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
643 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
651 ShAmt = Sh->getZExtValue();
652 if (isShifterOpProfitable(N.
getOperand(0), ShOpcVal, ShAmt)) {
678 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.
hasOneUse())) {
690 unsigned ShAmt =
Log2_32(RHSC);
703 !CurDAG->isBaseWithConstantOffset(N)) {
706 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
707 Base = CurDAG->getTargetFrameIndex(
708 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
713 Offset = CurDAG->getRegister(0,
MVT::i32);
724 -0x1000+1, 0x1000, RHSC)) {
727 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
728 Base = CurDAG->getTargetFrameIndex(
729 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
731 Offset = CurDAG->getRegister(0,
MVT::i32);
745 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.
hasOneUse()) {
748 Offset = CurDAG->getRegister(0,
MVT::i32);
769 ShAmt = Sh->getZExtValue();
770 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
783 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
791 ShAmt = Sh->getZExtValue();
792 if (isShifterOpProfitable(N.
getOperand(0), ShOpcVal, ShAmt)) {
810 bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(
SDNode *Op,
SDValue N,
814 ? cast<LoadSDNode>(Op)->getAddressingMode()
815 : cast<StoreSDNode>(Op)->getAddressingMode();
829 ShAmt = Sh->getZExtValue();
830 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
846 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(
SDNode *Op,
SDValue N,
850 ? cast<LoadSDNode>(Op)->getAddressingMode()
851 : cast<StoreSDNode>(Op)->getAddressingMode();
857 Offset = CurDAG->getRegister(0,
MVT::i32);
866 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(
SDNode *Op,
SDValue N,
870 ? cast<LoadSDNode>(Op)->getAddressingMode()
871 : cast<StoreSDNode>(Op)->getAddressingMode();
876 Offset = CurDAG->getRegister(0,
MVT::i32);
886 bool ARMDAGToDAGISel::SelectAddrOffsetNone(
SDValue N,
SDValue &Base) {
891 bool ARMDAGToDAGISel::SelectAddrMode3(
SDValue N,
903 if (!CurDAG->isBaseWithConstantOffset(N)) {
906 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
907 Base = CurDAG->getTargetFrameIndex(
908 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
910 Offset = CurDAG->getRegister(0,
MVT::i32);
919 -256 + 1, 256, RHSC)) {
922 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
923 Base = CurDAG->getTargetFrameIndex(
924 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
926 Offset = CurDAG->getRegister(0,
MVT::i32);
945 bool ARMDAGToDAGISel::SelectAddrMode3Offset(
SDNode *Op,
SDValue N,
949 ? cast<LoadSDNode>(Op)->getAddressingMode()
950 : cast<StoreSDNode>(Op)->getAddressingMode();
955 Offset = CurDAG->getRegister(0,
MVT::i32);
967 bool ARMDAGToDAGISel::SelectAddrMode5(
SDValue N,
969 if (!CurDAG->isBaseWithConstantOffset(N)) {
972 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
973 Base = CurDAG->getTargetFrameIndex(
974 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
987 -256 + 1, 256, RHSC)) {
990 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
991 Base = CurDAG->getTargetFrameIndex(
992 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1015 unsigned Alignment = 0;
1017 MemSDNode *MemN = cast<MemSDNode>(Parent);
1019 if (isa<LSBaseSDNode>(MemN) ||
1027 if (MMOAlign >= MemSize && MemSize > 1)
1028 Alignment = MemSize;
1036 Align = CurDAG->getTargetConstant(Alignment,
SDLoc(N),
MVT::i32);
1040 bool ARMDAGToDAGISel::SelectAddrMode6Offset(
SDNode *Op,
SDValue N,
1049 Offset = CurDAG->getRegister(0,
MVT::i32);
1054 bool ARMDAGToDAGISel::SelectAddrModePC(
SDValue N,
1059 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1072 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(
SDValue N,
1090 SDValue &Offset,
unsigned Scale) {
1093 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1101 if (!CurDAG->isBaseWithConstantOffset(N))
1107 if ((LHSR && LHSR->
getReg() == ARM::SP) ||
1108 (RHSR && RHSR->getReg() == ARM::SP))
1124 ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(
SDValue N,
1127 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1131 ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(
SDValue N,
1134 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1138 ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(
SDValue N,
1141 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1145 ARMDAGToDAGISel::SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
1149 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1157 if (!CurDAG->isBaseWithConstantOffset(N)) {
1171 if ((LHSR && LHSR->
getReg() == ARM::SP) ||
1172 (RHSR && RHSR->getReg() == ARM::SP)) {
1176 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1179 if (LHSC != 0 || RHSC != 0)
return false;
1190 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1200 ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(
SDValue N,
SDValue &Base,
1202 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
1206 ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(
SDValue N,
SDValue &Base,
1208 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
1212 ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(
SDValue N,
SDValue &Base,
1214 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
1217 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(
SDValue N,
1220 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1226 Base = CurDAG->getTargetFrameIndex(
1227 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1232 if (!CurDAG->isBaseWithConstantOffset(N))
1237 (LHSR && LHSR->
getReg() == ARM::SP)) {
1243 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1249 Base = CurDAG->getTargetFrameIndex(
1250 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1252 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1266 bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(
SDValue N,
SDValue &BaseReg,
1278 unsigned ShImmVal = 0;
1280 ShImmVal = RHS->getZExtValue() & 31;
1288 bool ARMDAGToDAGISel::SelectT2AddrModeImm12(
SDValue N,
1294 !CurDAG->isBaseWithConstantOffset(N)) {
1297 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1298 Base = CurDAG->getTargetFrameIndex(
1299 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1316 if (SelectT2AddrModeImm8(N, Base, OffImm))
1320 int RHSC = (
int)RHS->getZExtValue();
1324 if (RHSC >= 0 && RHSC < 0x1000) {
1327 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1328 Base = CurDAG->getTargetFrameIndex(
1329 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1331 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1342 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(
SDValue N,
1346 !CurDAG->isBaseWithConstantOffset(N))
1350 int RHSC = (
int)RHS->getSExtValue();
1354 if ((RHSC >= -255) && (RHSC < 0)) {
1357 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1358 Base = CurDAG->getTargetFrameIndex(
1359 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1361 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1369 bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(
SDNode *Op,
SDValue N,
1373 ? cast<LoadSDNode>(Op)->getAddressingMode()
1374 : cast<StoreSDNode>(Op)->getAddressingMode();
1386 bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(
SDValue N,
1395 int RHSC = (
int)RHS->getZExtValue();
1396 if (RHSC >= 0 && RHSC < 0x1000)
1398 else if (RHSC < 0 && RHSC >= -255)
1419 ShAmt = Sh->getZExtValue();
1420 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1428 ShImm = CurDAG->getTargetConstant(ShAmt,
SDLoc(N),
MVT::i32);
1433 bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(
SDValue N,
SDValue &Base,
1448 if (RHSC > 1020 || RHSC % 4 != 0)
1453 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1454 Base = CurDAG->getTargetFrameIndex(
1455 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1458 OffImm = CurDAG->getTargetConstant(RHSC/4,
SDLoc(N),
MVT::i32);
1469 SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(
SDNode *N) {
1478 unsigned Opcode = 0;
1480 if (LoadedVT ==
MVT::i32 && isPre &&
1481 SelectAddrMode2OffsetImmPre(N, LD->
getOffset(), Offset, AMOpc)) {
1482 Opcode = ARM::LDR_PRE_IMM;
1484 }
else if (LoadedVT ==
MVT::i32 && !isPre &&
1485 SelectAddrMode2OffsetImm(N, LD->
getOffset(), Offset, AMOpc)) {
1486 Opcode = ARM::LDR_POST_IMM;
1489 SelectAddrMode2OffsetReg(N, LD->
getOffset(), Offset, AMOpc)) {
1490 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1494 SelectAddrMode3Offset(N, LD->
getOffset(), Offset, AMOpc)) {
1497 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1498 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
1501 if (SelectAddrMode3Offset(N, LD->
getOffset(), Offset, AMOpc)) {
1503 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1507 SelectAddrMode2OffsetImmPre(N, LD->
getOffset(), Offset, AMOpc)) {
1509 Opcode = ARM::LDRB_PRE_IMM;
1510 }
else if (!isPre &&
1511 SelectAddrMode2OffsetImm(N, LD->
getOffset(), Offset, AMOpc)) {
1513 Opcode = ARM::LDRB_POST_IMM;
1514 }
else if (SelectAddrMode2OffsetReg(N, LD->
getOffset(), Offset, AMOpc)) {
1516 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1522 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1526 CurDAG->getRegister(0,
MVT::i32), Chain };
1533 CurDAG->getRegister(0,
MVT::i32), Chain };
1542 SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(
SDNode *N) {
1552 unsigned Opcode = 0;
1554 if (SelectT2AddrModeImm8Offset(N, LD->
getOffset(), Offset)) {
1557 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1561 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1563 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1568 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1570 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1582 CurDAG->getRegister(0,
MVT::i32), Chain };
1594 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl,
MVT::i32);
1595 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl,
MVT::i32);
1596 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl,
MVT::i32);
1597 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1605 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl,
MVT::i32);
1606 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl,
MVT::i32);
1607 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl,
MVT::i32);
1608 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1615 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1617 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl,
MVT::i32);
1618 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl,
MVT::i32);
1619 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1626 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1628 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl,
MVT::i32);
1629 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl,
MVT::i32);
1630 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1639 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl,
MVT::i32);
1640 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl,
MVT::i32);
1641 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl,
MVT::i32);
1642 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl,
MVT::i32);
1643 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl,
MVT::i32);
1644 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1645 V2, SubReg2, V3, SubReg3 };
1653 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1655 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl,
MVT::i32);
1656 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl,
MVT::i32);
1657 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl,
MVT::i32);
1658 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl,
MVT::i32);
1659 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1660 V2, SubReg2, V3, SubReg3 };
1668 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1670 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl,
MVT::i32);
1671 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl,
MVT::i32);
1672 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl,
MVT::i32);
1673 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl,
MVT::i32);
1674 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1675 V2, SubReg2, V3, SubReg3 };
1683 unsigned NumVecs,
bool is64BitVector) {
1684 unsigned NumRegs = NumVecs;
1685 if (!is64BitVector && NumVecs < 3)
1688 unsigned Alignment = cast<ConstantSDNode>(
Align)->getZExtValue();
1689 if (Alignment >= 32 && NumRegs == 4)
1691 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1693 else if (Alignment >= 8)
1698 return CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
1704 default:
return false;
1705 case ARM::VLD1d8wb_fixed :
return true;
1706 case ARM::VLD1d16wb_fixed :
return true;
1707 case ARM::VLD1d64Qwb_fixed :
return true;
1708 case ARM::VLD1d32wb_fixed :
return true;
1709 case ARM::VLD1d64wb_fixed :
return true;
1710 case ARM::VLD1d64TPseudoWB_fixed :
return true;
1711 case ARM::VLD1d64QPseudoWB_fixed :
return true;
1712 case ARM::VLD1q8wb_fixed :
return true;
1713 case ARM::VLD1q16wb_fixed :
return true;
1714 case ARM::VLD1q32wb_fixed :
return true;
1715 case ARM::VLD1q64wb_fixed :
return true;
1716 case ARM::VLD2d8wb_fixed :
return true;
1717 case ARM::VLD2d16wb_fixed :
return true;
1718 case ARM::VLD2d32wb_fixed :
return true;
1719 case ARM::VLD2q8PseudoWB_fixed :
return true;
1720 case ARM::VLD2q16PseudoWB_fixed :
return true;
1721 case ARM::VLD2q32PseudoWB_fixed :
return true;
1722 case ARM::VLD2DUPd8wb_fixed :
return true;
1723 case ARM::VLD2DUPd16wb_fixed :
return true;
1724 case ARM::VLD2DUPd32wb_fixed :
return true;
1731 default:
return false;
1732 case ARM::VST1d8wb_fixed :
return true;
1733 case ARM::VST1d16wb_fixed :
return true;
1734 case ARM::VST1d32wb_fixed :
return true;
1735 case ARM::VST1d64wb_fixed :
return true;
1736 case ARM::VST1q8wb_fixed :
return true;
1737 case ARM::VST1q16wb_fixed :
return true;
1738 case ARM::VST1q32wb_fixed :
return true;
1739 case ARM::VST1q64wb_fixed :
return true;
1740 case ARM::VST1d64TPseudoWB_fixed :
return true;
1741 case ARM::VST1d64QPseudoWB_fixed :
return true;
1742 case ARM::VST2d8wb_fixed :
return true;
1743 case ARM::VST2d16wb_fixed :
return true;
1744 case ARM::VST2d32wb_fixed :
return true;
1745 case ARM::VST2q8PseudoWB_fixed :
return true;
1746 case ARM::VST2q16PseudoWB_fixed :
return true;
1747 case ARM::VST2q32PseudoWB_fixed :
return true;
1755 &&
"Incorrect fixed stride updating instruction.");
1758 case ARM::VLD1d8wb_fixed:
return ARM::VLD1d8wb_register;
1759 case ARM::VLD1d16wb_fixed:
return ARM::VLD1d16wb_register;
1760 case ARM::VLD1d32wb_fixed:
return ARM::VLD1d32wb_register;
1761 case ARM::VLD1d64wb_fixed:
return ARM::VLD1d64wb_register;
1762 case ARM::VLD1q8wb_fixed:
return ARM::VLD1q8wb_register;
1763 case ARM::VLD1q16wb_fixed:
return ARM::VLD1q16wb_register;
1764 case ARM::VLD1q32wb_fixed:
return ARM::VLD1q32wb_register;
1765 case ARM::VLD1q64wb_fixed:
return ARM::VLD1q64wb_register;
1766 case ARM::VLD1d64Twb_fixed:
return ARM::VLD1d64Twb_register;
1767 case ARM::VLD1d64Qwb_fixed:
return ARM::VLD1d64Qwb_register;
1768 case ARM::VLD1d64TPseudoWB_fixed:
return ARM::VLD1d64TPseudoWB_register;
1769 case ARM::VLD1d64QPseudoWB_fixed:
return ARM::VLD1d64QPseudoWB_register;
1771 case ARM::VST1d8wb_fixed:
return ARM::VST1d8wb_register;
1772 case ARM::VST1d16wb_fixed:
return ARM::VST1d16wb_register;
1773 case ARM::VST1d32wb_fixed:
return ARM::VST1d32wb_register;
1774 case ARM::VST1d64wb_fixed:
return ARM::VST1d64wb_register;
1775 case ARM::VST1q8wb_fixed:
return ARM::VST1q8wb_register;
1776 case ARM::VST1q16wb_fixed:
return ARM::VST1q16wb_register;
1777 case ARM::VST1q32wb_fixed:
return ARM::VST1q32wb_register;
1778 case ARM::VST1q64wb_fixed:
return ARM::VST1q64wb_register;
1779 case ARM::VST1d64TPseudoWB_fixed:
return ARM::VST1d64TPseudoWB_register;
1780 case ARM::VST1d64QPseudoWB_fixed:
return ARM::VST1d64QPseudoWB_register;
1782 case ARM::VLD2d8wb_fixed:
return ARM::VLD2d8wb_register;
1783 case ARM::VLD2d16wb_fixed:
return ARM::VLD2d16wb_register;
1784 case ARM::VLD2d32wb_fixed:
return ARM::VLD2d32wb_register;
1785 case ARM::VLD2q8PseudoWB_fixed:
return ARM::VLD2q8PseudoWB_register;
1786 case ARM::VLD2q16PseudoWB_fixed:
return ARM::VLD2q16PseudoWB_register;
1787 case ARM::VLD2q32PseudoWB_fixed:
return ARM::VLD2q32PseudoWB_register;
1789 case ARM::VST2d8wb_fixed:
return ARM::VST2d8wb_register;
1790 case ARM::VST2d16wb_fixed:
return ARM::VST2d16wb_register;
1791 case ARM::VST2d32wb_fixed:
return ARM::VST2d32wb_register;
1792 case ARM::VST2q8PseudoWB_fixed:
return ARM::VST2q8PseudoWB_register;
1793 case ARM::VST2q16PseudoWB_fixed:
return ARM::VST2q16PseudoWB_register;
1794 case ARM::VST2q32PseudoWB_fixed:
return ARM::VST2q32PseudoWB_register;
1796 case ARM::VLD2DUPd8wb_fixed:
return ARM::VLD2DUPd8wb_register;
1797 case ARM::VLD2DUPd16wb_fixed:
return ARM::VLD2DUPd16wb_register;
1798 case ARM::VLD2DUPd32wb_fixed:
return ARM::VLD2DUPd32wb_register;
1803 SDNode *ARMDAGToDAGISel::SelectVLD(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
1804 const uint16_t *DOpcodes,
1805 const uint16_t *QOpcodes0,
1806 const uint16_t *QOpcodes1) {
1807 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLD NumVecs out-of-range");
1811 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1818 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
1836 assert(NumVecs == 1 &&
"v2i64 type only supported for VLD1");
1844 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1849 std::vector<EVT> ResTys;
1850 ResTys.push_back(ResTy);
1861 if (is64BitVector || NumVecs <= 2) {
1862 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
1870 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.
getNode()))
1875 !isa<ConstantSDNode>(Inc.
getNode()))
1881 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1892 const SDValue OpsA[] = { MemAddr,
Align, Reg0, ImplDef, Pred, Reg0, Chain };
1893 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1902 assert(isa<ConstantSDNode>(Inc.
getNode()) &&
1903 "only constant post-increment update allowed for VLD3/4");
1911 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
1916 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
1917 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1924 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1925 ARM::qsub_3 == ARM::qsub_0+3 &&
"Unexpected subreg numbering");
1926 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1927 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
1929 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1936 SDNode *ARMDAGToDAGISel::SelectVST(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
1937 const uint16_t *DOpcodes,
1938 const uint16_t *QOpcodes0,
1939 const uint16_t *QOpcodes1) {
1940 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VST NumVecs out-of-range");
1944 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1945 unsigned Vec0Idx = 3;
1950 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
1955 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
1973 assert(NumVecs == 1 &&
"v2i64 type only supported for VST1");
1977 std::vector<EVT> ResTys;
1987 if (is64BitVector || NumVecs <= 2) {
1991 }
else if (is64BitVector) {
2013 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2021 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.
getNode()))
2025 if (!isa<ConstantSDNode>(Inc.
getNode()))
2034 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2037 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2056 const SDValue OpsA[] = { MemAddr,
Align, Reg0, RegSeq, Pred, Reg0, Chain };
2057 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2060 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
2068 assert(isa<ConstantSDNode>(Inc.
getNode()) &&
2069 "only constant post-increment update allowed for VST3/4");
2077 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
2079 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2083 SDNode *ARMDAGToDAGISel::SelectVLDSTLane(
SDNode *N,
bool IsLoad,
2084 bool isUpdating,
unsigned NumVecs,
2085 const uint16_t *DOpcodes,
2086 const uint16_t *QOpcodes) {
2087 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDSTLane NumVecs out-of-range");
2091 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2092 unsigned Vec0Idx = 3;
2097 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
2101 cast<ConstantSDNode>(N->
getOperand(Vec0Idx + NumVecs))->getZExtValue();
2105 unsigned Alignment = 0;
2107 Alignment = cast<ConstantSDNode>(
Align)->getZExtValue();
2109 if (Alignment > NumBytes)
2110 Alignment = NumBytes;
2111 if (Alignment < 8 && Alignment < NumBytes)
2114 Alignment = (Alignment & -Alignment);
2118 Align = CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
2134 std::vector<EVT> ResTys;
2136 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2181 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2183 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2184 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
2190 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2191 ARM::qsub_3 == ARM::qsub_0+3 &&
"Unexpected subreg numbering");
2192 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2193 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2195 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2202 SDNode *ARMDAGToDAGISel::SelectVLDDup(
SDNode *N,
bool isUpdating,
2204 const uint16_t *Opcodes) {
2205 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDDup NumVecs out-of-range");
2213 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
2218 unsigned Alignment = 0;
2220 Alignment = cast<ConstantSDNode>(
Align)->getZExtValue();
2222 if (Alignment > NumBytes)
2223 Alignment = NumBytes;
2224 if (Alignment < 8 && Alignment < NumBytes)
2227 Alignment = (Alignment & -Alignment);
2231 Align = CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
2253 if (!isa<ConstantSDNode>(Inc.
getNode()))
2256 else if (NumVecs > 2)
2263 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2264 std::vector<EVT> ResTys;
2269 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2270 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
2271 SuperReg =
SDValue(VLdDup, 0);
2274 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
"Unexpected subreg numbering");
2275 unsigned SubIdx = ARM::dsub_0;
2276 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2278 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2285 SDNode *ARMDAGToDAGISel::SelectVTBL(
SDNode *N,
bool IsExt,
unsigned NumVecs,
2287 assert(NumVecs >= 2 && NumVecs <= 4 &&
"VTBL NumVecs out-of-range");
2290 unsigned FirstTblReg = IsExt ? 2 : 1;
2315 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
2318 SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(
SDNode *N,
2320 if (!Subtarget->hasV6T2Ops())
2323 unsigned Opc = isSigned
2324 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
2325 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2329 unsigned And_imm = 0;
2334 if (And_imm & (And_imm + 1))
2337 unsigned Srl_imm = 0;
2340 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
2344 unsigned LSB = Srl_imm;
2350 if (Subtarget->isThumb()) {
2351 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2353 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2354 getAL(CurDAG, dl), Reg0, Reg0 };
2355 return CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2364 getAL(CurDAG, dl), Reg0, Reg0 };
2365 return CurDAG->SelectNodeTo(N, ARM::MOVsi,
MVT::i32, Ops);
2369 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2370 CurDAG->getTargetConstant(Width, dl,
MVT::i32),
2371 getAL(CurDAG, dl), Reg0 };
2372 return CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2379 unsigned Shl_imm = 0;
2381 assert(Shl_imm > 0 && Shl_imm < 32 &&
"bad amount in shift node!");
2382 unsigned Srl_imm = 0;
2384 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
2386 unsigned Width = 32 - Srl_imm - 1;
2387 int LSB = Srl_imm - Shl_imm;
2392 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2393 CurDAG->getTargetConstant(Width, dl,
MVT::i32),
2394 getAL(CurDAG, dl), Reg0 };
2395 return CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2400 unsigned Width = cast<VTSDNode>(N->
getOperand(1))->getVT().getSizeInBits();
2406 if (LSB + Width > 32)
2411 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2412 CurDAG->getTargetConstant(Width - 1, dl,
MVT::i32),
2413 getAL(CurDAG, dl), Reg0 };
2414 return CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2435 if (Subtarget->isThumb1Only())
2449 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2450 XType.isInteger() && SRAConstant !=
nullptr &&
2452 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS :
ARM::ABS;
2453 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2459 SDNode *ARMDAGToDAGISel::SelectConcatVector(
SDNode *N) {
2479 SDNode *ResNode = SelectWriteRegister(N);
2485 SDNode *ResNode = SelectReadRegister(N);
2491 SDNode *ResNode = SelectInlineAsm(N);
2498 SDNode *ResNode = SelectABSOp(N);
2505 unsigned Val = cast<ConstantSDNode>(
N)->getZExtValue();
2507 if (Subtarget->useMovt(*MF))
2512 if (Subtarget->isThumb()) {
2513 UseCP = (Val > 255 &&
2516 !(Subtarget->hasV6T2Ops() && Val <= 0xffff));
2521 !(Subtarget->hasV6T2Ops() && Val <= 0xffff));
2525 SDValue CPIdx = CurDAG->getTargetConstantPool(
2527 TLI->getPointerTy(CurDAG->getDataLayout()));
2530 if (Subtarget->isThumb()) {
2533 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
2539 CurDAG->getTargetConstant(0, dl,
MVT::i32),
2542 CurDAG->getEntryNode()
2556 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
2557 SDValue TFI = CurDAG->getTargetFrameIndex(
2558 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
2559 if (Subtarget->isThumb1Only()) {
2565 return CurDAG->SelectNodeTo(N, ARM::tADDframe,
MVT::i32, TFI,
2566 CurDAG->getTargetConstant(0, dl,
MVT::i32));
2568 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2569 ARM::t2ADDri : ARM::ADDri);
2572 CurDAG->getRegister(0,
MVT::i32) };
2573 return CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2577 if (
SDNode *
I = SelectV6T2BitfieldExtractOp(N,
false))
2582 if (
SDNode *
I = SelectV6T2BitfieldExtractOp(N,
true))
2586 if (Subtarget->isThumb1Only())
2589 unsigned RHSV =
C->getZExtValue();
2592 unsigned ShImm =
Log2_32(RHSV-1);
2599 if (Subtarget->isThumb()) {
2600 SDValue Ops[] = { V, V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
2601 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs,
MVT::i32, Ops);
2603 SDValue Ops[] = { V, V, Reg0, ShImmOp,
getAL(CurDAG, dl), Reg0,
2605 return CurDAG->SelectNodeTo(N, ARM::ADDrsi,
MVT::i32, Ops);
2609 unsigned ShImm =
Log2_32(RHSV+1);
2616 if (Subtarget->isThumb()) {
2617 SDValue Ops[] = { V, V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
2618 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs,
MVT::i32, Ops);
2620 SDValue Ops[] = { V, V, Reg0, ShImmOp,
getAL(CurDAG, dl), Reg0,
2622 return CurDAG->SelectNodeTo(N, ARM::RSBrsi,
MVT::i32, Ops);
2629 if (
SDNode *
I = SelectV6T2BitfieldExtractOp(N,
false))
2640 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2642 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2656 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2657 (N1CVal & 0xffffU) == 0xffffU &&
2658 (N2CVal & 0xffffU) == 0x0U) {
2659 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2663 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
2673 if (Subtarget->isThumb1Only())
2675 if (Subtarget->isThumb()) {
2682 CurDAG->getRegister(0,
MVT::i32) };
2683 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2689 if (Subtarget->isThumb1Only())
2691 if (Subtarget->isThumb()) {
2698 CurDAG->getRegister(0,
MVT::i32) };
2699 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2705 if (Subtarget->isThumb()) {
2714 CurDAG->getRegister(0,
MVT::i32) };
2715 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2721 if (Subtarget->isThumb()) {
2730 CurDAG->getRegister(0,
MVT::i32) };
2731 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2737 SDNode *ResNode =
nullptr;
2738 if (Subtarget->isThumb() && Subtarget->hasThumb2())
2739 ResNode = SelectT2IndexedLoad(N);
2741 ResNode = SelectARMIndexedLoad(N);
2760 unsigned Opc = Subtarget->isThumb() ?
2761 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
2771 SDValue Tmp2 = CurDAG->getTargetConstant(((
unsigned)
2772 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
2774 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
2780 ReplaceUses(
SDValue(N, 1), InFlag);
2790 default:
return nullptr;
2791 case MVT::v8i8: Opc = ARM::VZIPd8;
break;
2804 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2810 default:
return nullptr;
2811 case MVT::v8i8: Opc = ARM::VUZPd8;
break;
2824 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2830 default:
return nullptr;
2831 case MVT::v8i8: Opc = ARM::VTRNd8;
break;
2843 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
2850 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
2853 assert(EltVT ==
MVT::f32 &&
"unexpected type for BUILD_VECTOR");
2856 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
2862 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2864 return SelectVLDDup(N,
false, 2, Opcodes);
2868 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2869 ARM::VLD3DUPd16Pseudo,
2870 ARM::VLD3DUPd32Pseudo };
2871 return SelectVLDDup(N,
false, 3, Opcodes);
2875 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2876 ARM::VLD4DUPd16Pseudo,
2877 ARM::VLD4DUPd32Pseudo };
2878 return SelectVLDDup(N,
false, 4, Opcodes);
2882 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2883 ARM::VLD2DUPd16wb_fixed,
2884 ARM::VLD2DUPd32wb_fixed };
2885 return SelectVLDDup(N,
true, 2, Opcodes);
2889 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2890 ARM::VLD3DUPd16Pseudo_UPD,
2891 ARM::VLD3DUPd32Pseudo_UPD };
2892 return SelectVLDDup(N,
true, 3, Opcodes);
2896 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2897 ARM::VLD4DUPd16Pseudo_UPD,
2898 ARM::VLD4DUPd32Pseudo_UPD };
2899 return SelectVLDDup(N,
true, 4, Opcodes);
2903 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2904 ARM::VLD1d16wb_fixed,
2905 ARM::VLD1d32wb_fixed,
2906 ARM::VLD1d64wb_fixed };
2907 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2908 ARM::VLD1q16wb_fixed,
2909 ARM::VLD1q32wb_fixed,
2910 ARM::VLD1q64wb_fixed };
2911 return SelectVLD(N,
true, 1, DOpcodes, QOpcodes,
nullptr);
2915 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2916 ARM::VLD2d16wb_fixed,
2917 ARM::VLD2d32wb_fixed,
2918 ARM::VLD1q64wb_fixed};
2919 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2920 ARM::VLD2q16PseudoWB_fixed,
2921 ARM::VLD2q32PseudoWB_fixed };
2922 return SelectVLD(N,
true, 2, DOpcodes, QOpcodes,
nullptr);
2926 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2927 ARM::VLD3d16Pseudo_UPD,
2928 ARM::VLD3d32Pseudo_UPD,
2929 ARM::VLD1d64TPseudoWB_fixed};
2930 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2931 ARM::VLD3q16Pseudo_UPD,
2932 ARM::VLD3q32Pseudo_UPD };
2933 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2934 ARM::VLD3q16oddPseudo_UPD,
2935 ARM::VLD3q32oddPseudo_UPD };
2936 return SelectVLD(N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2940 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2941 ARM::VLD4d16Pseudo_UPD,
2942 ARM::VLD4d32Pseudo_UPD,
2943 ARM::VLD1d64QPseudoWB_fixed};
2944 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2945 ARM::VLD4q16Pseudo_UPD,
2946 ARM::VLD4q32Pseudo_UPD };
2947 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2948 ARM::VLD4q16oddPseudo_UPD,
2949 ARM::VLD4q32oddPseudo_UPD };
2950 return SelectVLD(N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2954 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2955 ARM::VLD2LNd16Pseudo_UPD,
2956 ARM::VLD2LNd32Pseudo_UPD };
2957 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2958 ARM::VLD2LNq32Pseudo_UPD };
2959 return SelectVLDSTLane(N,
true,
true, 2, DOpcodes, QOpcodes);
2963 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2964 ARM::VLD3LNd16Pseudo_UPD,
2965 ARM::VLD3LNd32Pseudo_UPD };
2966 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2967 ARM::VLD3LNq32Pseudo_UPD };
2968 return SelectVLDSTLane(N,
true,
true, 3, DOpcodes, QOpcodes);
2972 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2973 ARM::VLD4LNd16Pseudo_UPD,
2974 ARM::VLD4LNd32Pseudo_UPD };
2975 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2976 ARM::VLD4LNq32Pseudo_UPD };
2977 return SelectVLDSTLane(N,
true,
true, 4, DOpcodes, QOpcodes);
2981 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2982 ARM::VST1d16wb_fixed,
2983 ARM::VST1d32wb_fixed,
2984 ARM::VST1d64wb_fixed };
2985 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2986 ARM::VST1q16wb_fixed,
2987 ARM::VST1q32wb_fixed,
2988 ARM::VST1q64wb_fixed };
2989 return SelectVST(N,
true, 1, DOpcodes, QOpcodes,
nullptr);
2993 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2994 ARM::VST2d16wb_fixed,
2995 ARM::VST2d32wb_fixed,
2996 ARM::VST1q64wb_fixed};
2997 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2998 ARM::VST2q16PseudoWB_fixed,
2999 ARM::VST2q32PseudoWB_fixed };
3000 return SelectVST(N,
true, 2, DOpcodes, QOpcodes,
nullptr);
3004 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3005 ARM::VST3d16Pseudo_UPD,
3006 ARM::VST3d32Pseudo_UPD,
3007 ARM::VST1d64TPseudoWB_fixed};
3008 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3009 ARM::VST3q16Pseudo_UPD,
3010 ARM::VST3q32Pseudo_UPD };
3011 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3012 ARM::VST3q16oddPseudo_UPD,
3013 ARM::VST3q32oddPseudo_UPD };
3014 return SelectVST(N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3018 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3019 ARM::VST4d16Pseudo_UPD,
3020 ARM::VST4d32Pseudo_UPD,
3021 ARM::VST1d64QPseudoWB_fixed};
3022 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3023 ARM::VST4q16Pseudo_UPD,
3024 ARM::VST4q32Pseudo_UPD };
3025 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3026 ARM::VST4q16oddPseudo_UPD,
3027 ARM::VST4q32oddPseudo_UPD };
3028 return SelectVST(N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3032 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3033 ARM::VST2LNd16Pseudo_UPD,
3034 ARM::VST2LNd32Pseudo_UPD };
3035 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3036 ARM::VST2LNq32Pseudo_UPD };
3037 return SelectVLDSTLane(N,
false,
true, 2, DOpcodes, QOpcodes);
3041 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3042 ARM::VST3LNd16Pseudo_UPD,
3043 ARM::VST3LNd32Pseudo_UPD };
3044 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3045 ARM::VST3LNq32Pseudo_UPD };
3046 return SelectVLDSTLane(N,
false,
true, 3, DOpcodes, QOpcodes);
3050 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3051 ARM::VST4LNd16Pseudo_UPD,
3052 ARM::VST4LNd32Pseudo_UPD };
3053 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3054 ARM::VST4LNq32Pseudo_UPD };
3055 return SelectVLDSTLane(N,
false,
true, 4, DOpcodes, QOpcodes);
3060 unsigned IntNo = cast<ConstantSDNode>(N->
getOperand(1))->getZExtValue();
3065 case Intrinsic::arm_ldaexd:
3066 case Intrinsic::arm_ldrexd: {
3070 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3072 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3073 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3074 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
3077 std::vector<EVT> ResTys;
3091 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3094 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
3095 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3099 if (!SDValue(N, 0).use_empty()) {
3102 Result = SDValue(Ld, 0);
3105 CurDAG->getTargetConstant(ARM::gsub_0, dl,
MVT::i32);
3107 dl,
MVT::i32, SDValue(Ld, 0), SubRegIdx);
3108 Result = SDValue(ResNode,0);
3110 ReplaceUses(SDValue(N, 0), Result);
3112 if (!SDValue(N, 1).use_empty()) {
3115 Result = SDValue(Ld, 1);
3118 CurDAG->getTargetConstant(ARM::gsub_1, dl,
MVT::i32);
3120 dl,
MVT::i32, SDValue(Ld, 0), SubRegIdx);
3121 Result = SDValue(ResNode,0);
3123 ReplaceUses(SDValue(N, 1), Result);
3125 ReplaceUses(SDValue(N, 2), OutChain);
3128 case Intrinsic::arm_stlexd:
3129 case Intrinsic::arm_strexd: {
3140 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3154 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3155 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3156 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
3158 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3161 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
3162 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3167 case Intrinsic::arm_neon_vld1: {
3168 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3169 ARM::VLD1d32, ARM::VLD1d64 };
3170 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3171 ARM::VLD1q32, ARM::VLD1q64};
3172 return SelectVLD(N,
false, 1, DOpcodes, QOpcodes,
nullptr);
3175 case Intrinsic::arm_neon_vld2: {
3176 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3177 ARM::VLD2d32, ARM::VLD1q64 };
3178 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3179 ARM::VLD2q32Pseudo };
3180 return SelectVLD(N,
false, 2, DOpcodes, QOpcodes,
nullptr);
3183 case Intrinsic::arm_neon_vld3: {
3184 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3187 ARM::VLD1d64TPseudo };
3188 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3189 ARM::VLD3q16Pseudo_UPD,
3190 ARM::VLD3q32Pseudo_UPD };
3191 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3192 ARM::VLD3q16oddPseudo,
3193 ARM::VLD3q32oddPseudo };
3194 return SelectVLD(N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3197 case Intrinsic::arm_neon_vld4: {
3198 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3201 ARM::VLD1d64QPseudo };
3202 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3203 ARM::VLD4q16Pseudo_UPD,
3204 ARM::VLD4q32Pseudo_UPD };
3205 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3206 ARM::VLD4q16oddPseudo,
3207 ARM::VLD4q32oddPseudo };
3208 return SelectVLD(N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3211 case Intrinsic::arm_neon_vld2lane: {
3212 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3213 ARM::VLD2LNd16Pseudo,
3214 ARM::VLD2LNd32Pseudo };
3215 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3216 ARM::VLD2LNq32Pseudo };
3217 return SelectVLDSTLane(N,
true,
false, 2, DOpcodes, QOpcodes);
3220 case Intrinsic::arm_neon_vld3lane: {
3221 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3222 ARM::VLD3LNd16Pseudo,
3223 ARM::VLD3LNd32Pseudo };
3224 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3225 ARM::VLD3LNq32Pseudo };
3226 return SelectVLDSTLane(N,
true,
false, 3, DOpcodes, QOpcodes);
3229 case Intrinsic::arm_neon_vld4lane: {
3230 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3231 ARM::VLD4LNd16Pseudo,
3232 ARM::VLD4LNd32Pseudo };
3233 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3234 ARM::VLD4LNq32Pseudo };
3235 return SelectVLDSTLane(N,
true,
false, 4, DOpcodes, QOpcodes);
3238 case Intrinsic::arm_neon_vst1: {
3239 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3240 ARM::VST1d32, ARM::VST1d64 };
3241 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3242 ARM::VST1q32, ARM::VST1q64 };
3243 return SelectVST(N,
false, 1, DOpcodes, QOpcodes,
nullptr);
3246 case Intrinsic::arm_neon_vst2: {
3247 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3248 ARM::VST2d32, ARM::VST1q64 };
3249 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3250 ARM::VST2q32Pseudo };
3251 return SelectVST(N,
false, 2, DOpcodes, QOpcodes,
nullptr);
3254 case Intrinsic::arm_neon_vst3: {
3255 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3258 ARM::VST1d64TPseudo };
3259 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3260 ARM::VST3q16Pseudo_UPD,
3261 ARM::VST3q32Pseudo_UPD };
3262 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3263 ARM::VST3q16oddPseudo,
3264 ARM::VST3q32oddPseudo };
3265 return SelectVST(N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3268 case Intrinsic::arm_neon_vst4: {
3269 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3272 ARM::VST1d64QPseudo };
3273 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3274 ARM::VST4q16Pseudo_UPD,
3275 ARM::VST4q32Pseudo_UPD };
3276 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3277 ARM::VST4q16oddPseudo,
3278 ARM::VST4q32oddPseudo };
3279 return SelectVST(N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3282 case Intrinsic::arm_neon_vst2lane: {
3283 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3284 ARM::VST2LNd16Pseudo,
3285 ARM::VST2LNd32Pseudo };
3286 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3287 ARM::VST2LNq32Pseudo };
3288 return SelectVLDSTLane(N,
false,
false, 2, DOpcodes, QOpcodes);
3291 case Intrinsic::arm_neon_vst3lane: {
3292 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3293 ARM::VST3LNd16Pseudo,
3294 ARM::VST3LNd32Pseudo };
3295 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3296 ARM::VST3LNq32Pseudo };
3297 return SelectVLDSTLane(N,
false,
false, 3, DOpcodes, QOpcodes);
3300 case Intrinsic::arm_neon_vst4lane: {
3301 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3302 ARM::VST4LNd16Pseudo,
3303 ARM::VST4LNd32Pseudo };
3304 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3305 ARM::VST4LNq32Pseudo };
3306 return SelectVLDSTLane(N,
false,
false, 4, DOpcodes, QOpcodes);
3313 unsigned IntNo = cast<ConstantSDNode>(N->
getOperand(0))->getZExtValue();
3318 case Intrinsic::arm_neon_vtbl2:
3320 case Intrinsic::arm_neon_vtbl3:
3321 return SelectVTBL(N,
false, 3, ARM::VTBL3Pseudo);
3322 case Intrinsic::arm_neon_vtbl4:
3323 return SelectVTBL(N,
false, 4, ARM::VTBL4Pseudo);
3325 case Intrinsic::arm_neon_vtbx2:
3326 return SelectVTBL(N,
true, 2, ARM::VTBX2);
3327 case Intrinsic::arm_neon_vtbx3:
3328 return SelectVTBL(N,
true, 3, ARM::VTBX3Pseudo);
3329 case Intrinsic::arm_neon_vtbx4:
3330 return SelectVTBL(N,
true, 4, ARM::VTBX4Pseudo);
3344 return CurDAG->getMachineNode(
ARM::VTBL1, dl, VT, Ops);
3353 SDValue RegSeq = SDValue(createDRegPairNode(
MVT::v16i8, V0, V1), 0);
3360 return CurDAG->getMachineNode(
ARM::VTBL2, dl, VT, Ops);
3364 return SelectConcatVector(N);
3367 return SelectCode(N);
3377 std::vector<SDValue>& Ops) {
3379 RegString.
split(Fields,
":");
3381 if (Fields.
size() > 1) {
3382 bool AllIntFields =
true;
3387 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
3391 assert(AllIntFields &&
3392 "Unexpected non-integer value in special register string.");
3403 .Case(
"r8_usr", 0x00)
3404 .
Case(
"r9_usr", 0x01)
3405 .
Case(
"r10_usr", 0x02)
3406 .
Case(
"r11_usr", 0x03)
3407 .
Case(
"r12_usr", 0x04)
3408 .
Case(
"sp_usr", 0x05)
3409 .
Case(
"lr_usr", 0x06)
3410 .
Case(
"r8_fiq", 0x08)
3411 .
Case(
"r9_fiq", 0x09)
3412 .
Case(
"r10_fiq", 0x0a)
3413 .
Case(
"r11_fiq", 0x0b)
3414 .
Case(
"r12_fiq", 0x0c)
3415 .
Case(
"sp_fiq", 0x0d)
3416 .
Case(
"lr_fiq", 0x0e)
3417 .
Case(
"lr_irq", 0x10)
3418 .
Case(
"sp_irq", 0x11)
3419 .
Case(
"lr_svc", 0x12)
3420 .
Case(
"sp_svc", 0x13)
3421 .
Case(
"lr_abt", 0x14)
3422 .
Case(
"sp_abt", 0x15)
3423 .
Case(
"lr_und", 0x16)
3424 .
Case(
"sp_und", 0x17)
3425 .
Case(
"lr_mon", 0x1c)
3426 .
Case(
"sp_mon", 0x1d)
3427 .
Case(
"elr_hyp", 0x1e)
3428 .
Case(
"sp_hyp", 0x1f)
3429 .
Case(
"spsr_fiq", 0x2e)
3430 .
Case(
"spsr_irq", 0x30)
3431 .
Case(
"spsr_svc", 0x32)
3432 .
Case(
"spsr_abt", 0x34)
3433 .
Case(
"spsr_und", 0x36)
3434 .
Case(
"spsr_mon", 0x3c)
3435 .
Case(
"spsr_hyp", 0x3e)
3453 .
Case(
"primask", 0x10)
3454 .
Case(
"basepri", 0x11)
3455 .
Case(
"basepri_max", 0x12)
3456 .
Case(
"faultmask", 0x13)
3457 .
Case(
"control", 0x14)
3471 .
Case(
"nzcvqg", 0x3)
3480 if (SYSmvalue == -1)
3484 if (!Subtarget->
hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3490 assert (Flags.
empty() &&
"Unexpected flags for reading M class register.");
3499 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.
empty()))
3510 if (SYSmvalue < 0x4)
3511 return SYSmvalue | Mask << 10;
3522 if (Reg ==
"apsr") {
3532 if (Reg !=
"cpsr" && Reg !=
"spsr") {
3537 if (Flags.
empty() || Flags ==
"all")
3542 for (
char Flag : Flags) {
3562 if (!FlagVal || (Mask & FlagVal))
3577 SDNode *ARMDAGToDAGISel::SelectReadRegister(
SDNode *N){
3580 bool IsThumb2 = Subtarget->isThumb2();
3583 std::vector<SDValue> Ops;
3593 if (Ops.size() == 5){
3594 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3597 assert(Ops.size() == 3 &&
3598 "Invalid number of fields in special register string.");
3599 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3603 Ops.push_back(
getAL(CurDAG, DL));
3604 Ops.push_back(CurDAG->getRegister(0,
MVT::i32));
3606 return CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops);
3609 std::string SpecialReg = RegString->getString().lower();
3612 if (BankedReg != -1) {
3613 Ops = { CurDAG->getTargetConstant(BankedReg, DL,
MVT::i32),
3616 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3624 .Case(
"fpscr", ARM::VMRS)
3625 .
Case(
"fpexc", ARM::VMRS_FPEXC)
3626 .
Case(
"fpsid", ARM::VMRS_FPSID)
3627 .
Case(
"mvfr0", ARM::VMRS_MVFR0)
3628 .
Case(
"mvfr1", ARM::VMRS_MVFR1)
3629 .
Case(
"mvfr2", ARM::VMRS_MVFR2)
3630 .
Case(
"fpinst", ARM::VMRS_FPINST)
3631 .
Case(
"fpinst2", ARM::VMRS_FPINST2)
3636 if (!Subtarget->hasVFP2())
3638 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
3641 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
3649 if (Subtarget->isMClass()) {
3651 if (SYSmValue == -1)
3654 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL,
MVT::i32),
3662 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
3663 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
3665 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS, DL,
3669 if (SpecialReg ==
"spsr") {
3670 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
3672 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
3682 SDNode *ARMDAGToDAGISel::SelectWriteRegister(
SDNode *N){
3685 bool IsThumb2 = Subtarget->isThumb2();
3688 std::vector<SDValue> Ops;
3697 if (Ops.size() == 5) {
3698 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3701 assert(Ops.size() == 3 &&
3702 "Invalid number of fields in special register string.");
3703 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3705 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3708 Ops.push_back(
getAL(CurDAG, DL));
3709 Ops.push_back(CurDAG->getRegister(0,
MVT::i32));
3712 return CurDAG->getMachineNode(Opcode, DL,
MVT::Other, Ops);
3715 std::string SpecialReg = RegString->getString().lower();
3717 if (BankedReg != -1) {
3721 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3729 .Case(
"fpscr", ARM::VMSR)
3730 .
Case(
"fpexc", ARM::VMSR_FPEXC)
3731 .
Case(
"fpsid", ARM::VMSR_FPSID)
3732 .
Case(
"fpinst", ARM::VMSR_FPINST)
3733 .
Case(
"fpinst2", ARM::VMSR_FPINST2)
3737 if (!Subtarget->hasVFP2())
3741 return CurDAG->getMachineNode(Opcode, DL,
MVT::Other, Ops);
3746 std::string
Reg = Fields[0].str();
3751 if (Subtarget->isMClass()) {
3753 if (SpecialReg ==
"basepri_max") {
3758 if (SYSmValue == -1)
3761 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL,
MVT::i32),
3764 return CurDAG->getMachineNode(ARM::t2MSR_M, DL,
MVT::Other, Ops);
3775 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
3783 std::vector<SDValue> AsmNodeOperands;
3785 bool Changed =
false;
3798 : SDValue(
nullptr,0);
3802 for(
unsigned i = 0, e = N->
getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
3804 AsmNodeOperands.push_back(op);
3810 Flag =
C->getZExtValue();
3822 AsmNodeOperands.push_back(op);
3830 unsigned DefIdx = 0;
3831 bool IsTiedToChangedOp =
false;
3835 IsTiedToChangedOp = OpChanged[DefIdx];
3843 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3847 assert((i+2 < NumOps) &&
"Invalid number of operands in inline asm");
3850 unsigned Reg0 = cast<RegisterSDNode>(V0)->
getReg();
3851 unsigned Reg1 = cast<RegisterSDNode>(V1)->
getReg();
3862 SDValue Chain = SDValue(N,0);
3865 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR,
MVT::Untyped,
3869 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl,
MVT::i32,
3871 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl,
MVT::i32,
3873 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3875 SDValue
T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.
getValue(1));
3880 CurDAG->UpdateNodeOperands(GU, Ops);
3888 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0,
MVT::i32,
3890 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1,
MVT::i32,
3892 SDValue Pair = SDValue(createGPRPairNode(
MVT::Untyped, T0, T1), 0);
3898 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.
getValue(1));
3907 OpChanged[OpChanged.
size() -1 ] =
true;
3909 if (IsTiedToChangedOp)
3914 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
3917 AsmNodeOperands.push_back(PairedReg);
3924 AsmNodeOperands.push_back(Glue);
3935 bool ARMDAGToDAGISel::
3936 SelectInlineAsmMemoryOperand(
const SDValue &Op,
unsigned ConstraintID,
3937 std::vector<SDValue> &OutOps) {
3938 switch(ConstraintID) {
3957 OutOps.push_back(Op);
3968 return new ARMDAGToDAGISel(TM, OptLevel);
void push_back(const T &Elt)
SDValue getValue(unsigned R) const
bool hasOneUse() const
Return true if there is exactly one use of this node.
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
static int getARClassRegisterMask(StringRef Reg, StringRef Flags)
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
bool mayStore() const
Return true if this instruction could possibly modify memory.
static unsigned getFlagWord(unsigned Kind, unsigned NumOps)
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
Describe properties that are true of each instruction in the target description file.
static unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset)
getAM5Opc - This function encodes the addrmode5 opc field.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
static bool isVSTfixed(unsigned Opc)
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
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...
void setNodeId(int Id)
Set unique node id.
StringSwitch & Case(const char(&S)[N], const T &Value)
const SDValue & getBasePtr() const
static bool isThumb(const MCSubtargetInfo &STI)
static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx)
isUseOperandTiedToDef - Return true if the flag of the inline asm operand indicates it is an use oper...
unsigned getResNo() const
get the index which selects a specific result in the SDNode
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
static cl::opt< bool > CheckVMLxHazard("check-vmlx-hazard", cl::Hidden, cl::desc("Check fp vmla / vmls hazard at isel time"), cl::init(true))
MachineMemOperand - A description of a memory reference used in the backend.
static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC)
getFlagWordForRegClass - Augment an existing flag word returned by getFlagWord with the required regi...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const HexagonInstrInfo * TII
static SDValue getAL(SelectionDAG *CurDAG, SDLoc dl)
getAL - Returns a ARMCC::AL immediate node.
Shift and rotation operations.
std::size_t countTrailingOnes(T Value, ZeroBehavior ZB=ZB_Width)
Count the number of ones from the least significant bit to the first zero bit.
Base class for LoadSDNode and StoreSDNode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
A Use represents the edge between a Value definition and its users.
CopyToReg - This node has three operands: a chain, a register number to set to this value...
Reg
All possible values of the reg field in the ModR/M byte.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
INLINEASM - Represents an inline asm block.
EVT getVectorElementType() const
getVectorElementType - Given a vector type, return the type of each element.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool isFpMLxInstruction(unsigned Opcode) const
isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS instruction.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
static bool isVLDfixed(unsigned Opc)
Simple integer binary arithmetic operators.
static int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
EVT getMemoryVT() const
Return the type of the in-memory value.
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
static bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
Flag
These should be considered private to the implementation of the MCInstrDesc class.
SDNode * getNode() const
get the SDNode which holds the desired result
IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
A switch()-like statement whose cases are string literals.
initializer< Ty > init(const Ty &Val)
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
static unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
static int getBankedRegisterMask(StringRef RegString)
const SDValue & getOperand(unsigned i) const
static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc)
static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned &Imm)
static int getMClassRegisterSYSmValueMask(StringRef RegString)
static cl::opt< bool > DisableShifterOp("disable-shifter-op", cl::Hidden, cl::desc("Disable isel of shifter-op"), cl::init(false))
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
static void getIntOperandsFromRegisterString(StringRef RegString, SelectionDAG *CurDAG, SDLoc DL, std::vector< SDValue > &Ops)
SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT, bool isOpaque=false)
unsigned getOpcode() const
static unsigned getKind(unsigned Flags)
FunctionPass class - This class is used to implement most global optimizations.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
EVT - Extended Value Type.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc, or post-dec.
static bool isInt32Immediate(SDNode *N, unsigned &Imm)
isInt32Immediate - This method tests to see if the node is a 32-bit constant operand.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements)
getVectorVT - Returns the EVT that represents a vector NumElements in length, where each element is o...
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
REG_SEQUENCE - This variadic instruction is used to form a register that represents a consecutive seq...
unsigned getOpcode() const
Return the opcode number for this descriptor.
const SDValue & getOffset() const
static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead, const ARMSubtarget *Subtarget)
const MDOperand & getOperand(unsigned I) const
EXTRACT_SUBREG - This instruction takes two operands: a register that has subregisters, and a subregister index.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
unsigned getObjectAlignment(int ObjectIdx) const
Return the alignment of the specified stack object.
SDNode * getGluedUser() const
If this node has a glue value with a user, return the user (there is at most one).
const SDValue & getChain() const
This is an abstract virtual class for memory operations.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Represents one node in the SelectionDAG.
static bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
R Default(const T &Value) const
unsigned Log2_32(uint32_t Value)
Log2_32 - This function returns the floor log base 2 of the specified value, -1 if the value is zero...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
int64_t getSExtValue() const
op_iterator op_begin() const
static unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)
getAM3Opc - This function encodes the addrmode3 opc field.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
static bool hasRegClassConstraint(unsigned Flag, unsigned &RC)
hasRegClassConstraint - Returns true if the flag contains a register class constraint.
Bitwise operators - logical and, logical or, logical xor.
static IntegerType * getInt32Ty(LLVMContext &C)
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
unsigned getSizeInBits() const
getSizeInBits - Return the size of the specified value type in bits.
op_iterator op_end() const
FunctionPass * createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel)
createARMISelDag - This pass converts a legalized DAG into a ARM-specific DAG, ready for instruction ...
EVT getValueType() const
Return the ValueType of the referenced return value.
bool is128BitVector() const
is128BitVector - Return true if this is a 128-bit vector type.
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
const MDNode * getMD() const
const ARM::ArchExtKind Kind
C - The default llvm calling convention, compatible with C.
bool isPowerOf2_32(uint32_t Value)
isPowerOf2_32 - This function returns true if the argument is a power of two > 0. ...
StringRef - Represent a constant reference to a string, i.e.
static int getMClassFlagsMask(StringRef Flags)
unsigned getAlignment() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
bool is64BitVector() const
is64BitVector - Return true if this is a 64-bit vector type.
void setObjectAlignment(int ObjectIdx, unsigned Align)
setObjectAlignment - Change the alignment of the specified stack object.
bool hasThumb2DSP() const
std::string lower() const
MVT getSimpleVT() const
getSimpleVT - Return the SimpleValueType held in the specified simple EVT.
static unsigned getFlagWordForMatchingOp(unsigned InputFlag, unsigned MatchedOperandNo)
getFlagWordForMatchingOp - Augment an existing flag word returned by getFlagWord with information ind...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
This file describes how to lower LLVM code to machine code.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
bool empty() const
empty - Check if the string is empty.
uint64_t getZExtValue() const
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
unsigned getVectorNumElements() const
getVectorNumElements - Given a vector type, return the number of elements it contains.
This class is used to represent ISD::LOAD nodes.