39 #define DEBUG_TYPE "arm-isel"
43 cl::desc(
"Disable isel of shifter-op"),
73 StringRef getPassName()
const override {
return "ARM Instruction Selection"; }
75 void PreprocessISelDAG()
override;
79 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &dl) {
80 return CurDAG->getTargetConstant(Imm, dl,
MVT::i32);
85 bool hasNoVMLxHazardUse(
SDNode *
N)
const;
86 bool isShifterOpProfitable(
const SDValue &Shift,
90 bool CheckProfitability =
true);
92 SDValue &
B,
bool CheckProfitability =
true);
96 return SelectRegShifterOperand(N, A, B, C,
false);
101 return SelectImmShifterOperand(N, A, B,
false);
111 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
116 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
121 SelectAddrMode2Worker(N, Base, Offset, Opc);
130 Reg = CurDAG->getRegister(ARM::CPSR,
MVT::i32);
154 bool SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
SDValue &Base,
174 inline bool is_so_imm(
unsigned Imm)
const {
178 inline bool is_so_imm_not(
unsigned Imm)
const {
182 inline bool is_t2_so_imm(
unsigned Imm)
const {
186 inline bool is_t2_so_imm_not(
unsigned Imm)
const {
191 #include "ARMGenDAGISel.inc"
197 bool tryARMIndexedLoad(
SDNode *N);
198 bool tryT1IndexedLoad(
SDNode *N);
199 bool tryT2IndexedLoad(
SDNode *N);
205 void SelectVLD(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
206 const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
207 const uint16_t *QOpcodes1);
213 void SelectVST(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
214 const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
215 const uint16_t *QOpcodes1);
220 void SelectVLDSTLane(
SDNode *N,
bool IsLoad,
bool isUpdating,
221 unsigned NumVecs,
const uint16_t *DOpcodes,
222 const uint16_t *QOpcodes);
227 void SelectVLDDup(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
228 const uint16_t *DOpcodes,
229 const uint16_t *QOpcodes =
nullptr);
234 void SelectVTBL(
SDNode *N,
bool IsExt,
unsigned NumVecs,
unsigned Opc);
237 bool tryV6T2BitfieldExtractOp(
SDNode *N,
bool isSigned);
242 bool tryReadRegister(
SDNode *N);
243 bool tryWriteRegister(
SDNode *N);
245 bool tryInlineAsm(
SDNode *N);
247 void SelectConcatVector(
SDNode *N);
248 void SelectCMPZ(
SDNode *N,
bool &SwitchEQNEToPLMI);
250 bool trySMLAWSMULW(
SDNode *N);
252 void SelectCMP_SWAP(
SDNode *N);
256 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
unsigned ConstraintID,
257 std::vector<SDValue> &OutOps)
override;
276 unsigned ConstantMaterializationCost(
unsigned Val)
const;
283 bool canExtractShiftFromMul(
const SDValue &N,
unsigned MaxShift,
284 unsigned &PowerOfTwo,
SDValue &NewMulConst)
const;
296 Imm = cast<ConstantSDNode>(
N)->getZExtValue();
321 int RangeMin,
int RangeMax,
322 int &ScaledConstant) {
323 assert(Scale > 0 &&
"Invalid scale!");
331 if ((ScaledConstant % Scale) != 0)
334 ScaledConstant /= Scale;
335 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
338 void ARMDAGToDAGISel::PreprocessISelDAG() {
339 if (!Subtarget->hasV6T2Ops())
342 bool isThumb2 = Subtarget->isThumb();
344 E = CurDAG->allnodes_end();
I !=
E; ) {
361 unsigned And_imm = 0;
371 if (TZ != 1 && TZ != 2)
383 if (And_imm & (And_imm + 1))
388 unsigned Srl_imm = 0;
399 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
402 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
403 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
410 CurDAG->getConstant(Srl_imm + TZ,
SDLoc(Srl),
417 CurDAG->UpdateNodeOperands(N, N0, N1);
424 bool ARMDAGToDAGISel::hasNoVMLxHazardUse(
SDNode *N)
const {
428 if (!Subtarget->hasVMLxHazards())
439 CurDAG->getSubtarget().getInstrInfo());
466 bool ARMDAGToDAGISel::isShifterOpProfitable(
const SDValue &Shift,
469 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
475 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
478 unsigned ARMDAGToDAGISel::ConstantMaterializationCost(
unsigned Val)
const {
479 if (Subtarget->isThumb()) {
480 if (Val <= 255)
return 1;
481 if (Subtarget->hasV6T2Ops() &&
484 if (Val <= 510)
return 2;
485 if (~Val <= 255)
return 2;
490 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)
return 1;
493 if (Subtarget->useMovt(*MF))
return 2;
497 bool ARMDAGToDAGISel::canExtractShiftFromMul(
const SDValue &N,
499 unsigned &PowerOfTwo,
509 if (!MulConst)
return false;
512 if (!MulConst->
hasOneUse())
return false;
514 if (MulConstVal == 0)
return false;
517 PowerOfTwo = MaxShift;
518 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
520 if (PowerOfTwo == 0)
return false;
524 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
525 NewMulConst = CurDAG->getConstant(NewMulConstVal,
SDLoc(N),
MVT::i32);
526 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
527 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
528 return NewCost < OldCost;
531 void ARMDAGToDAGISel::replaceDAGValue(
const SDValue &N,
SDValue M) {
533 CurDAG->ReplaceAllUsesWith(N, M);
536 bool ARMDAGToDAGISel::SelectImmShifterOperand(
SDValue N,
539 bool CheckProfitability) {
546 unsigned PowerOfTwo = 0;
548 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
550 replaceDAGValue(N.
getOperand(1), NewMulConst);
566 unsigned ShImmVal = 0;
568 if (!RHS)
return false;
575 bool ARMDAGToDAGISel::SelectRegShifterOperand(
SDValue N,
579 bool CheckProfitability) {
590 unsigned ShImmVal = 0;
592 if (RHS)
return false;
595 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
603 bool ARMDAGToDAGISel::SelectAddrModeImm12(
SDValue N,
610 !CurDAG->isBaseWithConstantOffset(N)) {
613 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
614 Base = CurDAG->getTargetFrameIndex(
615 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
636 if (RHSC > -0x1000 && RHSC < 0x1000) {
639 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
640 Base = CurDAG->getTargetFrameIndex(
641 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
643 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
659 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.
hasOneUse())) {
671 unsigned ShAmt =
Log2_32(RHSC);
684 !CurDAG->isBaseWithConstantOffset(N))
691 -0x1000+1, 0x1000, RHSC))
709 ShAmt = Sh->getZExtValue();
710 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
723 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
731 ShAmt = Sh->getZExtValue();
732 if (isShifterOpProfitable(N.
getOperand(0), ShOpcVal, ShAmt)) {
748 unsigned PowerOfTwo = 0;
750 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
751 replaceDAGValue(Offset.
getOperand(1), NewMulConst);
770 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.
hasOneUse())) {
782 unsigned ShAmt =
Log2_32(RHSC);
795 !CurDAG->isBaseWithConstantOffset(N)) {
798 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
799 Base = CurDAG->getTargetFrameIndex(
800 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
807 Offset = CurDAG->getRegister(0,
MVT::i32);
818 -0x1000+1, 0x1000, RHSC)) {
821 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
822 Base = CurDAG->getTargetFrameIndex(
823 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
825 Offset = CurDAG->getRegister(0,
MVT::i32);
839 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.
hasOneUse()) {
842 Offset = CurDAG->getRegister(0,
MVT::i32);
863 ShAmt = Sh->getZExtValue();
864 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
877 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
885 ShAmt = Sh->getZExtValue();
886 if (isShifterOpProfitable(N.
getOperand(0), ShOpcVal, ShAmt)) {
908 ? cast<LoadSDNode>(Op)->getAddressingMode()
909 : cast<StoreSDNode>(
Op)->getAddressingMode();
923 ShAmt = Sh->getZExtValue();
924 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
940 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(
SDNode *Op,
SDValue N,
944 ? cast<LoadSDNode>(Op)->getAddressingMode()
945 : cast<StoreSDNode>(
Op)->getAddressingMode();
951 Offset = CurDAG->getRegister(0,
MVT::i32);
960 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(
SDNode *Op,
SDValue N,
964 ? cast<LoadSDNode>(Op)->getAddressingMode()
965 : cast<StoreSDNode>(
Op)->getAddressingMode();
970 Offset = CurDAG->getRegister(0,
MVT::i32);
980 bool ARMDAGToDAGISel::SelectAddrOffsetNone(
SDValue N,
SDValue &Base) {
985 bool ARMDAGToDAGISel::SelectAddrMode3(
SDValue N,
997 if (!CurDAG->isBaseWithConstantOffset(N)) {
1000 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1001 Base = CurDAG->getTargetFrameIndex(
1002 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1004 Offset = CurDAG->getRegister(0,
MVT::i32);
1013 -256 + 1, 256, RHSC)) {
1016 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1017 Base = CurDAG->getTargetFrameIndex(
1018 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1020 Offset = CurDAG->getRegister(0,
MVT::i32);
1039 bool ARMDAGToDAGISel::SelectAddrMode3Offset(
SDNode *Op,
SDValue N,
1043 ? cast<LoadSDNode>(Op)->getAddressingMode()
1044 : cast<StoreSDNode>(
Op)->getAddressingMode();
1049 Offset = CurDAG->getRegister(0,
MVT::i32);
1061 bool ARMDAGToDAGISel::SelectAddrMode5(
SDValue N,
1063 if (!CurDAG->isBaseWithConstantOffset(N)) {
1066 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1067 Base = CurDAG->getTargetFrameIndex(
1068 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1083 -256 + 1, 256, RHSC)) {
1086 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1087 Base = CurDAG->getTargetFrameIndex(
1088 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1111 unsigned Alignment = 0;
1113 MemSDNode *MemN = cast<MemSDNode>(Parent);
1115 if (isa<LSBaseSDNode>(MemN) ||
1123 if (MMOAlign >= MemSize && MemSize > 1)
1124 Alignment = MemSize;
1132 Align = CurDAG->getTargetConstant(Alignment,
SDLoc(N),
MVT::i32);
1136 bool ARMDAGToDAGISel::SelectAddrMode6Offset(
SDNode *Op,
SDValue N,
1145 Offset = CurDAG->getRegister(0,
MVT::i32);
1150 bool ARMDAGToDAGISel::SelectAddrModePC(
SDValue N,
1155 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1168 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(
SDValue N,
1185 ARMDAGToDAGISel::SelectThumbAddrModeImm5S(
SDValue N,
unsigned Scale,
1187 if (!CurDAG->isBaseWithConstantOffset(N)) {
1208 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1217 ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(
SDValue N,
SDValue &Base,
1219 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
1223 ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(
SDValue N,
SDValue &Base,
1225 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
1229 ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(
SDValue N,
SDValue &Base,
1231 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
1234 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(
SDValue N,
1237 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1243 Base = CurDAG->getTargetFrameIndex(
1244 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1249 if (!CurDAG->isBaseWithConstantOffset(N))
1254 (LHSR && LHSR->
getReg() == ARM::SP)) {
1260 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1266 Base = CurDAG->getTargetFrameIndex(
1267 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1269 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1283 bool ARMDAGToDAGISel::SelectT2AddrModeImm12(
SDValue N,
1289 !CurDAG->isBaseWithConstantOffset(N)) {
1292 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
1293 Base = CurDAG->getTargetFrameIndex(
1294 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1313 if (SelectT2AddrModeImm8(N, Base, OffImm))
1321 if (RHSC >= 0 && RHSC < 0x1000) {
1324 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1325 Base = CurDAG->getTargetFrameIndex(
1326 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1328 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1339 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(
SDValue N,
1343 !CurDAG->isBaseWithConstantOffset(N))
1351 if ((RHSC >= -255) && (RHSC < 0)) {
1354 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1355 Base = CurDAG->getTargetFrameIndex(
1356 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1358 OffImm = CurDAG->getTargetConstant(RHSC,
SDLoc(N),
MVT::i32);
1366 bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(
SDNode *Op,
SDValue N,
1370 ? cast<LoadSDNode>(Op)->getAddressingMode()
1371 : cast<StoreSDNode>(
Op)->getAddressingMode();
1383 bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(
SDValue N,
1393 if (RHSC >= 0 && RHSC < 0x1000)
1395 else if (RHSC < 0 && RHSC >= -255)
1416 ShAmt = Sh->getZExtValue();
1417 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1428 unsigned PowerOfTwo = 0;
1430 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1431 replaceDAGValue(OffReg.
getOperand(1), NewMulConst);
1436 ShImm = CurDAG->getTargetConstant(ShAmt,
SDLoc(N),
MVT::i32);
1441 bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(
SDValue N,
SDValue &Base,
1456 if (RHSC > 1020 || RHSC % 4 != 0)
1461 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1462 Base = CurDAG->getTargetFrameIndex(
1463 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1466 OffImm = CurDAG->getTargetConstant(RHSC/4,
SDLoc(N),
MVT::i32);
1477 void ARMDAGToDAGISel::transferMemOperands(
SDNode *N,
SDNode *Result) {
1479 MemOp[0] = cast<MemSDNode>(
N)->getMemOperand();
1480 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1483 bool ARMDAGToDAGISel::tryARMIndexedLoad(
SDNode *N) {
1492 unsigned Opcode = 0;
1494 if (LoadedVT ==
MVT::i32 && isPre &&
1496 Opcode = ARM::LDR_PRE_IMM;
1498 }
else if (LoadedVT ==
MVT::i32 && !isPre &&
1500 Opcode = ARM::LDR_POST_IMM;
1504 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
1511 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1512 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
1517 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1523 Opcode = ARM::LDRB_PRE_IMM;
1524 }
else if (!isPre &&
1527 Opcode = ARM::LDRB_POST_IMM;
1528 }
else if (SelectAddrMode2OffsetReg(N, LD->
getOffset(),
Offset, AMOpc)) {
1530 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
1536 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1540 CurDAG->getRegister(0,
MVT::i32), Chain };
1543 transferMemOperands(N, New);
1544 ReplaceNode(N, New);
1550 CurDAG->getRegister(0,
MVT::i32), Chain };
1553 transferMemOperands(N, New);
1554 ReplaceNode(N, New);
1562 bool ARMDAGToDAGISel::tryT1IndexedLoad(
SDNode *N) {
1567 LoadedVT.getSimpleVT().SimpleTy !=
MVT::i32)
1571 if (!COffs || COffs->getZExtValue() != 4)
1581 CurDAG->getRegister(0,
MVT::i32), Chain };
1584 transferMemOperands(N, New);
1585 ReplaceNode(N, New);
1589 bool ARMDAGToDAGISel::tryT2IndexedLoad(
SDNode *N) {
1599 unsigned Opcode = 0;
1604 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1608 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1610 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
1615 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1617 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
1629 CurDAG->getRegister(0,
MVT::i32), Chain };
1632 transferMemOperands(N, New);
1633 ReplaceNode(N, New);
1644 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl,
MVT::i32);
1645 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl,
MVT::i32);
1646 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl,
MVT::i32);
1647 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1648 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1655 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl,
MVT::i32);
1656 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl,
MVT::i32);
1657 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl,
MVT::i32);
1658 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1659 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1665 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1667 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl,
MVT::i32);
1668 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl,
MVT::i32);
1669 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1670 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1676 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1678 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl,
MVT::i32);
1679 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl,
MVT::i32);
1680 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1681 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1689 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl,
MVT::i32);
1690 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl,
MVT::i32);
1691 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl,
MVT::i32);
1692 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl,
MVT::i32);
1693 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl,
MVT::i32);
1694 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1695 V2, SubReg2, V3, SubReg3 };
1696 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1703 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1705 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl,
MVT::i32);
1706 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl,
MVT::i32);
1707 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl,
MVT::i32);
1708 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl,
MVT::i32);
1709 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1710 V2, SubReg2, V3, SubReg3 };
1711 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1718 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1720 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl,
MVT::i32);
1721 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl,
MVT::i32);
1722 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl,
MVT::i32);
1723 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl,
MVT::i32);
1724 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1725 V2, SubReg2, V3, SubReg3 };
1726 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
1733 unsigned NumVecs,
bool is64BitVector) {
1734 unsigned NumRegs = NumVecs;
1735 if (!is64BitVector && NumVecs < 3)
1738 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
1739 if (Alignment >= 32 && NumRegs == 4)
1741 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1743 else if (Alignment >= 8)
1748 return CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
1754 default:
return false;
1755 case ARM::VLD1d8wb_fixed :
return true;
1756 case ARM::VLD1d16wb_fixed :
return true;
1757 case ARM::VLD1d64Qwb_fixed :
return true;
1758 case ARM::VLD1d32wb_fixed :
return true;
1759 case ARM::VLD1d64wb_fixed :
return true;
1760 case ARM::VLD1d64TPseudoWB_fixed :
return true;
1761 case ARM::VLD1d64QPseudoWB_fixed :
return true;
1762 case ARM::VLD1q8wb_fixed :
return true;
1763 case ARM::VLD1q16wb_fixed :
return true;
1764 case ARM::VLD1q32wb_fixed :
return true;
1765 case ARM::VLD1q64wb_fixed :
return true;
1766 case ARM::VLD1DUPd8wb_fixed :
return true;
1767 case ARM::VLD1DUPd16wb_fixed :
return true;
1768 case ARM::VLD1DUPd32wb_fixed :
return true;
1769 case ARM::VLD1DUPq8wb_fixed :
return true;
1770 case ARM::VLD1DUPq16wb_fixed :
return true;
1771 case ARM::VLD1DUPq32wb_fixed :
return true;
1772 case ARM::VLD2d8wb_fixed :
return true;
1773 case ARM::VLD2d16wb_fixed :
return true;
1774 case ARM::VLD2d32wb_fixed :
return true;
1775 case ARM::VLD2q8PseudoWB_fixed :
return true;
1776 case ARM::VLD2q16PseudoWB_fixed :
return true;
1777 case ARM::VLD2q32PseudoWB_fixed :
return true;
1778 case ARM::VLD2DUPd8wb_fixed :
return true;
1779 case ARM::VLD2DUPd16wb_fixed :
return true;
1780 case ARM::VLD2DUPd32wb_fixed :
return true;
1787 default:
return false;
1788 case ARM::VST1d8wb_fixed :
return true;
1789 case ARM::VST1d16wb_fixed :
return true;
1790 case ARM::VST1d32wb_fixed :
return true;
1791 case ARM::VST1d64wb_fixed :
return true;
1792 case ARM::VST1q8wb_fixed :
return true;
1793 case ARM::VST1q16wb_fixed :
return true;
1794 case ARM::VST1q32wb_fixed :
return true;
1795 case ARM::VST1q64wb_fixed :
return true;
1796 case ARM::VST1d64TPseudoWB_fixed :
return true;
1797 case ARM::VST1d64QPseudoWB_fixed :
return true;
1798 case ARM::VST2d8wb_fixed :
return true;
1799 case ARM::VST2d16wb_fixed :
return true;
1800 case ARM::VST2d32wb_fixed :
return true;
1801 case ARM::VST2q8PseudoWB_fixed :
return true;
1802 case ARM::VST2q16PseudoWB_fixed :
return true;
1803 case ARM::VST2q32PseudoWB_fixed :
return true;
1811 &&
"Incorrect fixed stride updating instruction.");
1814 case ARM::VLD1d8wb_fixed:
return ARM::VLD1d8wb_register;
1815 case ARM::VLD1d16wb_fixed:
return ARM::VLD1d16wb_register;
1816 case ARM::VLD1d32wb_fixed:
return ARM::VLD1d32wb_register;
1817 case ARM::VLD1d64wb_fixed:
return ARM::VLD1d64wb_register;
1818 case ARM::VLD1q8wb_fixed:
return ARM::VLD1q8wb_register;
1819 case ARM::VLD1q16wb_fixed:
return ARM::VLD1q16wb_register;
1820 case ARM::VLD1q32wb_fixed:
return ARM::VLD1q32wb_register;
1821 case ARM::VLD1q64wb_fixed:
return ARM::VLD1q64wb_register;
1822 case ARM::VLD1d64Twb_fixed:
return ARM::VLD1d64Twb_register;
1823 case ARM::VLD1d64Qwb_fixed:
return ARM::VLD1d64Qwb_register;
1824 case ARM::VLD1d64TPseudoWB_fixed:
return ARM::VLD1d64TPseudoWB_register;
1825 case ARM::VLD1d64QPseudoWB_fixed:
return ARM::VLD1d64QPseudoWB_register;
1826 case ARM::VLD1DUPd8wb_fixed :
return ARM::VLD1DUPd8wb_register;
1827 case ARM::VLD1DUPd16wb_fixed :
return ARM::VLD1DUPd16wb_register;
1828 case ARM::VLD1DUPd32wb_fixed :
return ARM::VLD1DUPd32wb_register;
1829 case ARM::VLD1DUPq8wb_fixed :
return ARM::VLD1DUPq8wb_register;
1830 case ARM::VLD1DUPq16wb_fixed :
return ARM::VLD1DUPq16wb_register;
1831 case ARM::VLD1DUPq32wb_fixed :
return ARM::VLD1DUPq32wb_register;
1833 case ARM::VST1d8wb_fixed:
return ARM::VST1d8wb_register;
1834 case ARM::VST1d16wb_fixed:
return ARM::VST1d16wb_register;
1835 case ARM::VST1d32wb_fixed:
return ARM::VST1d32wb_register;
1836 case ARM::VST1d64wb_fixed:
return ARM::VST1d64wb_register;
1837 case ARM::VST1q8wb_fixed:
return ARM::VST1q8wb_register;
1838 case ARM::VST1q16wb_fixed:
return ARM::VST1q16wb_register;
1839 case ARM::VST1q32wb_fixed:
return ARM::VST1q32wb_register;
1840 case ARM::VST1q64wb_fixed:
return ARM::VST1q64wb_register;
1841 case ARM::VST1d64TPseudoWB_fixed:
return ARM::VST1d64TPseudoWB_register;
1842 case ARM::VST1d64QPseudoWB_fixed:
return ARM::VST1d64QPseudoWB_register;
1844 case ARM::VLD2d8wb_fixed:
return ARM::VLD2d8wb_register;
1845 case ARM::VLD2d16wb_fixed:
return ARM::VLD2d16wb_register;
1846 case ARM::VLD2d32wb_fixed:
return ARM::VLD2d32wb_register;
1847 case ARM::VLD2q8PseudoWB_fixed:
return ARM::VLD2q8PseudoWB_register;
1848 case ARM::VLD2q16PseudoWB_fixed:
return ARM::VLD2q16PseudoWB_register;
1849 case ARM::VLD2q32PseudoWB_fixed:
return ARM::VLD2q32PseudoWB_register;
1851 case ARM::VST2d8wb_fixed:
return ARM::VST2d8wb_register;
1852 case ARM::VST2d16wb_fixed:
return ARM::VST2d16wb_register;
1853 case ARM::VST2d32wb_fixed:
return ARM::VST2d32wb_register;
1854 case ARM::VST2q8PseudoWB_fixed:
return ARM::VST2q8PseudoWB_register;
1855 case ARM::VST2q16PseudoWB_fixed:
return ARM::VST2q16PseudoWB_register;
1856 case ARM::VST2q32PseudoWB_fixed:
return ARM::VST2q32PseudoWB_register;
1858 case ARM::VLD2DUPd8wb_fixed:
return ARM::VLD2DUPd8wb_register;
1859 case ARM::VLD2DUPd16wb_fixed:
return ARM::VLD2DUPd16wb_register;
1860 case ARM::VLD2DUPd32wb_fixed:
return ARM::VLD2DUPd32wb_register;
1865 void ARMDAGToDAGISel::SelectVLD(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
1866 const uint16_t *DOpcodes,
1867 const uint16_t *QOpcodes0,
1868 const uint16_t *QOpcodes1) {
1869 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLD NumVecs out-of-range");
1873 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1874 if (!SelectAddrMode6(N, N->
getOperand(AddrOpIdx), MemAddr, Align))
1880 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
1898 assert(NumVecs == 1 &&
"v2i64 type only supported for VLD1");
1906 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1911 std::vector<EVT> ResTys;
1912 ResTys.push_back(ResTy);
1923 if (is64BitVector || NumVecs <= 2) {
1924 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
1932 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.
getNode()))
1937 !isa<ConstantSDNode>(Inc.
getNode()))
1943 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
1953 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1954 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
1955 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1965 "only constant post-increment update allowed for VLD3/4");
1973 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
1978 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
1979 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1982 ReplaceNode(N, VLd);
1988 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1989 ARM::qsub_3 == ARM::qsub_0 + 3,
1990 "Unexpected subreg numbering");
1991 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1992 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
1994 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1998 CurDAG->RemoveDeadNode(N);
2001 void ARMDAGToDAGISel::SelectVST(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
2002 const uint16_t *DOpcodes,
2003 const uint16_t *QOpcodes0,
2004 const uint16_t *QOpcodes1) {
2005 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VST NumVecs out-of-range");
2009 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2010 unsigned Vec0Idx = 3;
2011 if (!SelectAddrMode6(N, N->
getOperand(AddrOpIdx), MemAddr, Align))
2015 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
2020 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
2038 assert(NumVecs == 1 &&
"v2i64 type only supported for VST1");
2042 std::vector<EVT> ResTys;
2052 if (is64BitVector || NumVecs <= 2) {
2056 }
else if (is64BitVector) {
2067 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
2078 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2086 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.
getNode()))
2090 if (!isa<ConstantSDNode>(Inc.
getNode()))
2099 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2102 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2104 ReplaceNode(N, VSt);
2116 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2122 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2123 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2126 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
2135 "only constant post-increment update allowed for VST3/4");
2143 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
2145 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2146 ReplaceNode(N, VStB);
2149 void ARMDAGToDAGISel::SelectVLDSTLane(
SDNode *N,
bool IsLoad,
bool isUpdating,
2151 const uint16_t *DOpcodes,
2152 const uint16_t *QOpcodes) {
2153 assert(NumVecs >=2 && NumVecs <= 4 &&
"VLDSTLane NumVecs out-of-range");
2157 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2158 unsigned Vec0Idx = 3;
2159 if (!SelectAddrMode6(N, N->
getOperand(AddrOpIdx), MemAddr, Align))
2163 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
2167 cast<ConstantSDNode>(N->
getOperand(Vec0Idx + NumVecs))->getZExtValue();
2171 unsigned Alignment = 0;
2173 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2175 if (Alignment > NumBytes)
2176 Alignment = NumBytes;
2177 if (Alignment < 8 && Alignment < NumBytes)
2180 Alignment = (Alignment & -Alignment);
2184 Align = CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
2200 std::vector<EVT> ResTys;
2202 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2234 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2247 unsigned Opc = (is64BitVector ? DOpcodes[
OpcodeIndex] :
2249 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2250 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
2252 ReplaceNode(N, VLdLn);
2258 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2259 ARM::qsub_3 == ARM::qsub_0 + 3,
2260 "Unexpected subreg numbering");
2261 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2262 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2264 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2268 CurDAG->RemoveDeadNode(N);
2271 void ARMDAGToDAGISel::SelectVLDDup(
SDNode *N,
bool isUpdating,
unsigned NumVecs,
2272 const uint16_t *DOpcodes,
2273 const uint16_t *QOpcodes) {
2274 assert(NumVecs >= 1 && NumVecs <= 4 &&
"VLDDup NumVecs out-of-range");
2278 if (!SelectAddrMode6(N, N->
getOperand(1), MemAddr, Align))
2282 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
2287 unsigned Alignment = 0;
2289 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2291 if (Alignment > NumBytes)
2292 Alignment = NumBytes;
2293 if (Alignment < 8 && Alignment < NumBytes)
2296 Alignment = (Alignment & -Alignment);
2300 Align = CurDAG->getTargetConstant(Alignment, dl,
MVT::i32);
2305 case MVT::v8i8: Opc = DOpcodes[0];
break;
2324 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.
getNode()))
2326 if (!isa<ConstantSDNode>(Inc.
getNode()))
2329 else if (NumVecs > 2)
2336 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2337 std::vector<EVT> ResTys;
2342 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2343 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
2350 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7,
"Unexpected subreg numbering");
2351 unsigned SubIdx = ARM::dsub_0;
2352 for (
unsigned Vec = 0; Vec < NumVecs; ++Vec)
2354 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2359 CurDAG->RemoveDeadNode(N);
2362 void ARMDAGToDAGISel::SelectVTBL(
SDNode *N,
bool IsExt,
unsigned NumVecs,
2364 assert(NumVecs >= 2 && NumVecs <= 4 &&
"VTBL NumVecs out-of-range");
2367 unsigned FirstTblReg = IsExt ? 2 : 1;
2380 ?
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2392 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2395 bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(
SDNode *N,
bool isSigned) {
2396 if (!Subtarget->hasV6T2Ops())
2399 unsigned Opc = isSigned
2400 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
2401 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2405 unsigned And_imm = 0;
2410 if (And_imm & (And_imm + 1))
2413 unsigned Srl_imm = 0;
2416 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
2420 unsigned LSB = Srl_imm;
2426 if (Subtarget->isThumb()) {
2427 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2429 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2430 getAL(CurDAG, dl), Reg0, Reg0 };
2431 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2441 getAL(CurDAG, dl), Reg0, Reg0 };
2442 CurDAG->SelectNodeTo(N, ARM::MOVsi,
MVT::i32, Ops);
2447 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2448 CurDAG->getTargetConstant(Width, dl,
MVT::i32),
2449 getAL(CurDAG, dl), Reg0 };
2450 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2458 unsigned Shl_imm = 0;
2460 assert(Shl_imm > 0 && Shl_imm < 32 &&
"bad amount in shift node!");
2461 unsigned Srl_imm = 0;
2463 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
2465 unsigned Width = 32 - Srl_imm - 1;
2466 int LSB = Srl_imm - Shl_imm;
2471 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2472 CurDAG->getTargetConstant(Width, dl,
MVT::i32),
2473 getAL(CurDAG, dl), Reg0 };
2474 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2482 unsigned Srl_imm = 0;
2486 assert(Srl_imm > 0 && Srl_imm < 32 &&
"bad amount in shift node!");
2489 unsigned Width = MSB - LSB;
2492 CurDAG->getTargetConstant(Srl_imm, dl,
MVT::i32),
2493 CurDAG->getTargetConstant(Width, dl,
MVT::i32),
2494 getAL(CurDAG, dl), Reg0 };
2495 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2501 unsigned Width = cast<VTSDNode>(N->
getOperand(1))->getVT().getSizeInBits();
2507 if (LSB + Width > 32)
2512 CurDAG->getTargetConstant(LSB, dl,
MVT::i32),
2513 CurDAG->getTargetConstant(Width - 1, dl,
MVT::i32),
2514 getAL(CurDAG, dl), Reg0 };
2515 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2532 bool ARMDAGToDAGISel::tryABSOp(
SDNode *N){
2537 if (Subtarget->isThumb1Only())
2551 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2552 XType.isInteger() && SRAConstant !=
nullptr &&
2554 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS :
ARM::ABS;
2555 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2572 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2593 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2597 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2603 SDValue &Src1,
bool Accumulate) {
2621 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->
getZExtValue() != 16 ||
2622 SHLSrc1->getZExtValue() != 16)
2654 bool ARMDAGToDAGISel::trySMLAWSMULW(
SDNode *N) {
2655 if (!Subtarget->hasV6Ops() ||
2656 (Subtarget->isThumb() && !Subtarget->hasThumb2()))
2681 CurDAG->getRegister(0,
MVT::i32) };
2691 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2698 void ARMDAGToDAGISel::SelectCMP_SWAP(
SDNode *N) {
2700 EVT MemTy = cast<MemSDNode>(
N)->getMemoryVT();
2702 Opcode = ARM::CMP_SWAP_8;
2704 Opcode = ARM::CMP_SWAP_16;
2706 Opcode = ARM::CMP_SWAP_32;
2712 SDNode *CmpSwap = CurDAG->getMachineNode(
2717 MemOp[0] = cast<MemSDNode>(
N)->getMemOperand();
2718 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2722 CurDAG->RemoveDeadNode(N);
2725 void ARMDAGToDAGISel::SelectConcatVector(
SDNode *N) {
2740 return std::make_pair(FirstOne, LastOne);
2743 void ARMDAGToDAGISel::SelectCMPZ(
SDNode *N,
bool &SwitchEQNEToPLMI) {
2745 SwitchEQNEToPLMI =
false;
2747 if (!Subtarget->isThumb())
2758 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() ||
2774 auto EmitShift = [&](
unsigned Opc,
SDValue Src,
unsigned Imm) ->
SDNode* {
2775 if (Subtarget->isThumb2()) {
2776 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
2779 CurDAG->getRegister(0,
MVT::i32) };
2780 return CurDAG->getMachineNode(Opc, dl,
MVT::i32, Ops);
2783 CurDAG->getTargetConstant(Imm, dl,
MVT::i32),
2785 return CurDAG->getMachineNode(Opc, dl,
MVT::i32, Ops);
2789 if (Range->second == 0) {
2791 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2792 ReplaceNode(And.
getNode(), NewN);
2793 }
else if (Range->first == 31) {
2795 NewN = EmitShift(ARM::tLSRri, X, Range->second);
2796 ReplaceNode(And.
getNode(), NewN);
2797 }
else if (Range->first == Range->second) {
2800 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2801 ReplaceNode(And.
getNode(), NewN);
2803 SwitchEQNEToPLMI =
true;
2804 }
else if (!Subtarget->hasV6T2Ops()) {
2807 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2808 NewN = EmitShift(ARM::tLSRri,
SDValue(NewN, 0),
2809 Range->second + (31 - Range->first));
2810 ReplaceNode(And.
getNode(), NewN);
2827 if (trySMLAWSMULW(N))
2831 if (tryWriteRegister(N))
2835 if (tryReadRegister(N))
2839 if (tryInlineAsm(N))
2849 unsigned Val = cast<ConstantSDNode>(
N)->getZExtValue();
2851 if (ConstantMaterializationCost(Val) > 2) {
2852 SDValue CPIdx = CurDAG->getTargetConstantPool(
2854 TLI->getPointerTy(CurDAG->getDataLayout()));
2857 if (Subtarget->isThumb()) {
2860 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
2866 CurDAG->getTargetConstant(0, dl,
MVT::i32),
2869 CurDAG->getEntryNode()
2874 ReplaceNode(N, ResNode);
2883 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
2884 SDValue TFI = CurDAG->getTargetFrameIndex(
2885 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
2886 if (Subtarget->isThumb1Only()) {
2892 CurDAG->SelectNodeTo(N, ARM::tADDframe,
MVT::i32, TFI,
2893 CurDAG->getTargetConstant(0, dl,
MVT::i32));
2896 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2897 ARM::t2ADDri : ARM::ADDri);
2900 CurDAG->getRegister(0,
MVT::i32) };
2901 CurDAG->SelectNodeTo(N, Opc,
MVT::i32, Ops);
2906 if (tryV6T2BitfieldExtractOp(N,
false))
2911 if (tryV6T2BitfieldExtractOp(N,
true))
2915 if (Subtarget->isThumb1Only())
2918 unsigned RHSV =
C->getZExtValue();
2921 unsigned ShImm =
Log2_32(RHSV-1);
2928 if (Subtarget->isThumb()) {
2929 SDValue Ops[] = { V, V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
2930 CurDAG->SelectNodeTo(N, ARM::t2ADDrs,
MVT::i32, Ops);
2933 SDValue Ops[] = { V, V, Reg0, ShImmOp,
getAL(CurDAG, dl), Reg0,
2935 CurDAG->SelectNodeTo(N, ARM::ADDrsi,
MVT::i32, Ops);
2940 unsigned ShImm =
Log2_32(RHSV+1);
2947 if (Subtarget->isThumb()) {
2948 SDValue Ops[] = { V, V, ShImmOp,
getAL(CurDAG, dl), Reg0, Reg0 };
2949 CurDAG->SelectNodeTo(N, ARM::t2RSBrs,
MVT::i32, Ops);
2952 SDValue Ops[] = { V, V, Reg0, ShImmOp,
getAL(CurDAG, dl), Reg0,
2954 CurDAG->SelectNodeTo(N, ARM::RSBrsi,
MVT::i32, Ops);
2962 if (tryV6T2BitfieldExtractOp(N,
false))
2969 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2976 bool PreferImmediateEncoding =
2977 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2978 if (!PreferImmediateEncoding &&
2979 ConstantMaterializationCost(Imm) >
2980 ConstantMaterializationCost(~Imm)) {
2984 CurDAG->getConstant(~N1C->getZExtValue(), dl,
MVT::i32);
2990 if (!Subtarget->hasThumb2()) {
2994 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl,
MVT::i32, Ops));
3001 CurDAG->getMachineNode(ARM::t2BICrr, dl,
MVT::i32, Ops));
3015 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
3017 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
3031 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
3032 (N1CVal & 0xffffU) == 0xffffU &&
3033 (N2CVal & 0xffffU) == 0x0U) {
3034 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
3038 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
3048 CurDAG->getRegister(0,
MVT::i32)));
3051 if (Subtarget->isThumb1Only())
3053 if (Subtarget->isThumb()) {
3062 CurDAG->getRegister(0,
MVT::i32) };
3063 ReplaceNode(N, CurDAG->getMachineNode(
3064 Subtarget->hasV6Ops() ?
ARM::UMULL : ARM::UMULLv5, dl,
3070 if (Subtarget->isThumb1Only())
3072 if (Subtarget->isThumb()) {
3081 CurDAG->getRegister(0,
MVT::i32) };
3082 ReplaceNode(N, CurDAG->getMachineNode(
3083 Subtarget->hasV6Ops() ?
ARM::SMULL : ARM::SMULLv5, dl,
3089 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL :
ARM::UMAAL;
3093 CurDAG->getRegister(0,
MVT::i32) };
3100 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() &&
3112 if (Op0 && Op1 && Op0->
getZExtValue() == 0 && Op1->getZExtValue() == 0)
3122 CurDAG->getRegister(0,
MVT::i32) };
3123 unsigned opc = Subtarget->isThumb() ? ARM::t2UMAAL :
ARM::UMAAL;
3130 if (Subtarget->isThumb()) {
3141 CurDAG->getRegister(0,
MVT::i32) };
3142 ReplaceNode(N, CurDAG->getMachineNode(
3143 Subtarget->hasV6Ops() ?
ARM::UMLAL : ARM::UMLALv5, dl,
3149 if (Subtarget->isThumb()) {
3160 CurDAG->getRegister(0,
MVT::i32) };
3161 ReplaceNode(N, CurDAG->getMachineNode(
3162 Subtarget->hasV6Ops() ?
ARM::SMLAL : ARM::SMLALv5, dl,
3168 if (!Subtarget->hasV6Ops())
3177 if (Subtarget->isThumb())
3178 assert(Subtarget->hasThumb2() &&
3179 "This pattern should not be generated for Thumb");
3185 if (!Zero || Zero->getZExtValue() != 0 ||
3191 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
3194 CurDAG->getRegister(0,
MVT::i32) };
3195 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl,
MVT::i32, Ops));
3199 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
3200 if (tryT2IndexedLoad(N))
3202 }
else if (Subtarget->isThumb()) {
3203 if (tryT1IndexedLoad(N))
3205 }
else if (tryARMIndexedLoad(N))
3223 unsigned Opc = Subtarget->isThumb() ?
3224 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
3234 unsigned CC = (
unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
3237 bool SwitchEQNEToPLMI;
3238 SelectCMPZ(InFlag.
getNode(), SwitchEQNEToPLMI);
3241 if (SwitchEQNEToPLMI) {
3255 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
3261 ReplaceUses(
SDValue(N, 1), InFlag);
3265 CurDAG->RemoveDeadNode(N);
3276 if (
C &&
C->getSExtValue() < 0 && Subtarget->isThumb()) {
3277 int64_t Addend = -
C->getSExtValue();
3284 if (Subtarget->isThumb2() && Addend < 1<<8) {
3287 CurDAG->getRegister(0,
MVT::i32) };
3288 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl,
MVT::i32, Ops);
3289 }
else if (!Subtarget->isThumb2() && Addend < 1<<8) {
3292 CurDAG->getTargetConstant(Addend, dl,
MVT::i32),
3294 Add = CurDAG->getMachineNode(ARM::tADDi8, dl,
MVT::i32, Ops);
3295 }
else if (!Subtarget->isThumb2() && Addend < 1<<3) {
3297 CurDAG->getTargetConstant(Addend, dl,
MVT::i32),
3299 Add = CurDAG->getMachineNode(ARM::tADDi3, dl,
MVT::i32, Ops);
3314 bool SwitchEQNEToPLMI;
3315 SelectCMPZ(InFlag.
getNode(), SwitchEQNEToPLMI);
3317 if (SwitchEQNEToPLMI) {
3347 case MVT::v8i8: Opc = ARM::VZIPd8;
break;
3360 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3368 case MVT::v8i8: Opc = ARM::VUZPd8;
break;
3381 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3389 case MVT::v8i8: Opc = ARM::VTRNd8;
break;
3401 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3409 assert(NumElts == 2 &&
"unexpected type for BUILD_VECTOR");
3420 assert(NumElts == 4 &&
"unexpected type for BUILD_VECTOR");
3428 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3430 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3432 SelectVLDDup(N,
false, 1, DOpcodes, QOpcodes);
3437 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3439 SelectVLDDup(N,
false, 2, Opcodes);
3444 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3445 ARM::VLD3DUPd16Pseudo,
3446 ARM::VLD3DUPd32Pseudo };
3447 SelectVLDDup(N,
false, 3, Opcodes);
3452 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3453 ARM::VLD4DUPd16Pseudo,
3454 ARM::VLD4DUPd32Pseudo };
3455 SelectVLDDup(N,
false, 4, Opcodes);
3460 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3461 ARM::VLD1DUPd16wb_fixed,
3462 ARM::VLD1DUPd32wb_fixed };
3463 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3464 ARM::VLD1DUPq16wb_fixed,
3465 ARM::VLD1DUPq32wb_fixed };
3466 SelectVLDDup(N,
true, 1, DOpcodes, QOpcodes);
3471 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3472 ARM::VLD2DUPd16wb_fixed,
3473 ARM::VLD2DUPd32wb_fixed };
3474 SelectVLDDup(N,
true, 2, Opcodes);
3479 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3480 ARM::VLD3DUPd16Pseudo_UPD,
3481 ARM::VLD3DUPd32Pseudo_UPD };
3482 SelectVLDDup(N,
true, 3, Opcodes);
3487 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3488 ARM::VLD4DUPd16Pseudo_UPD,
3489 ARM::VLD4DUPd32Pseudo_UPD };
3490 SelectVLDDup(N,
true, 4, Opcodes);
3495 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3496 ARM::VLD1d16wb_fixed,
3497 ARM::VLD1d32wb_fixed,
3498 ARM::VLD1d64wb_fixed };
3499 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3500 ARM::VLD1q16wb_fixed,
3501 ARM::VLD1q32wb_fixed,
3502 ARM::VLD1q64wb_fixed };
3503 SelectVLD(N,
true, 1, DOpcodes, QOpcodes,
nullptr);
3508 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3509 ARM::VLD2d16wb_fixed,
3510 ARM::VLD2d32wb_fixed,
3511 ARM::VLD1q64wb_fixed};
3512 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3513 ARM::VLD2q16PseudoWB_fixed,
3514 ARM::VLD2q32PseudoWB_fixed };
3515 SelectVLD(N,
true, 2, DOpcodes, QOpcodes,
nullptr);
3520 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3521 ARM::VLD3d16Pseudo_UPD,
3522 ARM::VLD3d32Pseudo_UPD,
3523 ARM::VLD1d64TPseudoWB_fixed};
3524 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3525 ARM::VLD3q16Pseudo_UPD,
3526 ARM::VLD3q32Pseudo_UPD };
3527 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3528 ARM::VLD3q16oddPseudo_UPD,
3529 ARM::VLD3q32oddPseudo_UPD };
3530 SelectVLD(N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3535 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3536 ARM::VLD4d16Pseudo_UPD,
3537 ARM::VLD4d32Pseudo_UPD,
3538 ARM::VLD1d64QPseudoWB_fixed};
3539 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3540 ARM::VLD4q16Pseudo_UPD,
3541 ARM::VLD4q32Pseudo_UPD };
3542 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3543 ARM::VLD4q16oddPseudo_UPD,
3544 ARM::VLD4q32oddPseudo_UPD };
3545 SelectVLD(N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3550 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3551 ARM::VLD2LNd16Pseudo_UPD,
3552 ARM::VLD2LNd32Pseudo_UPD };
3553 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3554 ARM::VLD2LNq32Pseudo_UPD };
3555 SelectVLDSTLane(N,
true,
true, 2, DOpcodes, QOpcodes);
3560 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3561 ARM::VLD3LNd16Pseudo_UPD,
3562 ARM::VLD3LNd32Pseudo_UPD };
3563 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3564 ARM::VLD3LNq32Pseudo_UPD };
3565 SelectVLDSTLane(N,
true,
true, 3, DOpcodes, QOpcodes);
3570 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3571 ARM::VLD4LNd16Pseudo_UPD,
3572 ARM::VLD4LNd32Pseudo_UPD };
3573 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3574 ARM::VLD4LNq32Pseudo_UPD };
3575 SelectVLDSTLane(N,
true,
true, 4, DOpcodes, QOpcodes);
3580 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3581 ARM::VST1d16wb_fixed,
3582 ARM::VST1d32wb_fixed,
3583 ARM::VST1d64wb_fixed };
3584 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3585 ARM::VST1q16wb_fixed,
3586 ARM::VST1q32wb_fixed,
3587 ARM::VST1q64wb_fixed };
3588 SelectVST(N,
true, 1, DOpcodes, QOpcodes,
nullptr);
3593 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3594 ARM::VST2d16wb_fixed,
3595 ARM::VST2d32wb_fixed,
3596 ARM::VST1q64wb_fixed};
3597 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3598 ARM::VST2q16PseudoWB_fixed,
3599 ARM::VST2q32PseudoWB_fixed };
3600 SelectVST(N,
true, 2, DOpcodes, QOpcodes,
nullptr);
3605 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3606 ARM::VST3d16Pseudo_UPD,
3607 ARM::VST3d32Pseudo_UPD,
3608 ARM::VST1d64TPseudoWB_fixed};
3609 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3610 ARM::VST3q16Pseudo_UPD,
3611 ARM::VST3q32Pseudo_UPD };
3612 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3613 ARM::VST3q16oddPseudo_UPD,
3614 ARM::VST3q32oddPseudo_UPD };
3615 SelectVST(N,
true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3620 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3621 ARM::VST4d16Pseudo_UPD,
3622 ARM::VST4d32Pseudo_UPD,
3623 ARM::VST1d64QPseudoWB_fixed};
3624 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3625 ARM::VST4q16Pseudo_UPD,
3626 ARM::VST4q32Pseudo_UPD };
3627 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3628 ARM::VST4q16oddPseudo_UPD,
3629 ARM::VST4q32oddPseudo_UPD };
3630 SelectVST(N,
true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3635 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3636 ARM::VST2LNd16Pseudo_UPD,
3637 ARM::VST2LNd32Pseudo_UPD };
3638 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3639 ARM::VST2LNq32Pseudo_UPD };
3640 SelectVLDSTLane(N,
false,
true, 2, DOpcodes, QOpcodes);
3645 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3646 ARM::VST3LNd16Pseudo_UPD,
3647 ARM::VST3LNd32Pseudo_UPD };
3648 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3649 ARM::VST3LNq32Pseudo_UPD };
3650 SelectVLDSTLane(N,
false,
true, 3, DOpcodes, QOpcodes);
3655 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3656 ARM::VST4LNd16Pseudo_UPD,
3657 ARM::VST4LNd32Pseudo_UPD };
3658 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3659 ARM::VST4LNq32Pseudo_UPD };
3660 SelectVLDSTLane(N,
false,
true, 4, DOpcodes, QOpcodes);
3666 unsigned IntNo = cast<ConstantSDNode>(N->
getOperand(1))->getZExtValue();
3671 case Intrinsic::arm_mrrc:
3672 case Intrinsic::arm_mrrc2: {
3677 if (Subtarget->isThumb())
3678 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3680 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3690 if (Opc != ARM::MRRC2) {
3700 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3703 case Intrinsic::arm_ldaexd:
3704 case Intrinsic::arm_ldrexd: {
3708 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
3710 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3711 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3712 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
3715 std::vector<EVT> ResTys;
3725 CurDAG->getRegister(0,
MVT::i32), Chain};
3726 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3729 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
3730 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3734 if (!SDValue(N, 0).use_empty()) {
3737 Result = SDValue(Ld, 0);
3740 CurDAG->getTargetConstant(ARM::gsub_0, dl,
MVT::i32);
3741 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3742 dl,
MVT::i32, SDValue(Ld, 0), SubRegIdx);
3743 Result = SDValue(ResNode,0);
3745 ReplaceUses(SDValue(N, 0), Result);
3747 if (!SDValue(N, 1).use_empty()) {
3750 Result = SDValue(Ld, 1);
3753 CurDAG->getTargetConstant(ARM::gsub_1, dl,
MVT::i32);
3754 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3755 dl,
MVT::i32, SDValue(Ld, 0), SubRegIdx);
3756 Result = SDValue(ResNode,0);
3758 ReplaceUses(SDValue(N, 1), Result);
3760 ReplaceUses(SDValue(N, 2), OutChain);
3761 CurDAG->RemoveDeadNode(N);
3764 case Intrinsic::arm_stlexd:
3765 case Intrinsic::arm_strexd: {
3776 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3790 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3791 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3792 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
3794 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
3797 MemOp[0] = cast<MemIntrinsicSDNode>(
N)->getMemOperand();
3798 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3804 case Intrinsic::arm_neon_vld1: {
3805 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3806 ARM::VLD1d32, ARM::VLD1d64 };
3807 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3808 ARM::VLD1q32, ARM::VLD1q64};
3809 SelectVLD(N,
false, 1, DOpcodes, QOpcodes,
nullptr);
3813 case Intrinsic::arm_neon_vld2: {
3814 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3815 ARM::VLD2d32, ARM::VLD1q64 };
3816 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3817 ARM::VLD2q32Pseudo };
3818 SelectVLD(N,
false, 2, DOpcodes, QOpcodes,
nullptr);
3822 case Intrinsic::arm_neon_vld3: {
3823 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3826 ARM::VLD1d64TPseudo };
3827 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3828 ARM::VLD3q16Pseudo_UPD,
3829 ARM::VLD3q32Pseudo_UPD };
3830 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3831 ARM::VLD3q16oddPseudo,
3832 ARM::VLD3q32oddPseudo };
3833 SelectVLD(N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3837 case Intrinsic::arm_neon_vld4: {
3838 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3841 ARM::VLD1d64QPseudo };
3842 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3843 ARM::VLD4q16Pseudo_UPD,
3844 ARM::VLD4q32Pseudo_UPD };
3845 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3846 ARM::VLD4q16oddPseudo,
3847 ARM::VLD4q32oddPseudo };
3848 SelectVLD(N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3852 case Intrinsic::arm_neon_vld2lane: {
3853 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3854 ARM::VLD2LNd16Pseudo,
3855 ARM::VLD2LNd32Pseudo };
3856 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3857 ARM::VLD2LNq32Pseudo };
3858 SelectVLDSTLane(N,
true,
false, 2, DOpcodes, QOpcodes);
3862 case Intrinsic::arm_neon_vld3lane: {
3863 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3864 ARM::VLD3LNd16Pseudo,
3865 ARM::VLD3LNd32Pseudo };
3866 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3867 ARM::VLD3LNq32Pseudo };
3868 SelectVLDSTLane(N,
true,
false, 3, DOpcodes, QOpcodes);
3872 case Intrinsic::arm_neon_vld4lane: {
3873 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3874 ARM::VLD4LNd16Pseudo,
3875 ARM::VLD4LNd32Pseudo };
3876 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3877 ARM::VLD4LNq32Pseudo };
3878 SelectVLDSTLane(N,
true,
false, 4, DOpcodes, QOpcodes);
3882 case Intrinsic::arm_neon_vst1: {
3883 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3884 ARM::VST1d32, ARM::VST1d64 };
3885 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3886 ARM::VST1q32, ARM::VST1q64 };
3887 SelectVST(N,
false, 1, DOpcodes, QOpcodes,
nullptr);
3891 case Intrinsic::arm_neon_vst2: {
3892 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3893 ARM::VST2d32, ARM::VST1q64 };
3894 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3895 ARM::VST2q32Pseudo };
3896 SelectVST(N,
false, 2, DOpcodes, QOpcodes,
nullptr);
3900 case Intrinsic::arm_neon_vst3: {
3901 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3904 ARM::VST1d64TPseudo };
3905 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3906 ARM::VST3q16Pseudo_UPD,
3907 ARM::VST3q32Pseudo_UPD };
3908 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3909 ARM::VST3q16oddPseudo,
3910 ARM::VST3q32oddPseudo };
3911 SelectVST(N,
false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3915 case Intrinsic::arm_neon_vst4: {
3916 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3919 ARM::VST1d64QPseudo };
3920 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3921 ARM::VST4q16Pseudo_UPD,
3922 ARM::VST4q32Pseudo_UPD };
3923 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3924 ARM::VST4q16oddPseudo,
3925 ARM::VST4q32oddPseudo };
3926 SelectVST(N,
false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3930 case Intrinsic::arm_neon_vst2lane: {
3931 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3932 ARM::VST2LNd16Pseudo,
3933 ARM::VST2LNd32Pseudo };
3934 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3935 ARM::VST2LNq32Pseudo };
3936 SelectVLDSTLane(N,
false,
false, 2, DOpcodes, QOpcodes);
3940 case Intrinsic::arm_neon_vst3lane: {
3941 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3942 ARM::VST3LNd16Pseudo,
3943 ARM::VST3LNd32Pseudo };
3944 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3945 ARM::VST3LNq32Pseudo };
3946 SelectVLDSTLane(N,
false,
false, 3, DOpcodes, QOpcodes);
3950 case Intrinsic::arm_neon_vst4lane: {
3951 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3952 ARM::VST4LNd16Pseudo,
3953 ARM::VST4LNd32Pseudo };
3954 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3955 ARM::VST4LNq32Pseudo };
3956 SelectVLDSTLane(N,
false,
false, 4, DOpcodes, QOpcodes);
3964 unsigned IntNo = cast<ConstantSDNode>(N->
getOperand(0))->getZExtValue();
3969 case Intrinsic::arm_neon_vtbl2:
3972 case Intrinsic::arm_neon_vtbl3:
3973 SelectVTBL(N,
false, 3, ARM::VTBL3Pseudo);
3975 case Intrinsic::arm_neon_vtbl4:
3976 SelectVTBL(N,
false, 4, ARM::VTBL4Pseudo);
3979 case Intrinsic::arm_neon_vtbx2:
3980 SelectVTBL(N,
true, 2, ARM::VTBX2);
3982 case Intrinsic::arm_neon_vtbx3:
3983 SelectVTBL(N,
true, 3, ARM::VTBX3Pseudo);
3985 case Intrinsic::arm_neon_vtbx4:
3986 SelectVTBL(N,
true, 4, ARM::VTBX4Pseudo);
3998 ReplaceNode(N, CurDAG->getMachineNode(
ARM::VTBL1, dl, VT, Ops));
4008 SDValue RegSeq = SDValue(createDRegPairNode(
MVT::v16i8, V0, V1), 0);
4012 ReplaceNode(N, CurDAG->getMachineNode(
ARM::VTBL2, dl, VT, Ops));
4017 SelectConcatVector(N);
4036 std::vector<SDValue> &Ops) {
4038 RegString.
split(Fields,
':');
4040 if (Fields.
size() > 1) {
4041 bool AllIntFields =
true;
4046 AllIntFields &= !
Field.trim(
"CPcp").getAsInteger(10, IntField);
4051 "Unexpected non-integer value in special register string.");
4062 .Case(
"r8_usr", 0x00)
4063 .
Case(
"r9_usr", 0x01)
4064 .
Case(
"r10_usr", 0x02)
4065 .
Case(
"r11_usr", 0x03)
4066 .
Case(
"r12_usr", 0x04)
4067 .
Case(
"sp_usr", 0x05)
4068 .
Case(
"lr_usr", 0x06)
4069 .
Case(
"r8_fiq", 0x08)
4070 .
Case(
"r9_fiq", 0x09)
4071 .
Case(
"r10_fiq", 0x0a)
4072 .
Case(
"r11_fiq", 0x0b)
4073 .
Case(
"r12_fiq", 0x0c)
4074 .
Case(
"sp_fiq", 0x0d)
4075 .
Case(
"lr_fiq", 0x0e)
4076 .
Case(
"lr_irq", 0x10)
4077 .
Case(
"sp_irq", 0x11)
4078 .
Case(
"lr_svc", 0x12)
4079 .
Case(
"sp_svc", 0x13)
4080 .
Case(
"lr_abt", 0x14)
4081 .
Case(
"sp_abt", 0x15)
4082 .
Case(
"lr_und", 0x16)
4083 .
Case(
"sp_und", 0x17)
4084 .
Case(
"lr_mon", 0x1c)
4085 .
Case(
"sp_mon", 0x1d)
4086 .
Case(
"elr_hyp", 0x1e)
4087 .
Case(
"sp_hyp", 0x1f)
4088 .
Case(
"spsr_fiq", 0x2e)
4089 .
Case(
"spsr_irq", 0x30)
4090 .
Case(
"spsr_svc", 0x32)
4091 .
Case(
"spsr_abt", 0x34)
4092 .
Case(
"spsr_und", 0x36)
4093 .
Case(
"spsr_mon", 0x3c)
4094 .
Case(
"spsr_hyp", 0x3e)
4112 .
Case(
"primask", 0x10)
4113 .
Case(
"basepri", 0x11)
4114 .
Case(
"basepri_max", 0x12)
4115 .
Case(
"faultmask", 0x13)
4116 .
Case(
"control", 0x14)
4117 .
Case(
"msplim", 0x0a)
4118 .
Case(
"psplim", 0x0b)
4128 return 0x2 | (
int)hasDSP;
4133 .
Case(
"nzcvqg", 0x3)
4142 if (SYSmvalue == -1)
4146 if (!Subtarget->
hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
4155 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
4159 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
4177 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.
empty()))
4182 if (!Subtarget->
hasDSP() && (Mask & 0x1))
4188 if (SYSmvalue < 0x4)
4189 return SYSmvalue | Mask << 10;
4200 if (Reg ==
"apsr") {
4210 if (Reg !=
"cpsr" && Reg !=
"spsr") {
4215 if (Flags.
empty() || Flags ==
"all")
4220 for (
char Flag : Flags) {
4240 if (!FlagVal || (Mask & FlagVal))
4255 bool ARMDAGToDAGISel::tryReadRegister(
SDNode *N){
4258 bool IsThumb2 = Subtarget->isThumb2();
4261 std::vector<SDValue> Ops;
4271 if (Ops.size() == 5){
4272 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
4275 assert(Ops.size() == 3 &&
4276 "Invalid number of fields in special register string.");
4277 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
4281 Ops.push_back(
getAL(CurDAG, DL));
4282 Ops.push_back(CurDAG->getRegister(0,
MVT::i32));
4284 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
4288 std::string SpecialReg = RegString->getString().lower();
4291 if (BankedReg != -1) {
4292 Ops = { CurDAG->getTargetConstant(BankedReg, DL,
MVT::i32),
4296 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
4305 .Case(
"fpscr", ARM::VMRS)
4306 .
Case(
"fpexc", ARM::VMRS_FPEXC)
4307 .
Case(
"fpsid", ARM::VMRS_FPSID)
4308 .
Case(
"mvfr0", ARM::VMRS_MVFR0)
4309 .
Case(
"mvfr1", ARM::VMRS_MVFR1)
4310 .
Case(
"mvfr2", ARM::VMRS_MVFR2)
4311 .
Case(
"fpinst", ARM::VMRS_FPINST)
4312 .
Case(
"fpinst2", ARM::VMRS_FPINST2)
4317 if (!Subtarget->hasVFP2())
4319 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
4322 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
4332 if (Subtarget->isMClass()) {
4334 if (
Reg.endswith(
"_ns")) {
4340 if (SYSmValue == -1)
4343 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL,
MVT::i32),
4353 if (SpecialReg ==
"apsr" || SpecialReg ==
"cpsr") {
4354 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
4356 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4361 if (SpecialReg ==
"spsr") {
4362 Ops = {
getAL(CurDAG, DL), CurDAG->getRegister(0,
MVT::i32),
4365 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4376 bool ARMDAGToDAGISel::tryWriteRegister(
SDNode *N){
4379 bool IsThumb2 = Subtarget->isThumb2();
4382 std::vector<SDValue> Ops;
4391 if (Ops.size() == 5) {
4392 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4395 assert(Ops.size() == 3 &&
4396 "Invalid number of fields in special register string.");
4397 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4399 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4402 Ops.push_back(
getAL(CurDAG, DL));
4403 Ops.push_back(CurDAG->getRegister(0,
MVT::i32));
4406 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL,
MVT::Other, Ops));
4410 std::string SpecialReg = RegString->getString().lower();
4412 if (BankedReg != -1) {
4417 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4426 .Case(
"fpscr", ARM::VMSR)
4427 .
Case(
"fpexc", ARM::VMSR_FPEXC)
4428 .
Case(
"fpsid", ARM::VMSR_FPSID)
4429 .
Case(
"fpinst", ARM::VMSR_FPINST)
4430 .
Case(
"fpinst2", ARM::VMSR_FPINST2)
4434 if (!Subtarget->hasVFP2())
4438 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL,
MVT::Other, Ops));
4442 std::pair<StringRef, StringRef> Fields;
4444 std::string
Reg = Fields.first.str();
4449 if (Subtarget->isMClass()) {
4451 if (SpecialReg ==
"basepri_max") {
4456 if (SYSmValue == -1)
4459 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL,
MVT::i32),
4462 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL,
MVT::Other, Ops));
4474 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4482 bool ARMDAGToDAGISel::tryInlineAsm(
SDNode *N){
4483 std::vector<SDValue> AsmNodeOperands;
4485 bool Changed =
false;
4498 : SDValue(
nullptr,0);
4502 for(
unsigned i = 0, e = N->
getGluedNode() ? NumOps - 1 : NumOps;
i < e; ++
i) {
4504 AsmNodeOperands.push_back(op);
4510 Flag =
C->getZExtValue();
4522 AsmNodeOperands.push_back(op);
4530 unsigned DefIdx = 0;
4531 bool IsTiedToChangedOp =
false;
4535 IsTiedToChangedOp = OpChanged[DefIdx];
4544 AsmNodeOperands.push_back(op);
4554 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4558 assert((
i+2 < NumOps) &&
"Invalid number of operands in inline asm");
4561 unsigned Reg0 = cast<RegisterSDNode>(V0)->
getReg();
4562 unsigned Reg1 = cast<RegisterSDNode>(V1)->
getReg();
4573 SDValue Chain = SDValue(N,0);
4576 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR,
MVT::Untyped,
4580 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl,
MVT::i32,
4582 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl,
MVT::i32,
4584 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4586 SDValue
T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.
getValue(1));
4591 CurDAG->UpdateNodeOperands(GU, Ops);
4599 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0,
MVT::i32,
4601 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1,
MVT::i32,
4609 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.
getValue(1));
4618 OpChanged[OpChanged.
size() -1 ] =
true;
4620 if (IsTiedToChangedOp)
4625 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
4628 AsmNodeOperands.push_back(PairedReg);
4635 AsmNodeOperands.push_back(Glue);
4642 ReplaceNode(N, New.
getNode());
4647 bool ARMDAGToDAGISel::
4648 SelectInlineAsmMemoryOperand(
const SDValue &Op,
unsigned ConstraintID,
4649 std::vector<SDValue> &OutOps) {
4650 switch(ConstraintID) {
4670 OutOps.push_back(Op);
4681 return new ARMDAGToDAGISel(TM, OptLevel);
static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1, bool Accumulate)
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)
SDVTList getVTList() const
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.
static Optional< std::pair< unsigned, unsigned > > getContiguousRangeOfSetBits(const APInt &A)
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.
const SDValue & getBasePtr() const
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the most significant bit to the least stopping at the first 1...
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...
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.
struct fuzzer::@269 Flags
const HexagonInstrInfo * TII
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.
static int getT2SOImmValSplatVal(unsigned V)
getT2SOImmValSplat - Return the 12-bit encoded representation if the specified value can be obtained ...
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...
bool hasV8MMainlineOps() const
LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(const T &Value) const
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(const char(&S)[N], const T &Value)
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...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
EVT getMemoryVT() const
Return the type of the in-memory value.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0, SDValue &Src1, bool Accumulate)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
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
unsigned getScalarSizeInBits() const
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)
unsigned const MachineRegisterInfo * MRI
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)
constexpr bool isPowerOf2_32(uint32_t Value)
isPowerOf2_32 - This function returns true if the argument is a power of two > 0. ...
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)
LLVM_NODISCARD std::pair< StringRef, StringRef > rsplit(char Separator) const
Split into two substrings around the last occurrence of a separator character.
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 ManagedStatic< OptionRegistry > OR
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned getOpcode() const
static unsigned getKind(unsigned Flags)
FunctionPass class - This class is used to implement most global optimizations.
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
self_iterator getIterator()
unsigned countPopulation() const
Count the number of bits set.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo...
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...
static SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl)
getAL - Returns a ARMCC::AL immediate node.
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getOpcode() const
Return the opcode number for this descriptor.
const SDValue & getOffset() const
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead, const ARMSubtarget *Subtarget)
const MDOperand & getOperand(unsigned I) const
Iterator for intrusive lists based on ilist_node.
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...
bool use_empty() const
Return true if there are no nodes using value ResNo of Node.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
static int getMClassFlagsMask(StringRef Flags, bool hasDSP)
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.
Class for arbitrary precision integers.
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
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_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
static int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
op_iterator op_end() const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
int getNodeId() const
Return the unique node id.
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
This class is used to form a handle around another node that is persistent and is updated across invo...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
static void getIntOperandsFromRegisterString(StringRef RegString, SelectionDAG *CurDAG, const SDLoc &DL, std::vector< SDValue > &Ops)
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned countLeadingZeros() const
The APInt version of the countLeadingZeros functions in MathExtras.h.
constexpr bool isShiftedMask_32(uint32_t Value)
isShiftedMask_32 - This function returns true if the argument contains a non-empty sequence of ones w...
StringRef - Represent a constant reference to a string, i.e.
unsigned getAlignment() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
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.
LLVM_NODISCARD 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.
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.
static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)