39#include "llvm/IR/IntrinsicsAArch64.h"
44#define GET_TARGET_REGBANK_IMPL
45#include "AArch64GenRegisterBank.inc"
48#include "AArch64GenRegisterBankInfo.def"
58 static auto InitializeRegisterBankOnce = [&]() {
67 assert(&AArch64::GPRRegBank == &RBGPR &&
68 "The order in RegBanks is messed up");
72 assert(&AArch64::FPRRegBank == &RBFPR &&
73 "The order in RegBanks is messed up");
77 assert(&AArch64::CCRegBank == &RBCCR &&
78 "The order in RegBanks is messed up");
83 "Subclass not added?");
85 "GPRs should hold up to 128-bit");
90 "Subclass not added?");
92 "Subclass not added?");
94 "FPRs should hold up to 512-bit via QQQQ sequence");
99 "CCR should hold up to 32-bit");
105 "PartialMappingIdx's are incorrectly ordered");
109 "PartialMappingIdx's are incorrectly ordered");
112#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
115 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
116 #Idx " is incorrectly initialized"); \
130#define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
132 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
133 PartialMappingIdx::PMI_First##RBName, Size, \
135 #RBName #Size " " #Offset " is incorrectly initialized"); \
138#define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
152#define CHECK_VALUEMAP_3OPS(RBName, Size) \
154 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
155 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
156 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
168#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
170 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
171 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
172 (void)PartialMapDstIdx; \
173 (void)PartialMapSrcIdx; \
174 const ValueMapping *Map = getCopyMapping(AArch64::RBNameDst##RegBankID, \
175 AArch64::RBNameSrc##RegBankID, \
176 TypeSize::getFixed(Size)); \
178 assert(Map[0].BreakDown == \
179 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
180 Map[0].NumBreakDowns == 1 && \
181 #RBNameDst #Size " Dst is incorrectly initialized"); \
182 assert(Map[1].BreakDown == \
183 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
184 Map[1].NumBreakDowns == 1 && \
185 #RBNameSrc #Size " Src is incorrectly initialized"); \
198#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
200 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
201 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
202 (void)PartialMapDstIdx; \
203 (void)PartialMapSrcIdx; \
204 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
206 assert(Map[0].BreakDown == \
207 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
208 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
209 " Dst is incorrectly initialized"); \
210 assert(Map[1].BreakDown == \
211 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
212 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
213 " Src is incorrectly initialized"); \
225 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
239 if (&
A == &AArch64::GPRRegBank && &
B == &AArch64::FPRRegBank)
242 if (&
A == &AArch64::FPRRegBank && &
B == &AArch64::GPRRegBank)
252 switch (RC.
getID()) {
253 case AArch64::GPR64sponlyRegClassID:
254 return AArch64::GPRRegBank;
268 switch (
MI.getOpcode()) {
269 case TargetOpcode::G_OR: {
278 if (
MI.getNumOperands() != 3)
292 case TargetOpcode::G_BITCAST: {
299 if (
MI.getNumOperands() != 2)
314 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
321 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
332 case TargetOpcode::G_LOAD: {
339 if (
MI.getNumOperands() != 2)
371 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT);
373 LLT Ty =
MRI.getType(Dst);
375 unsigned Size = Ty.getSizeInBits();
382 const APFloat Imm =
MI.getOperand(1).getFPImm()->getValueAPF();
383 const APInt ImmBits =
Imm.bitcastToAPInt();
387 return UseMI.getOpcode() == TargetOpcode::G_STORE &&
388 UseMI.getOperand(0).getReg() == Dst;
404 bool IsLegal =
TLI->isFPImmLegal(
Imm, VT, OptForSize);
405 bool IsFMov =
TLI->isFPImmLegalAsFMov(
Imm, VT);
406 return !IsFMov && IsLegal;
420 if (!TruncMI || TruncMI->
getOpcode() != TargetOpcode::G_TRUNC)
425 if (!SrcDef || SrcDef->
getOpcode() != TargetOpcode::G_CONSTANT)
428 LLT TruncSrcTy =
MRI.getType(TruncSrc);
434 MRI.setRegBank(TruncSrc, AArch64::GPRRegBank);
436 if (
MRI.use_empty(ScalarReg))
442void AArch64RegisterBankInfo::applyMappingImpl(
444 MachineInstr &
MI = OpdMapper.getMI();
445 MachineRegisterInfo &
MRI = OpdMapper.getMRI();
447 switch (
MI.getOpcode()) {
448 case TargetOpcode::G_CONSTANT: {
450 [[maybe_unused]] LLT DstTy =
MRI.
getType(Dst);
453 "Expected a scalar smaller than 32 bits on a GPR.");
458 APInt Val =
MI.getOperand(1).getCImm()->getValue().zext(32);
460 MI.getOperand(1).setCImm(ConstantInt::get(Ctx, Val));
461 MI.getOperand(0).setReg(ExtReg);
466 case TargetOpcode::G_FCONSTANT: {
469 "Expected Dst to be on a GPR.");
470 const APFloat &
Imm =
MI.getOperand(1).getFPImm()->getValueAPF();
471 APInt
Bits =
Imm.bitcastToAPInt();
473 if (
Bits.getBitWidth() < 32) {
481 MI.eraseFromParent();
484 case TargetOpcode::G_STORE: {
496 MI.getOperand(0).setReg(Ext.getReg(0));
501 case TargetOpcode::G_LOAD: {
509 MI.getOperand(0).setReg(ExtReg);
514 case TargetOpcode::G_OR:
515 case TargetOpcode::G_BITCAST:
517 assert((OpdMapper.getInstrMapping().getID() >= 1 &&
518 OpdMapper.getInstrMapping().getID() <= 4) &&
519 "Don't know how to handle that ID");
521 case TargetOpcode::G_SPLAT_VECTOR: {
527 "Expected sources smaller than 32-bits");
534 MI.getOperand(1).setReg(ConstReg);
544AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
546 const unsigned Opc =
MI.getOpcode();
550 unsigned NumOperands =
MI.getNumOperands();
551 assert(NumOperands <= 3 &&
552 "This code is for instructions with 3 or less operands");
569 for (
unsigned Idx = 1;
Idx != NumOperands; ++
Idx) {
575 "Operand has incompatible size");
578 assert(IsFPR == OpIsFPR &&
"Operand has incompatible type");
593 case Intrinsic::aarch64_neon_uaddlv:
594 case Intrinsic::aarch64_neon_uaddv:
595 case Intrinsic::aarch64_neon_saddv:
596 case Intrinsic::aarch64_neon_umaxv:
597 case Intrinsic::aarch64_neon_smaxv:
598 case Intrinsic::aarch64_neon_uminv:
599 case Intrinsic::aarch64_neon_sminv:
600 case Intrinsic::aarch64_neon_faddv:
601 case Intrinsic::aarch64_neon_fmaxv:
602 case Intrinsic::aarch64_neon_fminv:
603 case Intrinsic::aarch64_neon_fmaxnmv:
604 case Intrinsic::aarch64_neon_fminnmv:
605 case Intrinsic::aarch64_neon_fmulx:
606 case Intrinsic::aarch64_neon_frecpe:
607 case Intrinsic::aarch64_neon_frecps:
608 case Intrinsic::aarch64_neon_frecpx:
609 case Intrinsic::aarch64_neon_frsqrte:
610 case Intrinsic::aarch64_neon_frsqrts:
611 case Intrinsic::aarch64_neon_facge:
612 case Intrinsic::aarch64_neon_facgt:
613 case Intrinsic::aarch64_neon_fabd:
614 case Intrinsic::aarch64_neon_sqrdmlah:
615 case Intrinsic::aarch64_neon_sqrdmlsh:
616 case Intrinsic::aarch64_neon_sqrdmulh:
617 case Intrinsic::aarch64_neon_suqadd:
618 case Intrinsic::aarch64_neon_usqadd:
619 case Intrinsic::aarch64_neon_uqadd:
620 case Intrinsic::aarch64_neon_sqadd:
621 case Intrinsic::aarch64_neon_uqsub:
622 case Intrinsic::aarch64_neon_sqsub:
623 case Intrinsic::aarch64_neon_sqdmulh:
624 case Intrinsic::aarch64_neon_sqdmulls_scalar:
625 case Intrinsic::aarch64_neon_srshl:
626 case Intrinsic::aarch64_neon_urshl:
627 case Intrinsic::aarch64_neon_sqshl:
628 case Intrinsic::aarch64_neon_uqshl:
629 case Intrinsic::aarch64_neon_sqrshl:
630 case Intrinsic::aarch64_neon_uqrshl:
631 case Intrinsic::aarch64_neon_ushl:
632 case Intrinsic::aarch64_neon_sshl:
633 case Intrinsic::aarch64_neon_sqshrn:
634 case Intrinsic::aarch64_neon_sqshrun:
635 case Intrinsic::aarch64_neon_sqrshrn:
636 case Intrinsic::aarch64_neon_sqrshrun:
637 case Intrinsic::aarch64_neon_uqshrn:
638 case Intrinsic::aarch64_neon_uqrshrn:
639 case Intrinsic::aarch64_neon_sqneg:
640 case Intrinsic::aarch64_neon_sqabs:
641 case Intrinsic::aarch64_neon_scalar_uqxtn:
642 case Intrinsic::aarch64_neon_scalar_sqxtn:
643 case Intrinsic::aarch64_neon_scalar_sqxtun:
644 case Intrinsic::aarch64_crypto_sha1h:
645 case Intrinsic::aarch64_crypto_sha1c:
646 case Intrinsic::aarch64_crypto_sha1p:
647 case Intrinsic::aarch64_crypto_sha1m:
648 case Intrinsic::aarch64_sisd_fcvtxn:
649 case Intrinsic::aarch64_sisd_fabd:
651 case Intrinsic::aarch64_neon_saddlv: {
652 const LLT SrcTy =
MRI.getType(
MI.getOperand(2).getReg());
653 return SrcTy.getElementType().getSizeInBits() >= 16 &&
654 SrcTy.getElementCount().getFixedValue() >= 4;
659bool AArch64RegisterBankInfo::isPHIWithFPConstraints(
662 if (!
MI.isPHI() ||
Depth > MaxFPRSearchDepth)
666 [&](
const MachineInstr &
UseMI) {
667 if (onlyUsesFP(UseMI, MRI, TRI, Depth + 1))
669 return isPHIWithFPConstraints(UseMI, MRI, TRI, Depth + 1);
673bool AArch64RegisterBankInfo::hasFPConstraints(
const MachineInstr &
MI,
676 unsigned Depth)
const {
677 unsigned Op =
MI.getOpcode();
687 if (
Op != TargetOpcode::COPY && !
MI.isPHI() &&
693 if (RB == &AArch64::FPRRegBank)
695 if (RB == &AArch64::GPRRegBank)
702 if (!
MI.isPHI() ||
Depth > MaxFPRSearchDepth)
705 return any_of(
MI.explicit_uses(), [&](
const MachineOperand &
Op) {
707 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
714 unsigned Depth)
const {
715 switch (
MI.getOpcode()) {
716 case TargetOpcode::G_BITCAST: {
719 [&](
const MachineInstr &
UseMI) {
720 return onlyUsesFP(UseMI, MRI, TRI, Depth + 1) ||
721 prefersFPUse(UseMI, MRI, TRI);
725 case TargetOpcode::G_FPTOSI:
726 case TargetOpcode::G_FPTOUI:
727 case TargetOpcode::G_FPTOSI_SAT:
728 case TargetOpcode::G_FPTOUI_SAT:
729 case TargetOpcode::G_FCMP:
730 case TargetOpcode::G_LROUND:
731 case TargetOpcode::G_LLROUND:
732 case TargetOpcode::G_CLMUL:
733 case AArch64::G_PMULL:
736 case AArch64::G_FPTRUNC_ODD:
738 case TargetOpcode::G_INTRINSIC:
740 case Intrinsic::aarch64_neon_fcvtas:
741 case Intrinsic::aarch64_neon_fcvtau:
742 case Intrinsic::aarch64_neon_fcvtzs:
743 case Intrinsic::aarch64_neon_fcvtzu:
744 case Intrinsic::aarch64_neon_fcvtms:
745 case Intrinsic::aarch64_neon_fcvtmu:
746 case Intrinsic::aarch64_neon_fcvtns:
747 case Intrinsic::aarch64_neon_fcvtnu:
748 case Intrinsic::aarch64_neon_fcvtps:
749 case Intrinsic::aarch64_neon_fcvtpu:
761bool AArch64RegisterBankInfo::onlyDefinesFP(
const MachineInstr &
MI,
764 unsigned Depth)
const {
765 switch (
MI.getOpcode()) {
766 case TargetOpcode::G_SPLAT_VECTOR:
767 case AArch64::G_SADDLP:
768 case AArch64::G_UADDLP:
769 case TargetOpcode::G_SITOFP:
770 case TargetOpcode::G_UITOFP:
771 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
772 case TargetOpcode::G_INSERT_VECTOR_ELT:
773 case TargetOpcode::G_BUILD_VECTOR:
774 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
777 case AArch64::G_FPTRUNC_ODD:
779 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
781 case Intrinsic::aarch64_neon_ld1x2:
782 case Intrinsic::aarch64_neon_ld1x3:
783 case Intrinsic::aarch64_neon_ld1x4:
784 case Intrinsic::aarch64_neon_ld2:
785 case Intrinsic::aarch64_neon_ld2lane:
786 case Intrinsic::aarch64_neon_ld2r:
787 case Intrinsic::aarch64_neon_ld3:
788 case Intrinsic::aarch64_neon_ld3lane:
789 case Intrinsic::aarch64_neon_ld3r:
790 case Intrinsic::aarch64_neon_ld4:
791 case Intrinsic::aarch64_neon_ld4lane:
792 case Intrinsic::aarch64_neon_ld4r:
807 unsigned Depth)
const {
808 switch (
MI.getOpcode()) {
809 case TargetOpcode::G_SITOFP:
810 case TargetOpcode::G_UITOFP:
817bool AArch64RegisterBankInfo::shouldUseFPRForCvtOperand(
818 const MachineInstr &
MI,
bool BankedOpIsDef,
bool ForceFPRForBankedOp16,
819 bool ForceFPRForOtherOp16,
bool AllowFPRCVT,
bool CheckBankedOpUses)
const {
822 const AArch64Subtarget &STI = MF.
getSubtarget<AArch64Subtarget>();
825 unsigned BankedOpIdx = BankedOpIsDef ? 0 : 2;
826 unsigned OtherOpIdx = BankedOpIsDef ? 2 : 0;
828 Register BankedReg =
MI.getOperand(BankedOpIdx).getReg();
832 TypeSize BankedSize =
TRI.getRegSizeInBits(BankedReg,
MRI);
834 TRI.getRegSizeInBits(
MI.getOperand(OtherOpIdx).getReg(),
MRI);
835 if ((ForceFPRForBankedOp16 && BankedSize == 16) ||
836 (ForceFPRForOtherOp16 && OtherSize == 16))
839 if (BankedSize != OtherSize && !AllowFPRCVT)
842 if (CheckBankedOpUses)
845 return onlyUsesFP(UseMI, MRI, TRI) || prefersFPUse(UseMI, MRI, TRI);
853bool AArch64RegisterBankInfo::isLoadFromFPType(
const MachineInstr &
MI)
const {
856 const Value *LdVal = MemOp->getMMO().getValue();
860 Type *EltTy =
nullptr;
862 EltTy = GV->getValueType();
866 if (StructEltTy->getNumElements() == 0)
868 EltTy = StructEltTy->getTypeAtIndex(0U);
876 for (
const auto *LdUser : LdVal->
users()) {
878 EltTy = LdUser->getType();
882 EltTy = LdUser->getOperand(0)->getType();
892 const unsigned Opc =
MI.getOpcode();
897 Opc == TargetOpcode::G_PHI) {
912 case TargetOpcode::G_ADD:
913 case TargetOpcode::G_SUB:
914 case TargetOpcode::G_PTR_ADD:
915 case TargetOpcode::G_MUL:
916 case TargetOpcode::G_SDIV:
917 case TargetOpcode::G_UDIV:
919 case TargetOpcode::G_AND:
920 case TargetOpcode::G_OR:
921 case TargetOpcode::G_XOR:
923 case TargetOpcode::G_FADD:
924 case TargetOpcode::G_FSUB:
925 case TargetOpcode::G_FMUL:
926 case TargetOpcode::G_FDIV:
927 case TargetOpcode::G_FMAXIMUM:
928 case TargetOpcode::G_FMINIMUM:
929 return getSameKindOfOperandsMapping(
MI);
930 case TargetOpcode::G_FPEXT: {
931 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
932 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
939 case TargetOpcode::G_SHL:
940 case TargetOpcode::G_LSHR:
941 case TargetOpcode::G_ASHR: {
942 LLT ShiftAmtTy =
MRI.getType(
MI.getOperand(2).getReg());
943 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
944 if (ShiftAmtTy.
getSizeInBits() == 64 && SrcTy.getSizeInBits() == 32)
947 return getSameKindOfOperandsMapping(
MI);
949 case TargetOpcode::G_BITCAST: {
962 case TargetOpcode::COPY: {
966 if ((DstReg.
isPhysical() || !
MRI.getType(DstReg).isValid()) ||
976 assert(DstRB && SrcRB &&
"Both RegBank were nullptr");
985 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
986 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
989 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
991 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
993 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
998 Opc == TargetOpcode::G_BITCAST ? 2 : 1);
1000 case TargetOpcode::G_CONSTANT: {
1001 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1008 case TargetOpcode::G_BRCOND:
1009 case TargetOpcode::G_FRAME_INDEX: {
1016 MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits()),
1024 unsigned NumOperands =
MI.getNumOperands();
1030 for (
unsigned Idx = 0; Idx < NumOperands; ++Idx) {
1031 auto &MO =
MI.getOperand(Idx);
1032 if (!MO.isReg() || !MO.getReg())
1035 LLT Ty =
MRI.getType(MO.getReg());
1038 OpSize[Idx] = Ty.getSizeInBits().getKnownMinValue();
1046 (MO.isDef() && onlyDefinesFP(
MI,
MRI,
TRI)) ||
1047 (MO.isUse() && onlyUsesFP(
MI,
MRI,
TRI)) ||
1048 Ty.getSizeInBits() > 64)
1058 case TargetOpcode::G_CONSTANT: {
1060 LLT DstTy =
MRI.getType(Dst);
1065 case TargetOpcode::G_FCONSTANT: {
1073 case TargetOpcode::G_SPLAT_VECTOR: {
1074 Register ScalarReg =
MI.getOperand(1).getReg();
1075 LLT ScalarTy =
MRI.getType(ScalarReg);
1076 auto ScalarDef =
MRI.getVRegDef(ScalarReg);
1078 if (ScalarDef->getOpcode() == TargetOpcode::G_LOAD)
1081 onlyDefinesFP(*ScalarDef,
MRI,
TRI))
1093 case TargetOpcode::G_TRUNC: {
1094 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
1095 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128)
1099 case TargetOpcode::G_SITOFP:
1100 case TargetOpcode::G_UITOFP: {
1101 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1107 MRI.getType(SrcReg).getSizeInBits() ==
1108 MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits())
1114 case TargetOpcode::G_FPTOSI_SAT:
1115 case TargetOpcode::G_FPTOUI_SAT:
1116 case TargetOpcode::G_FPTOSI:
1117 case TargetOpcode::G_FPTOUI:
1118 case TargetOpcode::G_INTRINSIC_LRINT:
1119 case TargetOpcode::G_INTRINSIC_LLRINT:
1120 case TargetOpcode::G_LROUND:
1121 case TargetOpcode::G_LLROUND: {
1122 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
1123 if (DstType.isVector())
1131 if (((DstSize == SrcSize) || STI.hasFeature(AArch64::FeatureFPRCVT)) &&
1132 all_of(
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg()),
1134 return onlyUsesFP(UseMI, MRI, TRI) ||
1135 prefersFPUse(UseMI, MRI, TRI);
1142 case TargetOpcode::G_FCMP: {
1147 OpRegBankIdx = {Idx0,
1151 case TargetOpcode::G_BITCAST:
1153 if (OpRegBankIdx[0] != OpRegBankIdx[1])
1159 case TargetOpcode::G_LOAD: {
1174 if (
MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits() < 32)
1180 if (isLoadFromFPType(
MI)) {
1188 if (
any_of(
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg()),
1199 if (isPHIWithFPConstraints(UseMI, MRI, TRI))
1202 return onlyUsesFP(UseMI, MRI, TRI) ||
1203 prefersFPUse(UseMI, MRI, TRI);
1208 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
1209 if (Ty.isScalar() && Ty.getSizeInBits() < 32)
1213 case TargetOpcode::G_STORE:
1226 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
1227 if (Ty.isScalar() && Ty.getSizeInBits() < 32)
1231 case TargetOpcode::G_INDEXED_STORE:
1242 case TargetOpcode::G_INDEXED_SEXTLOAD:
1243 case TargetOpcode::G_INDEXED_ZEXTLOAD:
1247 case TargetOpcode::G_INDEXED_LOAD: {
1248 if (isLoadFromFPType(
MI))
1252 case TargetOpcode::G_SELECT: {
1259 LLT SrcTy =
MRI.getType(
MI.getOperand(2).getReg());
1260 if (SrcTy.isVector()) {
1276 if (
any_of(
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg()),
1293 for (
unsigned Idx = 2; Idx < 4; ++Idx) {
1308 case TargetOpcode::G_UNMERGE_VALUES: {
1314 LLT SrcTy =
MRI.getType(
MI.getOperand(
MI.getNumOperands()-1).getReg());
1317 if (SrcTy.isVector() || SrcTy ==
LLT::scalar(128) ||
1318 any_of(
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg()),
1321 for (
unsigned Idx = 0, NumOperands =
MI.getNumOperands();
1322 Idx < NumOperands; ++Idx)
1327 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1335 case AArch64::G_SQSHLU_I:
1344 case TargetOpcode::G_INSERT_VECTOR_ELT:
1358 case TargetOpcode::G_EXTRACT: {
1360 auto Src =
MI.getOperand(1).getReg();
1361 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
1362 if (SrcTy.getSizeInBits() != 128)
1364 auto Idx =
MRI.getRegClassOrNull(Src) == &AArch64::XSeqPairsClassRegClass
1367 OpRegBankIdx[0] = Idx;
1368 OpRegBankIdx[1] = Idx;
1371 case TargetOpcode::G_BUILD_VECTOR: {
1386 unsigned DefOpc =
DefMI->getOpcode();
1387 const LLT SrcTy =
MRI.getType(VReg);
1390 return Op.isDef() || mi_match(Op.getReg(), MRI, m_ICst(Cst));
1394 SrcTy.getSizeInBits() < 32 ||
1398 unsigned NumOperands =
MI.getNumOperands();
1399 for (
unsigned Idx = 0; Idx < NumOperands; ++Idx)
1404 case TargetOpcode::G_VECREDUCE_FADD:
1405 case TargetOpcode::G_VECREDUCE_FMUL:
1406 case TargetOpcode::G_VECREDUCE_FMAX:
1407 case TargetOpcode::G_VECREDUCE_FMIN:
1408 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
1409 case TargetOpcode::G_VECREDUCE_FMINIMUM:
1410 case TargetOpcode::G_VECREDUCE_ADD:
1411 case TargetOpcode::G_VECREDUCE_MUL:
1412 case TargetOpcode::G_VECREDUCE_AND:
1413 case TargetOpcode::G_VECREDUCE_OR:
1414 case TargetOpcode::G_VECREDUCE_XOR:
1415 case TargetOpcode::G_VECREDUCE_SMAX:
1416 case TargetOpcode::G_VECREDUCE_SMIN:
1417 case TargetOpcode::G_VECREDUCE_UMAX:
1418 case TargetOpcode::G_VECREDUCE_UMIN:
1423 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
1424 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
1429 case TargetOpcode::G_INTRINSIC:
1430 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
1432 case Intrinsic::aarch64_neon_fcvtas:
1433 case Intrinsic::aarch64_neon_fcvtau:
1434 case Intrinsic::aarch64_neon_fcvtzs:
1435 case Intrinsic::aarch64_neon_fcvtzu:
1436 case Intrinsic::aarch64_neon_fcvtms:
1437 case Intrinsic::aarch64_neon_fcvtmu:
1438 case Intrinsic::aarch64_neon_fcvtns:
1439 case Intrinsic::aarch64_neon_fcvtnu:
1440 case Intrinsic::aarch64_neon_fcvtps:
1441 case Intrinsic::aarch64_neon_fcvtpu: {
1443 if (shouldUseFPRForCvtOperand(
MI,
true,
1453 case Intrinsic::aarch64_neon_vcvtfxs2fp:
1454 case Intrinsic::aarch64_neon_vcvtfxu2fp: {
1456 if (shouldUseFPRForCvtOperand(
MI,
false,
1466 case Intrinsic::aarch64_neon_vcvtfp2fxs:
1467 case Intrinsic::aarch64_neon_vcvtfp2fxu: {
1469 if (shouldUseFPRForCvtOperand(
MI,
true,
1484 for (
const auto &
Op :
MI.defs()) {
1490 Idx +=
MI.getNumExplicitDefs();
1493 for (
const auto &
Op :
MI.explicit_uses()) {
1507 for (
unsigned Idx = 0; Idx < NumOperands; ++Idx) {
1508 if (
MI.getOperand(Idx).isReg() &&
MI.getOperand(Idx).getReg()) {
1509 LLT Ty =
MRI.getType(
MI.getOperand(Idx).getReg());
1514 if (!Mapping->isValid())
1517 OpdsMapping[Idx] = Mapping;
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool foldTruncOfI32Constant(MachineInstr &MI, unsigned OpIdx, MachineRegisterInfo &MRI)
#define CHECK_VALUEMAP(RBName, Size)
static bool isFPIntrinsic(const MachineRegisterInfo &MRI, const MachineInstr &MI)
#define CHECK_VALUEMAP_3OPS(RBName, Size)
static const unsigned CustomMappingID
#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)
#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)
#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize)
static bool preferGPRForFPImm(const MachineInstr &MI, const MachineRegisterInfo &MRI, const AArch64Subtarget &STI)
This file declares the targeting of the RegisterBankInfo class for AArch64.
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
static bool isAtomic(MachineBasicBlock::iterator I)
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static const MCPhysReg FPR[]
FPR - The set of FP registers that should be allocated for arguments on Darwin and AIX.
MachineRegisterInfo & MRI
This file defines the SmallVector class.
static unsigned getRegBankBaseIdxOffset(unsigned RBIdx, TypeSize Size)
static const RegisterBankInfo::ValueMapping * getCopyMapping(unsigned DstBankID, unsigned SrcBankID, TypeSize Size)
Get the pointer to the ValueMapping of the operands of a copy instruction from the SrcBankID register...
static bool checkPartialMappingIdx(PartialMappingIdx FirstAlias, PartialMappingIdx LastAlias, ArrayRef< PartialMappingIdx > Order)
static const RegisterBankInfo::PartialMapping PartMappings[]
static const RegisterBankInfo::ValueMapping * getFPExtMapping(unsigned DstSize, unsigned SrcSize)
Get the instruction mapping for G_FPEXT.
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx RBIdx, TypeSize Size)
Get the pointer to the ValueMapping representing the RegisterBank at RBIdx with a size of Size.
static const RegisterBankInfo::ValueMapping ValMappings[]
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const override
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const override
Get a register bank that covers RC.
AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
const AArch64RegisterInfo * getRegisterInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
Class for arbitrary precision integers.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
static LLT integer(unsigned SizeInBits)
unsigned getID() const
getID() - Return the register class ID number.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
const RegisterBank * getRegBank(Register Reg) const
Return the register bank of Reg.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setRegBank(Register Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
unsigned getMaximumSize(unsigned RegBankID) const
Get the maximum size in bits that fits in the given register bank.
virtual const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const
Get a register bank that covers RC.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
SmallVector< const InstructionMapping *, 4 > InstructionMappings
Convenient type to represent the alternatives for mapping an instruction.
virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
LLVM_ABI bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Type * getArrayElementType() const
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
iterator_range< user_iterator > users()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool expandVectorMOVImm(APInt Imm, SmallVectorImpl< ImmInsnModel > &Insn, const AArch64Subtarget &ST)
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
bool isPreISelGenericOptimizationHint(unsigned Opcode)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
void call_once(once_flag &flag, Function &&F, Args &&... ArgList)
Execute the function specified as a parameter once.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
MCRegisterClass TargetRegisterClass
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
The llvm::once_flag structure.