36 #define DEBUG_TYPE "aarch64-isel" 42 #define GET_GLOBALISEL_PREDICATE_BITSET 43 #include "AArch64GenGlobalISel.inc" 44 #undef GET_GLOBALISEL_PREDICATE_BITSET 70 bool emitScalarToVector(
unsigned &Dst,
const LLT DstTy,
83 ComplexRendererFns selectAddrModeUnscaled8(
MachineOperand &Root)
const {
84 return selectAddrModeUnscaled(Root, 1);
86 ComplexRendererFns selectAddrModeUnscaled16(
MachineOperand &Root)
const {
87 return selectAddrModeUnscaled(Root, 2);
89 ComplexRendererFns selectAddrModeUnscaled32(
MachineOperand &Root)
const {
90 return selectAddrModeUnscaled(Root, 4);
92 ComplexRendererFns selectAddrModeUnscaled64(
MachineOperand &Root)
const {
93 return selectAddrModeUnscaled(Root, 8);
95 ComplexRendererFns selectAddrModeUnscaled128(
MachineOperand &Root)
const {
96 return selectAddrModeUnscaled(Root, 16);
100 unsigned Size)
const;
102 ComplexRendererFns selectAddrModeIndexed(
MachineOperand &Root)
const {
103 return selectAddrModeIndexed(Root, Width / 8);
110 unsigned char OpFlags)
const;
118 #define GET_GLOBALISEL_PREDICATES_DECL 119 #include "AArch64GenGlobalISel.inc" 120 #undef GET_GLOBALISEL_PREDICATES_DECL 124 #define GET_GLOBALISEL_TEMPORARIES_DECL 125 #include "AArch64GenGlobalISel.inc" 126 #undef GET_GLOBALISEL_TEMPORARIES_DECL 131 #define GET_GLOBALISEL_IMPL 132 #include "AArch64GenGlobalISel.inc" 133 #undef GET_GLOBALISEL_IMPL 135 AArch64InstructionSelector::AArch64InstructionSelector(
139 TRI(*STI.getRegisterInfo()), RBI(RBI),
141 #include
"AArch64GenGlobalISel.inc" 144 #include
"AArch64GenGlobalISel.inc" 154 bool GetAllRegSet =
false) {
155 if (RB.
getID() == AArch64::GPRRegBankID) {
157 return GetAllRegSet ? &AArch64::GPR32allRegClass
158 : &AArch64::GPR32RegClass;
160 return GetAllRegSet ? &AArch64::GPR64allRegClass
161 : &AArch64::GPR64RegClass;
165 if (RB.
getID() == AArch64::FPRRegBankID) {
167 return &AArch64::FPR16RegClass;
169 return &AArch64::FPR32RegClass;
171 return &AArch64::FPR64RegClass;
173 return &AArch64::FPR128RegClass;
200 LLVM_DEBUG(
dbgs() <<
"Generic inst non-reg operands are unsupported\n");
208 if (!TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
209 LLVM_DEBUG(
dbgs() <<
"Generic inst has physical register operand\n");
219 if (PrevOpBank && OpBank != PrevOpBank) {
220 LLVM_DEBUG(
dbgs() <<
"Generic inst operands have different banks\n");
235 case AArch64::GPRRegBankID:
237 switch (GenericOpc) {
238 case TargetOpcode::G_SHL:
239 return AArch64::LSLVWr;
240 case TargetOpcode::G_LSHR:
241 return AArch64::LSRVWr;
242 case TargetOpcode::G_ASHR:
243 return AArch64::ASRVWr;
247 }
else if (OpSize == 64) {
248 switch (GenericOpc) {
249 case TargetOpcode::G_GEP:
250 return AArch64::ADDXrr;
251 case TargetOpcode::G_SHL:
252 return AArch64::LSLVXr;
253 case TargetOpcode::G_LSHR:
254 return AArch64::LSRVXr;
255 case TargetOpcode::G_ASHR:
256 return AArch64::ASRVXr;
262 case AArch64::FPRRegBankID:
265 switch (GenericOpc) {
266 case TargetOpcode::G_FADD:
267 return AArch64::FADDSrr;
268 case TargetOpcode::G_FSUB:
269 return AArch64::FSUBSrr;
270 case TargetOpcode::G_FMUL:
271 return AArch64::FMULSrr;
272 case TargetOpcode::G_FDIV:
273 return AArch64::FDIVSrr;
278 switch (GenericOpc) {
279 case TargetOpcode::G_FADD:
280 return AArch64::FADDDrr;
281 case TargetOpcode::G_FSUB:
282 return AArch64::FSUBDrr;
283 case TargetOpcode::G_FMUL:
284 return AArch64::FMULDrr;
285 case TargetOpcode::G_FDIV:
286 return AArch64::FDIVDrr;
287 case TargetOpcode::G_OR:
288 return AArch64::ORRv8i8;
305 const bool isStore = GenericOpc == TargetOpcode::G_STORE;
307 case AArch64::GPRRegBankID:
310 return isStore ? AArch64::STRBBui : AArch64::LDRBBui;
312 return isStore ? AArch64::STRHHui : AArch64::LDRHHui;
314 return isStore ? AArch64::STRWui : AArch64::LDRWui;
316 return isStore ? AArch64::STRXui : AArch64::LDRXui;
319 case AArch64::FPRRegBankID:
322 return isStore ? AArch64::STRBui : AArch64::LDRBui;
324 return isStore ? AArch64::STRHui : AArch64::LDRHui;
326 return isStore ? AArch64::STRSui : AArch64::LDRSui;
328 return isStore ? AArch64::STRDui : AArch64::LDRDui;
345 .
addUse(CopyReg, 0, AArch64::hsub);
359 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
361 !TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
364 MRI.
getType(SrcReg), RegBank, RBI,
true);
365 if (SrcRC == &AArch64::GPR32allRegClass)
368 assert(I.
isCopy() &&
"Generic operators do not allow physical registers");
375 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
377 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.
isCopy()) &&
378 "No phys reg on generic operators");
380 (DstSize == SrcSize ||
383 (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
384 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI)) ||
388 (((DstSize + 31) / 32 == (SrcSize + 31) / 32) && DstSize > SrcSize)) &&
389 "Copy with different width?!");
390 assert((DstSize <= 64 || RegBank.
getID() == AArch64::FPRRegBankID) &&
391 "GPRs cannot get more than 64-bit width values");
394 MRI.
getType(DstReg), RegBank, RBI,
true);
396 LLVM_DEBUG(
dbgs() <<
"Unexpected bitcast size " << DstSize <<
'\n');
400 if (!TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
407 SrcRC = getRegClassForTypeOnBank(MRI.
getType(SrcReg), *RB, RBI,
true);
410 if (RC == &AArch64::GPR32allRegClass && SrcRC == &AArch64::FPR16RegClass) {
413 TII.
get(AArch64::SUBREG_TO_REG))
420 }
else if (RC == &AArch64::FPR16RegClass &&
421 SrcRC == &AArch64::GPR32allRegClass) {
429 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
449 switch (GenericOpc) {
450 case TargetOpcode::G_SITOFP:
451 return AArch64::SCVTFUWSri;
452 case TargetOpcode::G_UITOFP:
453 return AArch64::UCVTFUWSri;
454 case TargetOpcode::G_FPTOSI:
455 return AArch64::FCVTZSUWSr;
456 case TargetOpcode::G_FPTOUI:
457 return AArch64::FCVTZUUWSr;
462 switch (GenericOpc) {
463 case TargetOpcode::G_SITOFP:
464 return AArch64::SCVTFUXSri;
465 case TargetOpcode::G_UITOFP:
466 return AArch64::UCVTFUXSri;
467 case TargetOpcode::G_FPTOSI:
468 return AArch64::FCVTZSUWDr;
469 case TargetOpcode::G_FPTOUI:
470 return AArch64::FCVTZUUWDr;
480 switch (GenericOpc) {
481 case TargetOpcode::G_SITOFP:
482 return AArch64::SCVTFUWDri;
483 case TargetOpcode::G_UITOFP:
484 return AArch64::UCVTFUWDri;
485 case TargetOpcode::G_FPTOSI:
486 return AArch64::FCVTZSUXSr;
487 case TargetOpcode::G_FPTOUI:
488 return AArch64::FCVTZUUXSr;
493 switch (GenericOpc) {
494 case TargetOpcode::G_SITOFP:
495 return AArch64::SCVTFUXDri;
496 case TargetOpcode::G_UITOFP:
497 return AArch64::UCVTFUXDri;
498 case TargetOpcode::G_FPTOSI:
499 return AArch64::FCVTZSUXDr;
500 case TargetOpcode::G_FPTOUI:
501 return AArch64::FCVTZUUXDr;
518 case CmpInst::ICMP_NE:
520 case CmpInst::ICMP_EQ:
522 case CmpInst::ICMP_SGT:
524 case CmpInst::ICMP_SGE:
526 case CmpInst::ICMP_SLT:
528 case CmpInst::ICMP_SLE:
530 case CmpInst::ICMP_UGT:
532 case CmpInst::ICMP_UGE:
534 case CmpInst::ICMP_ULT:
536 case CmpInst::ICMP_ULE:
548 case CmpInst::FCMP_OEQ:
551 case CmpInst::FCMP_OGT:
554 case CmpInst::FCMP_OGE:
557 case CmpInst::FCMP_OLT:
560 case CmpInst::FCMP_OLE:
563 case CmpInst::FCMP_ONE:
567 case CmpInst::FCMP_ORD:
570 case CmpInst::FCMP_UNO:
573 case CmpInst::FCMP_UEQ:
577 case CmpInst::FCMP_UGT:
580 case CmpInst::FCMP_UGE:
583 case CmpInst::FCMP_ULT:
586 case CmpInst::FCMP_ULE:
589 case CmpInst::FCMP_UNE:
595 bool AArch64InstructionSelector::selectCompareBranch(
601 if (CCMI->
getOpcode() == TargetOpcode::G_TRUNC)
603 if (CCMI->
getOpcode() != TargetOpcode::G_ICMP)
612 if (!RHSImm || *RHSImm != 0)
616 if (RB.
getID() != AArch64::GPRRegBankID)
620 if (Pred != CmpInst::ICMP_NE && Pred != CmpInst::ICMP_EQ)
626 CBOpc = (Pred == CmpInst::ICMP_EQ ? AArch64::CBZW : AArch64::CBNZW);
627 else if (CmpWidth == 64)
628 CBOpc = (Pred == CmpInst::ICMP_EQ ? AArch64::CBZX : AArch64::CBNZX);
641 bool AArch64InstructionSelector::selectVaStartAAPCS(
646 bool AArch64InstructionSelector::selectVaStartDarwin(
673 void AArch64InstructionSelector::materializeLargeCMVal(
680 auto MovZ = MIB.
buildInstr(AArch64::MOVZXi, {&AArch64::GPR64RegClass}, {});
684 MovZ->addOperand(MF, MachineOperand::CreateImm(0));
687 auto BuildMovK = [&](
unsigned SrcReg,
unsigned char Flags,
unsigned Offset,
688 unsigned ForceDstReg) {
689 unsigned DstReg = ForceDstReg
693 if (
auto *GV = dyn_cast<GlobalValue>(V)) {
694 MovI->
addOperand(MF, MachineOperand::CreateGA(
695 GV, MovZ->getOperand(1).getOffset(), Flags));
698 MF, MachineOperand::CreateBA(cast<BlockAddress>(V),
699 MovZ->getOperand(1).getOffset(), Flags));
701 MovI->addOperand(MF, MachineOperand::CreateImm(Offset));
705 unsigned DstReg = BuildMovK(MovZ->getOperand(0).getReg(),
712 bool AArch64InstructionSelector::select(
MachineInstr &I,
726 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
729 if (Opcode == TargetOpcode::PHI || Opcode == TargetOpcode::G_PHI) {
734 if (TargetRegisterInfo::isPhysicalRegister(DefReg)) {
735 DefRC =
TRI.getRegClass(DefReg);
747 DefRC = getRegClassForTypeOnBank(DefTy, RB, RBI);
768 dbgs() <<
"Generic instruction has unexpected implicit operands\n");
779 case TargetOpcode::G_BRCOND: {
785 <<
", expected at most 32-bits");
795 bool ProduceNonFlagSettingCondBr =
797 if (ProduceNonFlagSettingCondBr && selectCompareBranch(I, MF, MRI))
800 if (ProduceNonFlagSettingCondBr) {
810 .addDef(AArch64::WZR)
824 case TargetOpcode::G_BRINDIRECT: {
829 case TargetOpcode::G_FCONSTANT:
830 case TargetOpcode::G_CONSTANT: {
831 const bool isFP = Opcode == TargetOpcode::G_FCONSTANT;
833 const LLT s32 = LLT::scalar(32);
834 const LLT s64 = LLT::scalar(64);
835 const LLT p0 = LLT::pointer(0, 64);
844 if (Ty != s32 && Ty != s64) {
846 <<
" constant, expected: " << s32 <<
" or " << s64
851 if (RB.
getID() != AArch64::FPRRegBankID) {
853 <<
" constant on bank: " << RB
854 <<
", expected: FPR\n");
866 <<
" constant, expected: " << s32 <<
", " << s64
867 <<
", or " << p0 <<
'\n');
871 if (RB.
getID() != AArch64::GPRRegBankID) {
873 <<
" constant on bank: " << RB
874 <<
", expected: GPR\n");
879 const unsigned MovOpc =
880 DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
886 DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
888 DefSize == 32 ? AArch64::FPR32RegClass : AArch64::FPR64RegClass;
895 TII.get(AArch64::COPY))
900 LLVM_DEBUG(
dbgs() <<
"Failed to constrain G_FCONSTANT def operand\n");
919 case TargetOpcode::G_EXTRACT: {
929 I.
setDesc(
TII.get(SrcSize == 64 ? AArch64::UBFMXri : AArch64::UBFMWri));
935 "unexpected G_EXTRACT types");
941 TII.get(AArch64::COPY))
943 .addUse(DstReg, 0, AArch64::sub_32);
945 AArch64::GPR32RegClass,
MRI);
951 case TargetOpcode::G_INSERT: {
960 I.
setDesc(
TII.get(DstSize == 64 ? AArch64::BFMXri : AArch64::BFMWri));
968 "unexpected G_INSERT types");
974 TII.get(AArch64::SUBREG_TO_REG))
978 .addImm(AArch64::sub_32);
980 AArch64::GPR32RegClass,
MRI);
985 case TargetOpcode::G_FRAME_INDEX: {
987 if (Ty != LLT::pointer(0, 64)) {
989 <<
", expected: " << LLT::pointer(0, 64) <<
'\n');
1001 case TargetOpcode::G_GLOBAL_VALUE: {
1003 if (GV->isThreadLocal()) {
1007 unsigned char OpFlags = STI.ClassifyGlobalReference(GV,
TM);
1013 materializeLargeCMVal(I, GV, OpFlags);
1029 case TargetOpcode::G_LOAD:
1030 case TargetOpcode::G_STORE: {
1033 if (PtrTy != LLT::pointer(0, 64)) {
1035 <<
", expected: " << LLT::pointer(0, 64) <<
'\n');
1040 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
1044 unsigned MemSizeInBits = MemOp.getSize() * 8;
1051 "Load/Store pointer operand isn't a GPR");
1053 "Load/Store pointer operand isn't a pointer");
1059 const unsigned NewOpc =
1070 if (PtrMI->getOpcode() == TargetOpcode::G_GEP) {
1072 int64_t Imm = *COff;
1073 const unsigned Size = MemSizeInBits / 8;
1074 const unsigned Scale =
Log2_32(Size);
1075 if ((Imm & (Size - 1)) == 0 && Imm >= 0 && Imm < (0x1000 << Scale)) {
1076 unsigned Ptr2Reg = PtrMI->getOperand(1).getReg();
1079 Offset = Imm /
Size;
1086 if (!Offset && PtrMI->getOpcode() == TargetOpcode::G_FRAME_INDEX)
1089 I.
addOperand(MachineOperand::CreateImm(Offset));
1093 if (*CVal == 0 && Opcode == TargetOpcode::G_STORE) {
1096 else if (I.
getOpcode() == AArch64::STRXui)
1104 case TargetOpcode::G_SMULH:
1105 case TargetOpcode::G_UMULH: {
1113 if (RB.
getID() != AArch64::GPRRegBankID) {
1114 LLVM_DEBUG(
dbgs() <<
"G_[SU]MULH on bank: " << RB <<
", expected: GPR\n");
1118 if (Ty != LLT::scalar(64)) {
1120 <<
", expected: " << LLT::scalar(64) <<
'\n');
1124 unsigned NewOpc = I.
getOpcode() == TargetOpcode::G_SMULH ? AArch64::SMULHrr
1132 case TargetOpcode::G_FADD:
1133 case TargetOpcode::G_FSUB:
1134 case TargetOpcode::G_FMUL:
1135 case TargetOpcode::G_FDIV:
1137 case TargetOpcode::G_OR:
1138 case TargetOpcode::G_SHL:
1139 case TargetOpcode::G_LSHR:
1140 case TargetOpcode::G_ASHR:
1141 case TargetOpcode::G_GEP: {
1163 case TargetOpcode::G_PTR_MASK: {
1165 if (Align >= 64 || Align == 0)
1174 case TargetOpcode::G_PTRTOINT:
1175 case TargetOpcode::G_TRUNC: {
1187 dbgs() <<
"G_TRUNC/G_PTRTOINT input/output on different banks\n");
1191 if (DstRB.
getID() == AArch64::GPRRegBankID) {
1193 getRegClassForTypeOnBank(DstTy, DstRB, RBI);
1198 getRegClassForTypeOnBank(SrcTy, SrcRB, RBI);
1204 LLVM_DEBUG(
dbgs() <<
"Failed to constrain G_TRUNC/G_PTRTOINT\n");
1208 if (DstRC == SrcRC) {
1210 }
else if (Opcode == TargetOpcode::G_TRUNC && DstTy == LLT::scalar(32) &&
1211 SrcTy == LLT::scalar(64)) {
1214 }
else if (DstRC == &AArch64::GPR32RegClass &&
1215 SrcRC == &AArch64::GPR64RegClass) {
1219 dbgs() <<
"Unhandled mismatched classes in G_TRUNC/G_PTRTOINT\n");
1225 }
else if (DstRB.
getID() == AArch64::FPRRegBankID) {
1226 if (DstTy == LLT::vector(4, 16) && SrcTy == LLT::vector(4, 32)) {
1236 case TargetOpcode::G_ANYEXT: {
1241 if (RBDst.
getID() != AArch64::GPRRegBankID) {
1243 <<
", expected: GPR\n");
1248 if (RBSrc.
getID() != AArch64::GPRRegBankID) {
1250 <<
", expected: GPR\n");
1257 LLVM_DEBUG(
dbgs() <<
"G_ANYEXT operand has no size, not a gvreg?\n");
1261 if (DstSize != 64 && DstSize > 32) {
1263 <<
", expected: 32 or 64\n");
1274 .
addImm(AArch64::sub_32);
1280 case TargetOpcode::G_ZEXT:
1281 case TargetOpcode::G_SEXT: {
1285 const bool isSigned = Opcode == TargetOpcode::G_SEXT;
1290 if (RB.
getID() != AArch64::GPRRegBankID) {
1292 <<
", expected: GPR\n");
1297 if (DstTy == LLT::scalar(64)) {
1305 const unsigned SrcXReg =
1311 .
addImm(AArch64::sub_32);
1313 const unsigned NewOpc = isSigned ? AArch64::SBFMXri : AArch64::UBFMXri;
1318 .
addImm(SrcTy.getSizeInBits() - 1);
1320 const unsigned NewOpc = isSigned ? AArch64::SBFMWri : AArch64::UBFMWri;
1325 .
addImm(SrcTy.getSizeInBits() - 1);
1336 case TargetOpcode::G_SITOFP:
1337 case TargetOpcode::G_UITOFP:
1338 case TargetOpcode::G_FPTOSI:
1339 case TargetOpcode::G_FPTOUI: {
1343 if (NewOpc == Opcode)
1353 case TargetOpcode::G_INTTOPTR:
1358 case TargetOpcode::G_BITCAST:
1367 case TargetOpcode::G_SELECT: {
1370 <<
", expected: " << LLT::scalar(1) <<
'\n');
1378 unsigned CSelOpc = 0;
1380 if (Ty == LLT::scalar(32)) {
1381 CSelOpc = AArch64::CSELWr;
1382 }
else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
1383 CSelOpc = AArch64::CSELXr;
1390 .addDef(AArch64::WZR)
1406 case TargetOpcode::G_ICMP: {
1407 if (Ty != LLT::scalar(32)) {
1409 <<
", expected: " << LLT::scalar(32) <<
'\n');
1413 unsigned CmpOpc = 0;
1417 if (CmpTy == LLT::scalar(32)) {
1418 CmpOpc = AArch64::SUBSWrr;
1419 ZReg = AArch64::WZR;
1420 }
else if (CmpTy == LLT::scalar(64) || CmpTy.
isPointer()) {
1421 CmpOpc = AArch64::SUBSXrr;
1422 ZReg = AArch64::XZR;
1442 .addUse(AArch64::WZR)
1453 case TargetOpcode::G_FCMP: {
1454 if (Ty != LLT::scalar(32)) {
1456 <<
", expected: " << LLT::scalar(32) <<
'\n');
1460 unsigned CmpOpc = 0;
1462 if (CmpTy == LLT::scalar(32)) {
1463 CmpOpc = AArch64::FCMPSrr;
1464 }
else if (CmpTy == LLT::scalar(64)) {
1465 CmpOpc = AArch64::FCMPDrr;
1481 unsigned Def1Reg = DefReg;
1515 case TargetOpcode::G_VASTART:
1516 return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
1517 : selectVaStartAAPCS(I, MF, MRI);
1518 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1527 case TargetOpcode::G_IMPLICIT_DEF: {
1528 I.
setDesc(
TII.get(TargetOpcode::IMPLICIT_DEF));
1533 getRegClassForTypeOnBank(DstTy, DstRB, RBI);
1537 case TargetOpcode::G_BLOCK_ADDR: {
1555 case TargetOpcode::G_BUILD_VECTOR:
1556 return selectBuildVector(I, MRI);
1557 case TargetOpcode::G_MERGE_VALUES:
1564 bool AArch64InstructionSelector::emitScalarToVector(
1572 TII.get(TargetOpcode::IMPLICIT_DEF))
1575 auto BuildFn = [&](
unsigned SubregIndex) {
1577 TII.get(TargetOpcode::INSERT_SUBREG))
1588 return BuildFn(AArch64::ssub);
1590 return BuildFn(AArch64::dsub);
1598 assert(I.
getOpcode() == TargetOpcode::G_MERGE_VALUES &&
"unexpected opcode");
1601 assert(!DstTy.isVector() && !SrcTy.
isVector() &&
"invalid merge operation");
1606 if (DstTy.getSizeInBits() != 64 || SrcTy.
getSizeInBits() != 32)
1609 if (RB.
getID() != AArch64::GPRRegBankID)
1612 auto *DstRC = &AArch64::GPR64RegClass;
1615 TII.get(TargetOpcode::SUBREG_TO_REG))
1616 .addDef(SubToRegDef)
1619 .addImm(AArch64::sub_32);
1623 TII.get(TargetOpcode::SUBREG_TO_REG))
1624 .addDef(SubToRegDef2)
1627 .addImm(AArch64::sub_32);
1631 .addUse(SubToRegDef)
1642 bool AArch64InstructionSelector::selectBuildVector(
1650 if (EltSize < 32 || EltSize > 64)
1655 if (RB.
getID() == AArch64::GPRRegBankID) {
1656 if (EltSize == 32) {
1657 Opc = AArch64::INSvi32gpr;
1658 SubregIdx = AArch64::ssub;
1660 Opc = AArch64::INSvi64gpr;
1661 SubregIdx = AArch64::dsub;
1664 if (EltSize == 32) {
1665 Opc = AArch64::INSvi32lane;
1666 SubregIdx = AArch64::ssub;
1668 Opc = AArch64::INSvi64lane;
1669 SubregIdx = AArch64::dsub;
1673 if (EltSize * DstTy.getNumElements() != 128)
1676 unsigned DstVec = 0;
1678 DstTy, RBI.
getRegBank(AArch64::FPRRegBankID), RBI);
1681 for (
unsigned i = 2, e = DstTy.getSizeInBits() / EltSize + 1; i < e; ++i) {
1688 unsigned LaneIdx = i - 1;
1689 if (RB.
getID() == AArch64::FPRRegBankID) {
1692 TII.get(TargetOpcode::IMPLICIT_DEF))
1696 TII.get(TargetOpcode::INSERT_SUBREG))
1731 AArch64InstructionSelector::selectArithImmed(
MachineOperand &Root)
const {
1747 else if (Root.
isReg()) {
1749 if (Def->
getOpcode() != TargetOpcode::G_CONSTANT)
1760 if (Immed >> 12 == 0) {
1762 }
else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
1764 Immed = Immed >> 12;
1781 AArch64InstructionSelector::selectAddrModeUnscaled(
MachineOperand &Root,
1782 unsigned Size)
const {
1789 if (!isBaseWithConstantOffset(Root, MRI))
1797 if (!OffImm.
isReg())
1800 if (!RHS || RHS->
getOpcode() != TargetOpcode::G_CONSTANT)
1809 if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 <<
Log2_32(Size)))
1811 if (RHSC >= -256 && RHSC < 256) {
1825 AArch64InstructionSelector::selectAddrModeIndexed(
MachineOperand &Root,
1826 unsigned Size)
const {
1837 if (RootDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX) {
1844 if (isBaseWithConstantOffset(Root, MRI)) {
1849 if (LHSDef && RHSDef) {
1851 unsigned Scale =
Log2_32(Size);
1852 if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 << Scale)) {
1853 if (LHSDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX)
1869 if (selectAddrModeUnscaled(Root, Size).hasValue())
1881 assert(MI.
getOpcode() == TargetOpcode::G_CONSTANT &&
"Expected G_CONSTANT");
1883 assert(CstVal &&
"Expected constant value");
1884 MIB.
addImm(CstVal.getValue());
1892 return new AArch64InstructionSelector(TM, Subtarget, RBI);
static bool selectFP16CopyFromGPR32(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, unsigned SrcReg)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address...
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
uint64_t getZExtValue() const
Get zero extended value.
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.
MachineBasicBlock * getMBB() const
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
This class represents lattice values for constants.
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
void setTargetFlags(unsigned F)
int getVarArgsStackIndex() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
static CondCode getInvertedCondCode(CondCode Code)
unsigned getReg() const
getReg - Returns the register number.
static uint64_t selectImpl(uint64_t CandidateMask, uint64_t &NextInSequenceMask)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
unsigned const TargetRegisterInfo * TRI
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address...
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getBitWidth() const
getBitWidth - Return the bitwidth of this constant.
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address...
This file declares the targeting of the RegisterBankInfo class for AArch64.
bool isIntrinsicID() const
Holds all the information related to register banks.
const HexagonInstrInfo * TII
const ConstantFP * getFPImm() const
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static StringRef getName(Value *V)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
const RegClassOrRegBank & getRegClassOrRegBank(unsigned Reg) const
Return the register bank or register class of Reg.
static bool isStore(int Opcode)
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
TargetInstrInfo - Interface to description of machine instruction set.
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV)...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Control flow instructions. These all have token chains.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address...
unsigned const MachineRegisterInfo * MRI
static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the (value)...
static unsigned selectFPConvOpc(unsigned GenericOpc, LLT DstTy, LLT SrcTy)
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
const GlobalValue * getGlobal() const
Helper class to build MachineInstr.
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setImm(int64_t immVal)
self_iterator getIterator()
const MachineInstrBuilder & addFrameIndex(int Idx) const
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwises returns null...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
#define GET_GLOBALISEL_TEMPORARIES_INIT
const APFloat & getValueAPF() const
unsigned createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
MachineOperand class - Representation of each machine instruction operand.
Intrinsic::ID getIntrinsicID() const
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
This class implements the register bank concept.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
This file declares the MachineIRBuilder class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned Log2_32(uint32_t Value)
Return 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.
Optional< int64_t > getConstantVRegVal(unsigned VReg, const MachineRegisterInfo &MRI)
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides the logic to select generic machine instructions.
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
This class provides the information for the target register banks.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P)
InstructionSelector * createAArch64InstructionSelector(const AArch64TargetMachine &, AArch64Subtarget &, AArch64RegisterBankInfo &)
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
void setReg(unsigned Reg)
Change the register this operand corresponds to.
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
void setSubReg(unsigned subReg)
static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
#define GET_GLOBALISEL_PREDICATES_INIT
bool isReg() const
isReg - Tests if this is a MO_Register operand.
T get() const
Returns the value of the specified pointer type.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void changeFCMPPredToAArch64CC(CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
LLVM Value Representation.
unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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.
void ChangeToFrameIndex(int Idx)
Replace this operand with a frame index.
static bool unsupportedBinOp(const MachineInstr &I, const AArch64RegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const AArch64RegisterInfo &TRI)
Check whether I is a currently unsupported binary operation:
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
APInt bitcastToAPInt() const
const MachineInstrBuilder & addDef(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
const MachineOperand & getOperand(unsigned i) const
const ConstantInt * getCImm() const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
unsigned getID() const
Get the identifier of this register bank.
A discriminated union of two pointer types, with the discriminator in the low bit of the pointer...
unsigned getPredicate() const