37#define GET_CC_REGISTER_LISTS
38#include "AArch64GenCallingConv.inc"
39#define GET_REGINFO_TARGET_DESC
40#include "AArch64GenRegisterInfo.inc"
54 if (AArch64::PPRRegClass.
contains(Reg))
57 if (AArch64::ZPRRegClass.
contains(Reg)) {
58 RegToUseForCFI = getSubReg(Reg, AArch64::dsub);
59 for (
int I = 0; CSR_AArch64_AAPCS_SaveList[
I]; ++
I) {
60 if (CSR_AArch64_AAPCS_SaveList[
I] == RegToUseForCFI)
72 assert(MF &&
"Invalid MachineFunction pointer.");
81 if (TLI->supportSwiftError() &&
82 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError)) {
84 return CSR_Darwin_AArch64_AAPCS_SwiftError_SaveList;
86 return CSR_Win_AArch64_AAPCS_SwiftError_SaveList;
87 return CSR_AArch64_AAPCS_SwiftError_SaveList;
90 switch (
F.getCallingConv()) {
94 return CSR_AArch64_NoRegs_SaveList;
98 return CSR_AArch64_NoneRegs_SaveList;
101 return CSR_AArch64_AllRegs_SaveList;
104 return CSR_Win_AArch64_Arm64EC_Thunk_SaveList;
108 return CSR_Darwin_AArch64_RT_MostRegs_SaveList;
110 return CSR_Win_AArch64_RT_MostRegs_SaveList;
111 return CSR_AArch64_RT_MostRegs_SaveList;
115 return CSR_Darwin_AArch64_RT_AllRegs_SaveList;
117 return CSR_Win_AArch64_RT_AllRegs_SaveList;
118 return CSR_AArch64_RT_AllRegs_SaveList;
123 "Calling convention CFGuard_Check is unsupported on Darwin.");
124 return CSR_Win_AArch64_CFGuard_Check_SaveList;
128 return CSR_Darwin_AArch64_AAPCS_SwiftTail_SaveList;
130 return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList;
131 return CSR_AArch64_AAPCS_SwiftTail_SaveList;
135 return CSR_Darwin_AArch64_AAVPCS_SaveList;
137 return CSR_Win_AArch64_AAVPCS_SaveList;
138 return CSR_AArch64_AAVPCS_SaveList;
143 "Calling convention SVE_VectorCall is unsupported on Darwin.");
145 return CSR_Win_AArch64_SVE_AAPCS_SaveList;
146 return CSR_AArch64_SVE_AAPCS_SaveList;
150 "Calling convention "
151 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is only "
152 "supported to improve calls to SME ACLE save/restore/disable-za "
153 "functions, and is not intended to be used beyond that scope.");
157 "Calling convention "
158 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
159 "only supported to improve calls to SME ACLE __arm_get_current_vg "
160 "function, and is not intended to be used beyond that scope.");
164 "Calling convention "
165 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
166 "only supported to improve calls to SME ACLE __arm_sme_state "
167 "and is not intended to be used beyond that scope.");
171 return CSR_Darwin_AArch64_AAPCS_Win64_SaveList;
173 return CSR_Win_AArch64_AAPCS_SaveList;
174 return CSR_AArch64_AAPCS_X18_SaveList;
178 return AFI.isSplitCSR() ? CSR_Darwin_AArch64_CXX_TLS_PE_SaveList
179 : CSR_Darwin_AArch64_CXX_TLS_SaveList;
186 return AFI.hasSVE_AAPCS(*MF) ? CSR_Darwin_AArch64_SVE_AAPCS_SaveList
187 : CSR_Darwin_AArch64_AAPCS_SaveList;
189 return AFI.hasSVE_AAPCS(*MF) ? CSR_Win_AArch64_SVE_AAPCS_SaveList
190 : CSR_Win_AArch64_AAPCS_SaveList;
191 return AFI.hasSVE_AAPCS(*MF) ? CSR_AArch64_SVE_AAPCS_SaveList
192 : CSR_AArch64_AAPCS_SaveList;
198 assert(MF &&
"Invalid MachineFunction pointer.");
201 return CSR_Darwin_AArch64_CXX_TLS_ViaCopy_SaveList;
212 for (
size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
214 UpdatedCSRs.
push_back(AArch64::GPR64commonRegClass.getRegister(i));
224 unsigned Idx)
const {
226 if (RC == &AArch64::GPR32allRegClass && Idx == AArch64::hsub)
227 return &AArch64::FPR32RegClass;
228 else if (RC == &AArch64::GPR64allRegClass && Idx == AArch64::hsub)
229 return &AArch64::FPR64RegClass;
232 return AArch64GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
239 "Invalid subtarget for getDarwinCallPreservedMask");
242 return CSR_Darwin_AArch64_CXX_TLS_RegMask;
244 return CSR_Darwin_AArch64_AAVPCS_RegMask;
246 return CSR_Darwin_AArch64_SVE_AAPCS_RegMask;
248 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
250 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
252 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
255 "Calling convention CFGuard_Check is unsupported on Darwin.");
260 return CSR_Darwin_AArch64_AAPCS_SwiftError_RegMask;
262 return CSR_Darwin_AArch64_AAPCS_SwiftTail_RegMask;
264 return CSR_Darwin_AArch64_RT_MostRegs_RegMask;
266 return CSR_Darwin_AArch64_RT_AllRegs_RegMask;
267 return CSR_Darwin_AArch64_AAPCS_RegMask;
276 return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
278 return SCS ? CSR_AArch64_NoneRegs_SCS_RegMask
279 : CSR_AArch64_NoneRegs_RegMask;
281 return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
291 return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
293 return SCS ? CSR_AArch64_SVE_AAPCS_SCS_RegMask
294 : CSR_AArch64_SVE_AAPCS_RegMask;
296 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
298 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
300 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
302 return CSR_Win_AArch64_CFGuard_Check_RegMask;
306 return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
307 : CSR_AArch64_AAPCS_SwiftError_RegMask;
311 return CSR_AArch64_AAPCS_SwiftTail_RegMask;
314 return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
315 : CSR_AArch64_RT_MostRegs_RegMask;
317 return SCS ? CSR_AArch64_RT_AllRegs_SCS_RegMask
318 : CSR_AArch64_RT_AllRegs_RegMask;
320 return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
326 return CSR_AArch64_AAPCS_RegMask;
333 return CSR_Darwin_AArch64_TLS_RegMask;
335 assert(TT.isOSBinFormatELF() &&
"Invalid target");
336 return CSR_AArch64_TLS_ELF_RegMask;
343 memcpy(UpdatedMask, *Mask,
sizeof(UpdatedMask[0]) * RegMaskSize);
345 for (
size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
348 subregs_inclusive(AArch64::GPR64commonRegClass.getRegister(i))) {
351 UpdatedMask[SubReg / 32] |= 1u << (SubReg % 32);
359 return CSR_AArch64_SMStartStop_RegMask;
364 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
368 return CSR_AArch64_NoRegs_RegMask;
383 return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask;
384 return CSR_AArch64_AAPCS_ThisReturn_RegMask;
388 return CSR_AArch64_StackProbe_Windows_RegMask;
391std::optional<std::string>
395 return std::string(
"X19 is used as the frame base pointer register.");
406 for (
unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
412 " is clobbered by asynchronous signals when using Arm64EC.";
423 markSuperRegs(
Reserved, AArch64::WSP);
424 markSuperRegs(
Reserved, AArch64::WZR);
427 markSuperRegs(
Reserved, AArch64::W29);
432 markSuperRegs(
Reserved, AArch64::W13);
433 markSuperRegs(
Reserved, AArch64::W14);
434 markSuperRegs(
Reserved, AArch64::W23);
435 markSuperRegs(
Reserved, AArch64::W24);
436 markSuperRegs(
Reserved, AArch64::W28);
437 for (
unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
442 markSuperRegs(
Reserved, AArch64::W28);
443 markSuperRegs(
Reserved, AArch64::W27);
444 markSuperRegs(
Reserved, AArch64::W26);
445 markSuperRegs(
Reserved, AArch64::W25);
447 markSuperRegs(
Reserved, AArch64::LR);
448 markSuperRegs(
Reserved, AArch64::W30);
452 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
454 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
458 markSuperRegs(
Reserved, AArch64::W19);
462 markSuperRegs(
Reserved, AArch64::W16);
470 for (
MCPhysReg SubReg : subregs_inclusive(AArch64::ZA))
483 markSuperRegs(
Reserved, AArch64::FPCR);
484 markSuperRegs(
Reserved, AArch64::FPMR);
485 markSuperRegs(
Reserved, AArch64::FPSR);
488 markSuperRegs(
Reserved, AArch64::X27);
489 markSuperRegs(
Reserved, AArch64::X28);
490 markSuperRegs(
Reserved, AArch64::W27);
491 markSuperRegs(
Reserved, AArch64::W28);
500 static_assert(AArch64::W30_HI - AArch64::W0_HI == 30,
501 "Unexpected order of registers");
502 Reserved.set(AArch64::W0_HI, AArch64::W30_HI + 1);
503 static_assert(AArch64::B31_HI - AArch64::B0_HI == 31,
504 "Unexpected order of registers");
505 Reserved.set(AArch64::B0_HI, AArch64::B31_HI + 1);
506 static_assert(AArch64::H31_HI - AArch64::H0_HI == 31,
507 "Unexpected order of registers");
508 Reserved.set(AArch64::H0_HI, AArch64::H31_HI + 1);
509 static_assert(AArch64::S31_HI - AArch64::S0_HI == 31,
510 "Unexpected order of registers");
511 Reserved.set(AArch64::S0_HI, AArch64::S31_HI + 1);
512 static_assert(AArch64::D31_HI - AArch64::D0_HI == 31,
513 "Unexpected order of registers");
514 Reserved.set(AArch64::D0_HI, AArch64::D31_HI + 1);
515 static_assert(AArch64::Q31_HI - AArch64::Q0_HI == 31,
516 "Unexpected order of registers");
517 Reserved.set(AArch64::Q0_HI, AArch64::Q31_HI + 1);
525 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
529 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
537 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
539 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
551 markSuperRegs(
Reserved, AArch64::W30);
579 for (
size_t i = 0; i < 8; ++i) {
590 " function calls if any of the argument registers is reserved.")});
603 if (PhysReg == AArch64::ZA || PhysReg == AArch64::ZT0)
611 if (RC == &AArch64::CCRRegClass)
612 return &AArch64::GPR64RegClass;
630 if (hasStackRealignment(MF))
635 if (ST.hasSVE() || ST.isStreaming()) {
638 if (!AFI->hasCalculatedStackSizeSVE() || AFI->hasSVEStackSize())
649 if (ST.getStreamingHazardSize() &&
650 !AFI->getSMEFnAttrs().hasNonStreamingInterfaceAndBody()) {
682 return HasReg(CC_AArch64_GHC_ArgRegs, Reg);
685 return HasReg(CC_AArch64_Preserve_None_ArgRegs, Reg);
697 return HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
700 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
703 return HasReg(CC_AArch64_Win64PCS_Swift_ArgRegs, Reg) ||
704 HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
710 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
713 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg) ||
714 HasReg(CC_AArch64_AAPCS_Swift_ArgRegs, Reg);
720 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg);
723 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg) ||
724 HasReg(CC_AArch64_DarwinPCS_Swift_ArgRegs, Reg);
728 return HasReg(CC_AArch64_DarwinPCS_ILP32_VarArg_ArgRegs, Reg);
729 return HasReg(CC_AArch64_DarwinPCS_VarArg_ArgRegs, Reg);
732 HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
733 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
735 return HasReg(CC_AArch64_Win64_CFGuard_Check_ArgRegs, Reg);
742 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
743 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
750 return TFI->
hasFP(MF) ? AArch64::FP : AArch64::SP;
777 "Expected SVE area to be calculated by this point");
801 for (
unsigned i = 0; !
MI->getOperand(i).isFI(); ++i)
802 assert(i < MI->getNumOperands() &&
803 "Instr doesn't have FrameIndex operand!");
814 if (!
MI->mayLoad() && !
MI->mayStore())
829 int64_t FPOffset =
Offset - 16 * 20;
866 assert(
MI &&
"Unable to get the legal offset for nil instruction.");
879 if (Ins !=
MBB->end())
880 DL = Ins->getDebugLoc();
904 while (!
MI.getOperand(i).isFI()) {
906 assert(i <
MI.getNumOperands() &&
"Instr doesn't have FrameIndex operand!");
913 assert(
Done &&
"Unable to resolve frame index!");
927 if (
MI.getOpcode() == AArch64::STGloop ||
928 MI.getOpcode() == AArch64::STZGloop) {
929 assert(FIOperandNum == 3 &&
930 "Wrong frame index operand for STGloop/STZGloop");
931 unsigned Op =
MI.getOpcode() == AArch64::STGloop ? AArch64::STGloop_wback
932 : AArch64::STZGloop_wback;
933 ScratchReg =
MI.getOperand(1).getReg();
934 MI.getOperand(3).ChangeToRegister(ScratchReg,
false,
false,
true);
936 MI.tieOperands(1, 3);
939 MI.getMF()->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
940 MI.getOperand(FIOperandNum)
941 .ChangeToRegister(ScratchReg,
false,
false,
true);
951 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
957 int64_t VGSized =
Offset.getScalable() / 2;
959 Ops.push_back(dwarf::DW_OP_constu);
960 Ops.push_back(VGSized);
961 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
962 Ops.push_back(dwarf::DW_OP_mul);
963 Ops.push_back(dwarf::DW_OP_plus);
964 }
else if (VGSized < 0) {
965 Ops.push_back(dwarf::DW_OP_constu);
966 Ops.push_back(-VGSized);
967 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
968 Ops.push_back(dwarf::DW_OP_mul);
969 Ops.push_back(dwarf::DW_OP_minus);
974 int SPAdj,
unsigned FIOperandNum,
976 assert(SPAdj == 0 &&
"Unexpected");
985 int FrameIndex =
MI.getOperand(FIOperandNum).getIndex();
991 if (
MI.getOpcode() == TargetOpcode::STACKMAP ||
992 MI.getOpcode() == TargetOpcode::PATCHPOINT ||
993 MI.getOpcode() == TargetOpcode::STATEPOINT) {
999 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg,
false );
1000 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(
Offset.getFixed());
1004 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) {
1008 "Frame offsets with a scalable component are not supported");
1014 if (
MI.getOpcode() == AArch64::TAGPstack) {
1017 FrameReg =
MI.getOperand(3).getReg();
1020 }
else if (Tagged) {
1029 MF, FrameIndex, FrameReg,
false,
true);
1038 MI.getOperand(FIOperandNum)
1039 .ChangeToRegister(ScratchReg,
false,
false,
true);
1042 FrameReg = AArch64::SP;
1047 MF, FrameIndex, FrameReg,
false,
true);
1054 assert((!RS || !RS->isScavengingFrameIndex(FrameIndex)) &&
1055 "Emergency spill slot is out of reach");
1070 switch (RC->
getID()) {
1073 case AArch64::GPR32RegClassID:
1074 case AArch64::GPR32spRegClassID:
1075 case AArch64::GPR32allRegClassID:
1076 case AArch64::GPR64spRegClassID:
1077 case AArch64::GPR64allRegClassID:
1078 case AArch64::GPR64RegClassID:
1079 case AArch64::GPR32commonRegClassID:
1080 case AArch64::GPR64commonRegClassID:
1082 - (TFI->
hasFP(MF) || TT.isOSDarwin())
1085 case AArch64::FPR8RegClassID:
1086 case AArch64::FPR16RegClassID:
1087 case AArch64::FPR32RegClassID:
1088 case AArch64::FPR64RegClassID:
1089 case AArch64::FPR128RegClassID:
1092 case AArch64::MatrixIndexGPR32_8_11RegClassID:
1093 case AArch64::MatrixIndexGPR32_12_15RegClassID:
1096 case AArch64::DDRegClassID:
1097 case AArch64::DDDRegClassID:
1098 case AArch64::DDDDRegClassID:
1099 case AArch64::QQRegClassID:
1100 case AArch64::QQQRegClassID:
1101 case AArch64::QQQQRegClassID:
1104 case AArch64::FPR128_loRegClassID:
1105 case AArch64::FPR64_loRegClassID:
1106 case AArch64::FPR16_loRegClassID:
1108 case AArch64::FPR128_0to7RegClassID:
1119 if (!ST.useDistinctPredicateDstReg() ||
1120 !AArch64::PPRRegClass.hasSubClassEq(RegRC) || !MRI.
hasOneDef(VirtReg) ||
1131 Op1Reg = VRM->
getPhys(Op1Reg);
1146 for (
unsigned I = 0;; ++
I) {
1150 if (AArch64::PPRRegClass.
contains(R))
1160 bool PrefA = (
A != Op1Reg) && CanUseReg(
A);
1161 bool PrefB = (
B != Op1Reg) && CanUseReg(
B);
1162 return PrefA && !PrefB;
1197 bool ConsiderOnlyHints =
1204 if (AArch64::ZPRRegClass.hasSubClassEq(RegRC)) {
1207 if (DefOp.isImplicit() ||
1212 unsigned InstFlags =
1216 auto AddHintIfSuitable = [&](
MCPhysReg R,
1221 if (PhysReg && MO.getSubReg())
1222 PhysReg = getSubReg(PhysReg, MO.getSubReg());
1233 AddHintIfSuitable(R, Def.getOperand(2)) ||
1234 AddHintIfSuitable(R, Def.getOperand(3)) ||
1235 AddHintIfSuitable(R, Def.getOperand(4));
1239 AddHintIfSuitable(R, Def.getOperand(2)) ||
1240 AddHintIfSuitable(R, Def.getOperand(3));
1244 AddHintIfSuitable(R, Def.getOperand(2));
1247 AddHintIfSuitable(R, Def.getOperand(3));
1251 AddHintIfSuitable(R, Def.getOperand(1));
1258 return ConsiderOnlyHints;
1263 return ConsiderOnlyHints;
1265 if (!ST.hasSME() || !ST.isStreaming())
1266 return ConsiderOnlyHints;
1276 unsigned RegID = RegRC->
getID();
1277 if (RegID == AArch64::ZPR2StridedOrContiguousRegClassID ||
1278 RegID == AArch64::ZPR4StridedOrContiguousRegClassID) {
1282 if (
Use.getOpcode() != AArch64::COPY_INTO_TRANSPOSED_TUPLE)
1288 if (!Src.getSubReg() || !Dst.getSubReg())
1293 case AArch64::ZPR2StridedOrContiguousRegClassID:
1294 StridedRC = &AArch64::ZPR2StridedRegClass;
1296 case AArch64::ZPR4StridedOrContiguousRegClassID:
1297 StridedRC = &AArch64::ZPR4StridedRegClass;
1308 unsigned TupleSize =
Use.getOperand(2).getImm();
1309 unsigned TupIdx = Dst.getSubReg() - AArch64::zsub0;
1312 bool IsMulZPR = TupleID == AArch64::ZPR2Mul2RegClassID ||
1313 TupleID == AArch64::ZPR4Mul4RegClassID;
1318 auto &Src = Def.getOperand(1);
1319 return Def.getOpcode() ==
Use.getOpcode() &&
1360 if (CopyWithAssignedSrc ==
Copies.end()) {
1363 for (
unsigned I = 0;
I < StridedOrder.
size(); ++
I) {
1368 unsigned SubRegIdx = Src.getSubReg();
1370 (getSubReg(Reg, SubRegIdx) - AArch64::Z0) % TupleSize != TupIdx)
1376 auto IsFreeConsecutiveReg = [&](
unsigned I) {
1377 unsigned R = Reg - TupIdx +
I;
1380 ((getSubReg(R, AArch64::zsub0) - AArch64::Z0) ==
1381 (getSubReg(R - 1, AArch64::zsub0) - AArch64::Z0) + 1)) &&
1382 !
Matrix->isPhysRegUsed(R);
1384 if (
all_of(
seq(0U, TupleSize), IsFreeConsecutiveReg))
1397 unsigned AssignedTupIdx = AssignedDst.
getSubReg() - AArch64::zsub0;
1399 getSubReg(VRM->
getPhys(AssignedSrc.
getReg()), AArch64::zsub0) +
1400 (TupIdx - AssignedTupIdx);
1402 for (
unsigned I = 0;
I < StridedOrder.
size(); ++
I)
1403 if (getSubReg(StridedOrder[
I], AArch64::zsub0) == TargetStartReg)
1404 Hints.
insert(StridedOrder[
I]);
1408 return ConsiderOnlyHints;
1413 if (Def.getOpcode() != AArch64::COPY_INTO_TRANSPOSED_TUPLE)
1419 if (!Src.getSubReg() || !Dst.getSubReg())
1426 if (!VRM->
hasPhys(Src.getReg()))
1434 if (getSubReg(R, Dst.getSubReg()) == SrcZPR)
1439 return ConsiderOnlyHints;
1447 else if (hasStackRealignment(MF))
1465 ((DstRC->
getID() == AArch64::GPR64RegClassID) ||
1466 (DstRC->
getID() == AArch64::GPR64commonRegClassID)) &&
1467 MI->getOperand(0).getSubReg() &&
MI->getOperand(1).getSubReg())
1474 switch (
MI.getOpcode()) {
1475 case AArch64::COALESCER_BARRIER_FPR16:
1476 case AArch64::COALESCER_BARRIER_FPR32:
1477 case AArch64::COALESCER_BARRIER_FPR64:
1478 case AArch64::COALESCER_BARRIER_FPR128:
1494 if (
MI->isCopy() && SubReg != DstSubReg &&
1495 (AArch64::ZPRRegClass.hasSubClassEq(DstRC) ||
1496 AArch64::ZPRRegClass.hasSubClassEq(SrcRC))) {
1497 unsigned SrcReg =
MI->getOperand(1).getReg();
1500 unsigned DstReg =
MI->getOperand(0).getReg();
1510 return R == AArch64::VG;
1514 return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
1515 (LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool HandleDestructivePredicateHint(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallSetVector< MCPhysReg, 16 > &Hints, const VirtRegMap *VRM, const MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const AArch64Subtarget &ST, const LiveRegMatrix *Matrix)
static Register createScratchRegisterForInstruction(MachineInstr &MI, unsigned FIOperandNum, const AArch64InstrInfo *TII)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static unsigned getDwarfRegNum(MCRegister Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, int FI) const override
getNonLocalFrameIndexReference - This method returns the offset used to reference a frame index locat...
bool isFPReserved(const MachineFunction &MF) const
Should the Frame Pointer be reserved for the current function?
StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, bool PreferFP, bool ForSimm) const
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
unsigned getTaggedBasePointerOffset() const
bool hasStackHazardSlotIndex() const
bool hasCalculatedStackSizeSVE() const
bool hasSVEStackSize() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
BitVector getStrictlyReservedRegs(const MachineFunction &MF) const
const TargetRegisterClass * getCrossCopyRegClass(const TargetRegisterClass *RC) const override
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
MCRegister getBaseRegister() const
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const MCPhysReg * getCalleeSavedRegsViaCopy(const MachineFunction *MF) const
bool isIgnoredCVReg(MCRegister LLVMReg) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
bool shouldCoalesce(MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override
SrcRC and DstRC will be morphed into NewRC if this returns true.
bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override
bool isUserReservedReg(const MachineFunction &MF, MCRegister Reg) const
const TargetRegisterClass * getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const override
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, int64_t Offset) const override
Insert defining instruction(s) for BaseReg to be a pointer to FrameIdx at the beginning of the basic ...
void UpdateCustomCalleeSavedRegs(MachineFunction &MF) const
bool requiresRegisterScavenging(const MachineFunction &MF) const override
bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, int64_t Offset) const override
BitVector getUserReservedRegs(const MachineFunction &MF) const
void resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const override
bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override
needsFrameBaseReg - Returns true if the instruction's frame index reference would be better served by...
const uint32_t * getWindowsStackProbePreservedMask() const
Stack probing calls preserve different CSRs to the normal CC.
bool regNeedsCFI(MCRegister Reg, MCRegister &RegToUseForCFI) const
Return whether the register needs a CFI entry.
bool isAnyArgRegReserved(const MachineFunction &MF) const
void emitReservedArgRegCallError(const MachineFunction &MF) const
bool isStrictlyReservedReg(const MachineFunction &MF, MCRegister Reg) const
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override
const uint32_t * getTLSCallPreservedMask() const
const uint32_t * getNoPreservedMask() const override
Register getFrameRegister(const MachineFunction &MF) const override
bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const override
void getOffsetOpcodes(const StackOffset &Offset, SmallVectorImpl< uint64_t > &Ops) const override
bool isAsmClobberable(const MachineFunction &MF, MCRegister PhysReg) const override
AArch64RegisterInfo(const Triple &TT, unsigned HwMode)
const uint32_t * SMEABISupportRoutinesCallPreservedMaskFromX0() const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
const uint32_t * getCustomEHPadPreservedMask(const MachineFunction &MF) const override
unsigned getLocalAddressRegister(const MachineFunction &MF) const
bool hasBasePointer(const MachineFunction &MF) const
const uint32_t * getDarwinCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const
const uint32_t * getSMStartStopCallPreservedMask() const
bool useFPForScavengingIndex(const MachineFunction &MF) const override
bool cannotEliminateFrame(const MachineFunction &MF) const
bool isArgumentRegister(const MachineFunction &MF, MCRegister Reg) const override
void UpdateCustomCallPreservedMask(MachineFunction &MF, const uint32_t **Mask) const
bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallSetVector< MCPhysReg, 16 > &Hints, const MachineFunction &MF, const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const override
std::optional< std::string > explainReservedReg(const MachineFunction &MF, MCRegister PhysReg) const override
bool requiresFrameIndexScavenging(const MachineFunction &MF) const override
bool enableSRLTSubregToRegMitigation() const
bool isLRReservedForRA() const
bool isTargetDarwin() const
bool isTargetILP32() const
bool isXRegisterReservedForRA(size_t i) const
const AArch64TargetLowering * getTargetLowering() const override
bool isXRegCustomCalleeSaved(size_t i) const
bool isTargetWindowsOrUEFI() const
UEFI follows the Windows ARM64 ABI and produces PE/COFF images, so most of the Windows specific ABI h...
bool isWindowsArm64EC() const
bool isXRegisterReserved(size_t i) const
bool isCallingConvWin64(CallingConv::ID CC, bool IsVarArg) const
bool isTargetLinux() const
bool supportSwiftError() const override
Return true if the target supports swifterror attribute.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool regsOverlap(MCRegister RegA, MCRegister RegB) const
Returns true if the two registers are equal or alias each other.
Wrapper class representing physical registers. Should be passed by value.
MCSubRegIterator enumerates all sub-registers of Reg.
bool isValid() const
Returns true if this iterator is not yet at the end.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
int64_t getLocalFrameSize() const
Get the size of the local object blob.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
uint32_t * allocateRegMask()
Allocate and initialize a register mask with NumRegister bits.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineFunctionProperties & getProperties() const
Get the function properties.
bool hasEHFunclets() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static unsigned getRegMaskSize(unsigned NumRegs)
Returns number of elements needed for a regmask array.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< def_instr_iterator > def_instructions(Register Reg) const
bool subRegLivenessEnabled() const
MachineOperand * getOneDef(Register Reg) const
Returns the defining operand if there is exactly one operand defining the specified register,...
defusechain_instr_iterator< false, true, false, true > def_instr_iterator
def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the specified register,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
iterator_range< def_iterator > def_operands(Register Reg) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
LLVM_ABI void setCalleeSavedRegs(ArrayRef< MCPhysReg > CSRs)
Sets the updated Callee Saved Registers list.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
Vector takeVector()
Clear the SetVector and return the underlying vector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
virtual bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallSetVector< MCPhysReg, 16 > &Hints, const MachineFunction &MF, const VirtRegMap *VRM=nullptr, const LiveRegMatrix *Matrix=nullptr) const
Get a list of 'hint' registers that the register allocator should try first when allocating a physica...
Triple - Helper class for working with autoconf configuration names.
A Use represents the edge between a Value definition and its users.
MCRegister getPhys(Register virtReg) const
returns the physical register mapped to the specified virtual register
bool hasPhys(Register virtReg) const
returns true if the specified virtual register is mapped to a physical register
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
A range adaptor for a pair of iterators.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
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 initLLVMToCVRegMapping(MCRegisterInfo *MRI)
@ DestructiveBinaryShImmUnpred
@ DestructiveInstTypeMask
@ DestructiveUnaryPassthru
@ DestructiveBinaryImmUnpred
@ DestructiveTernaryCommWithRev
@ DestructiveBinaryCommWithRev
int32_t getSVEPseudoMap(uint32_t Opcode)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AArch64_VectorCall
Used between AArch64 Advanced SIMD functions.
@ Swift
Calling convention for Swift.
@ AArch64_SVE_VectorCall
Used between AArch64 SVE functions.
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ AnyReg
OBSOLETED - Used for stack based JavaScript calls.
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2
Preserve X2-X15, X19-X29, SP, Z0-Z31, P0-P15.
@ CXX_FAST_TLS
Used for access functions.
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0
Preserve X0-X13, X19-X29, SP, Z0-Z31, P0-P15.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1
Preserve X1-X15, X19-X29, SP, Z0-Z31, P0-P15.
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ ARM64EC_Thunk_X64
Calling convention used in the ARM64EC ABI to implement calls between x64 code and thunks.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset, bool *OutUseUnscaledOp=nullptr, unsigned *OutUnscaledOp=nullptr, int64_t *EmittableOffset=nullptr)
Check if the Offset is a valid frame offset for MI.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, StackOffset &Offset, const AArch64InstrInfo *TII)
rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
MCRegisterClass TargetRegisterClass