38#define GET_CC_REGISTER_LISTS
39#include "AArch64GenCallingConv.inc"
40#define GET_REGINFO_TARGET_DESC
41#include "AArch64GenRegisterInfo.inc"
55 if (AArch64::PPRRegClass.
contains(Reg))
58 if (AArch64::ZPRRegClass.
contains(Reg)) {
59 RegToUseForCFI = getSubReg(Reg, AArch64::dsub);
60 for (
int I = 0; CSR_AArch64_AAPCS_SaveList[
I]; ++
I) {
61 if (CSR_AArch64_AAPCS_SaveList[
I] == RegToUseForCFI)
73 assert(MF &&
"Invalid MachineFunction pointer.");
79 return CSR_AArch64_NoRegs_SaveList;
81 return CSR_AArch64_NoneRegs_SaveList;
83 return CSR_AArch64_AllRegs_SaveList;
86 return CSR_Win_AArch64_Arm64EC_Thunk_SaveList;
95 ? CSR_Win_AArch64_RT_MostRegs_SaveList
96 : CSR_AArch64_RT_MostRegs_SaveList;
100 ? CSR_Win_AArch64_RT_AllRegs_SaveList
101 : CSR_AArch64_RT_AllRegs_SaveList;
104 return CSR_Win_AArch64_CFGuard_Check_SaveList;
109 Attribute::SwiftError))
110 return CSR_Win_AArch64_AAPCS_SwiftError_SaveList;
112 return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList;
114 return CSR_Win_AArch64_AAVPCS_SaveList;
115 if (AFI.hasSVE_AAPCS(*MF))
116 return CSR_Win_AArch64_SVE_AAPCS_SaveList;
117 return CSR_Win_AArch64_AAPCS_SaveList;
120 return CSR_AArch64_AAVPCS_SaveList;
122 return CSR_AArch64_SVE_AAPCS_SaveList;
126 "Calling convention "
127 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is only "
128 "supported to improve calls to SME ACLE save/restore/disable-za "
129 "functions, and is not intended to be used beyond that scope.");
133 "Calling convention "
134 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
135 "only supported to improve calls to SME ACLE __arm_get_current_vg "
136 "function, and is not intended to be used beyond that scope.");
140 "Calling convention "
141 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
142 "only supported to improve calls to SME ACLE __arm_sme_state "
143 "and is not intended to be used beyond that scope.");
147 Attribute::SwiftError))
148 return CSR_AArch64_AAPCS_SwiftError_SaveList;
150 return CSR_AArch64_AAPCS_SwiftTail_SaveList;
154 return CSR_AArch64_AAPCS_X18_SaveList;
155 if (AFI.hasSVE_AAPCS(*MF))
156 return CSR_AArch64_SVE_AAPCS_SaveList;
157 return CSR_AArch64_AAPCS_SaveList;
162 assert(MF &&
"Invalid MachineFunction pointer.");
164 "Invalid subtarget for getDarwinCalleeSavedRegs");
169 "Calling convention CFGuard_Check is unsupported on Darwin.");
171 return CSR_Darwin_AArch64_AAVPCS_SaveList;
174 "Calling convention SVE_VectorCall is unsupported on Darwin.");
178 "Calling convention "
179 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is "
180 "only supported to improve calls to SME ACLE save/restore/disable-za "
181 "functions, and is not intended to be used beyond that scope.");
185 "Calling convention "
186 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
187 "only supported to improve calls to SME ACLE __arm_get_current_vg "
188 "function, and is not intended to be used beyond that scope.");
192 "Calling convention "
193 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
194 "only supported to improve calls to SME ACLE __arm_sme_state "
195 "and is not intended to be used beyond that scope.");
198 ? CSR_Darwin_AArch64_CXX_TLS_PE_SaveList
199 : CSR_Darwin_AArch64_CXX_TLS_SaveList;
203 Attribute::SwiftError))
204 return CSR_Darwin_AArch64_AAPCS_SwiftError_SaveList;
206 return CSR_Darwin_AArch64_AAPCS_SwiftTail_SaveList;
208 return CSR_Darwin_AArch64_RT_MostRegs_SaveList;
210 return CSR_Darwin_AArch64_RT_AllRegs_SaveList;
212 return CSR_Darwin_AArch64_AAPCS_Win64_SaveList;
213 if (AFI.hasSVE_AAPCS(*MF))
214 return CSR_Darwin_AArch64_SVE_AAPCS_SaveList;
215 return CSR_Darwin_AArch64_AAPCS_SaveList;
220 assert(MF &&
"Invalid MachineFunction pointer.");
223 return CSR_Darwin_AArch64_CXX_TLS_ViaCopy_SaveList;
234 for (
size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
236 UpdatedCSRs.
push_back(AArch64::GPR64commonRegClass.getRegister(i));
246 unsigned Idx)
const {
248 if (RC == &AArch64::GPR32allRegClass && Idx == AArch64::hsub)
249 return &AArch64::FPR32RegClass;
250 else if (RC == &AArch64::GPR64allRegClass && Idx == AArch64::hsub)
251 return &AArch64::FPR64RegClass;
254 return AArch64GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
261 "Invalid subtarget for getDarwinCallPreservedMask");
264 return CSR_Darwin_AArch64_CXX_TLS_RegMask;
266 return CSR_Darwin_AArch64_AAVPCS_RegMask;
268 return CSR_Darwin_AArch64_SVE_AAPCS_RegMask;
270 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
272 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
274 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
277 "Calling convention CFGuard_Check is unsupported on Darwin.");
282 return CSR_Darwin_AArch64_AAPCS_SwiftError_RegMask;
284 return CSR_Darwin_AArch64_AAPCS_SwiftTail_RegMask;
286 return CSR_Darwin_AArch64_RT_MostRegs_RegMask;
288 return CSR_Darwin_AArch64_RT_AllRegs_RegMask;
289 return CSR_Darwin_AArch64_AAPCS_RegMask;
298 return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
300 return SCS ? CSR_AArch64_NoneRegs_SCS_RegMask
301 : CSR_AArch64_NoneRegs_RegMask;
303 return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
313 return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
315 return SCS ? CSR_AArch64_SVE_AAPCS_SCS_RegMask
316 : CSR_AArch64_SVE_AAPCS_RegMask;
318 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
320 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
322 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
324 return CSR_Win_AArch64_CFGuard_Check_RegMask;
328 return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
329 : CSR_AArch64_AAPCS_SwiftError_RegMask;
333 return CSR_AArch64_AAPCS_SwiftTail_RegMask;
336 return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
337 : CSR_AArch64_RT_MostRegs_RegMask;
339 return SCS ? CSR_AArch64_RT_AllRegs_SCS_RegMask
340 : CSR_AArch64_RT_AllRegs_RegMask;
342 return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
348 return CSR_AArch64_AAPCS_RegMask;
355 return CSR_Darwin_AArch64_TLS_RegMask;
357 assert(TT.isOSBinFormatELF() &&
"Invalid target");
358 return CSR_AArch64_TLS_ELF_RegMask;
365 memcpy(UpdatedMask, *Mask,
sizeof(UpdatedMask[0]) * RegMaskSize);
367 for (
size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
370 subregs_inclusive(AArch64::GPR64commonRegClass.getRegister(i))) {
381 return CSR_AArch64_SMStartStop_RegMask;
386 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
390 return CSR_AArch64_NoRegs_RegMask;
405 return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask;
406 return CSR_AArch64_AAPCS_ThisReturn_RegMask;
410 return CSR_AArch64_StackProbe_Windows_RegMask;
413std::optional<std::string>
417 return std::string(
"X19 is used as the frame base pointer register.");
428 for (
unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
434 " is clobbered by asynchronous signals when using Arm64EC.";
446 markSuperRegs(
Reserved, AArch64::WSP);
447 markSuperRegs(
Reserved, AArch64::WZR);
450 markSuperRegs(
Reserved, AArch64::W29);
455 markSuperRegs(
Reserved, AArch64::W13);
456 markSuperRegs(
Reserved, AArch64::W14);
457 markSuperRegs(
Reserved, AArch64::W23);
458 markSuperRegs(
Reserved, AArch64::W24);
459 markSuperRegs(
Reserved, AArch64::W28);
460 for (
unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
464 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
466 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
470 markSuperRegs(
Reserved, AArch64::W19);
474 markSuperRegs(
Reserved, AArch64::W16);
495 markSuperRegs(
Reserved, AArch64::FPCR);
496 markSuperRegs(
Reserved, AArch64::FPMR);
497 markSuperRegs(
Reserved, AArch64::FPSR);
500 markSuperRegs(
Reserved, AArch64::X27);
501 markSuperRegs(
Reserved, AArch64::X28);
502 markSuperRegs(
Reserved, AArch64::W27);
503 markSuperRegs(
Reserved, AArch64::W28);
512 static_assert(AArch64::W30_HI - AArch64::W0_HI == 30,
513 "Unexpected order of registers");
514 Reserved.set(AArch64::W0_HI, AArch64::W30_HI);
515 static_assert(AArch64::B31_HI - AArch64::B0_HI == 31,
516 "Unexpected order of registers");
517 Reserved.set(AArch64::B0_HI, AArch64::B31_HI);
518 static_assert(AArch64::H31_HI - AArch64::H0_HI == 31,
519 "Unexpected order of registers");
520 Reserved.set(AArch64::H0_HI, AArch64::H31_HI);
521 static_assert(AArch64::S31_HI - AArch64::S0_HI == 31,
522 "Unexpected order of registers");
523 Reserved.set(AArch64::S0_HI, AArch64::S31_HI);
524 static_assert(AArch64::D31_HI - AArch64::D0_HI == 31,
525 "Unexpected order of registers");
526 Reserved.set(AArch64::D0_HI, AArch64::D31_HI);
527 static_assert(AArch64::Q31_HI - AArch64::Q0_HI == 31,
528 "Unexpected order of registers");
529 Reserved.set(AArch64::Q0_HI, AArch64::Q31_HI);
537 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
541 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
549 for (
size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
551 markSuperRegs(
Reserved, AArch64::GPR32commonRegClass.getRegister(i));
561 markSuperRegs(
Reserved, AArch64::LR);
598 " function calls if any of the argument registers is reserved.")});
611 if (PhysReg == AArch64::ZA || PhysReg == AArch64::ZT0)
619 return &AArch64::GPR64spRegClass;
624 if (RC == &AArch64::CCRRegClass)
625 return &AArch64::GPR64RegClass;
643 if (hasStackRealignment(MF))
648 if (ST.hasSVE() || ST.isStreaming()) {
651 if (!AFI->hasCalculatedStackSizeSVE() || AFI->hasSVEStackSize())
662 if (ST.getStreamingHazardSize() &&
663 !AFI->getSMEFnAttrs().hasNonStreamingInterfaceAndBody()) {
695 return HasReg(CC_AArch64_GHC_ArgRegs, Reg);
698 return HasReg(CC_AArch64_Preserve_None_ArgRegs, Reg);
710 return HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
713 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
716 return HasReg(CC_AArch64_Win64PCS_Swift_ArgRegs, Reg) ||
717 HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
723 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
726 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg) ||
727 HasReg(CC_AArch64_AAPCS_Swift_ArgRegs, Reg);
733 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg);
736 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg) ||
737 HasReg(CC_AArch64_DarwinPCS_Swift_ArgRegs, Reg);
741 return HasReg(CC_AArch64_DarwinPCS_ILP32_VarArg_ArgRegs, Reg);
742 return HasReg(CC_AArch64_DarwinPCS_VarArg_ArgRegs, Reg);
745 HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
746 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
748 return HasReg(CC_AArch64_Win64_CFGuard_Check_ArgRegs, Reg);
755 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
756 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
763 return TFI->
hasFP(MF) ? AArch64::FP : AArch64::SP;
790 "Expected SVE area to be calculated by this point");
814 for (
unsigned i = 0; !
MI->getOperand(i).isFI(); ++i)
815 assert(i < MI->getNumOperands() &&
816 "Instr doesn't have FrameIndex operand!");
827 if (!
MI->mayLoad() && !
MI->mayStore())
842 int64_t FPOffset =
Offset - 16 * 20;
879 assert(
MI &&
"Unable to get the legal offset for nil instruction.");
892 if (Ins !=
MBB->end())
893 DL = Ins->getDebugLoc();
899 Register BaseReg =
MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
900 MRI.constrainRegClass(BaseReg,
TII->getRegClass(
MCID, 0,
this));
917 while (!
MI.getOperand(i).isFI()) {
919 assert(i <
MI.getNumOperands() &&
"Instr doesn't have FrameIndex operand!");
926 assert(
Done &&
"Unable to resolve frame index!");
940 if (
MI.getOpcode() == AArch64::STGloop ||
941 MI.getOpcode() == AArch64::STZGloop) {
942 assert(FIOperandNum == 3 &&
943 "Wrong frame index operand for STGloop/STZGloop");
944 unsigned Op =
MI.getOpcode() == AArch64::STGloop ? AArch64::STGloop_wback
945 : AArch64::STZGloop_wback;
946 ScratchReg =
MI.getOperand(1).getReg();
947 MI.getOperand(3).ChangeToRegister(ScratchReg,
false,
false,
true);
949 MI.tieOperands(1, 3);
952 MI.getMF()->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
953 MI.getOperand(FIOperandNum)
954 .ChangeToRegister(ScratchReg,
false,
false,
true);
964 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
970 int64_t VGSized =
Offset.getScalable() / 2;
972 Ops.push_back(dwarf::DW_OP_constu);
973 Ops.push_back(VGSized);
974 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
975 Ops.push_back(dwarf::DW_OP_mul);
976 Ops.push_back(dwarf::DW_OP_plus);
977 }
else if (VGSized < 0) {
978 Ops.push_back(dwarf::DW_OP_constu);
979 Ops.push_back(-VGSized);
980 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
981 Ops.push_back(dwarf::DW_OP_mul);
982 Ops.push_back(dwarf::DW_OP_minus);
987 int SPAdj,
unsigned FIOperandNum,
989 assert(SPAdj == 0 &&
"Unexpected");
998 int FrameIndex =
MI.getOperand(FIOperandNum).getIndex();
1004 if (
MI.getOpcode() == TargetOpcode::STACKMAP ||
1005 MI.getOpcode() == TargetOpcode::PATCHPOINT ||
1006 MI.getOpcode() == TargetOpcode::STATEPOINT) {
1012 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg,
false );
1013 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(
Offset.getFixed());
1017 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) {
1021 "Frame offsets with a scalable component are not supported");
1027 if (
MI.getOpcode() == AArch64::TAGPstack) {
1030 FrameReg =
MI.getOperand(3).getReg();
1033 }
else if (Tagged) {
1042 MF, FrameIndex, FrameReg,
false,
true);
1051 MI.getOperand(FIOperandNum)
1052 .ChangeToRegister(ScratchReg,
false,
false,
true);
1055 FrameReg = AArch64::SP;
1060 MF, FrameIndex, FrameReg,
false,
true);
1067 assert((!RS || !RS->isScavengingFrameIndex(FrameIndex)) &&
1068 "Emergency spill slot is out of reach");
1083 switch (RC->
getID()) {
1086 case AArch64::GPR32RegClassID:
1087 case AArch64::GPR32spRegClassID:
1088 case AArch64::GPR32allRegClassID:
1089 case AArch64::GPR64spRegClassID:
1090 case AArch64::GPR64allRegClassID:
1091 case AArch64::GPR64RegClassID:
1092 case AArch64::GPR32commonRegClassID:
1093 case AArch64::GPR64commonRegClassID:
1095 - (TFI->
hasFP(MF) || TT.isOSDarwin())
1098 case AArch64::FPR8RegClassID:
1099 case AArch64::FPR16RegClassID:
1100 case AArch64::FPR32RegClassID:
1101 case AArch64::FPR64RegClassID:
1102 case AArch64::FPR128RegClassID:
1105 case AArch64::MatrixIndexGPR32_8_11RegClassID:
1106 case AArch64::MatrixIndexGPR32_12_15RegClassID:
1109 case AArch64::DDRegClassID:
1110 case AArch64::DDDRegClassID:
1111 case AArch64::DDDDRegClassID:
1112 case AArch64::QQRegClassID:
1113 case AArch64::QQQRegClassID:
1114 case AArch64::QQQQRegClassID:
1117 case AArch64::FPR128_loRegClassID:
1118 case AArch64::FPR64_loRegClassID:
1119 case AArch64::FPR16_loRegClassID:
1121 case AArch64::FPR128_0to7RegClassID:
1144 if (!ST.hasSME() || !ST.isStreaming())
1157 unsigned RegID =
MRI.getRegClass(VirtReg)->getID();
1158 if (RegID == AArch64::ZPR2StridedOrContiguousRegClassID ||
1159 RegID == AArch64::ZPR4StridedOrContiguousRegClassID) {
1163 if (
Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO &&
1164 Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO)
1167 unsigned UseOps =
Use.getNumOperands() - 1;
1170 case AArch64::ZPR2StridedOrContiguousRegClassID:
1171 StridedRC = &AArch64::ZPR2StridedRegClass;
1173 case AArch64::ZPR4StridedOrContiguousRegClassID:
1174 StridedRC = &AArch64::ZPR4StridedRegClass;
1185 int OpIdx =
Use.findRegisterUseOperandIdx(VirtReg,
this);
1186 assert(
OpIdx != -1 &&
"Expected operand index from register use.");
1188 unsigned TupleID =
MRI.getRegClass(
Use.getOperand(0).getReg())->getID();
1189 bool IsMulZPR = TupleID == AArch64::ZPR2Mul2RegClassID ||
1190 TupleID == AArch64::ZPR4Mul4RegClassID;
1195 return VRM->hasPhys(Op.getReg());
1231 if (AssignedRegOp ==
Use.operands_end()) {
1234 for (
unsigned I = 0;
I < StridedOrder.
size(); ++
I) {
1239 unsigned SubRegIdx =
Use.getOperand(
OpIdx).getSubReg();
1240 if (IsMulZPR && (getSubReg(Reg, SubRegIdx) - AArch64::Z0) % UseOps !=
1241 ((
unsigned)
OpIdx - 1))
1247 auto IsFreeConsecutiveReg = [&](
unsigned UseOp) {
1248 unsigned R = Reg - (
OpIdx - 1) + UseOp;
1251 ((getSubReg(R, AArch64::zsub0) - AArch64::Z0) ==
1252 (getSubReg(R - 1, AArch64::zsub0) - AArch64::Z0) + 1)) &&
1253 !
Matrix->isPhysRegUsed(R);
1256 IsFreeConsecutiveReg))
1264 getSubReg(VRM->
getPhys(AssignedRegOp->
getReg()), AArch64::zsub0) +
1267 for (
unsigned I = 0;
I < StridedOrder.
size(); ++
I)
1268 if (getSubReg(StridedOrder[
I], AArch64::zsub0) == TargetStartReg)
1279 if (
MI.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO &&
1280 MI.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO)
1284 unsigned FirstOpSubReg =
MI.getOperand(1).getSubReg();
1285 switch (FirstOpSubReg) {
1286 case AArch64::zsub0:
1287 case AArch64::zsub1:
1288 case AArch64::zsub2:
1289 case AArch64::zsub3:
1296 Register FirstOpVirtReg =
MI.getOperand(1).getReg();
1297 if (!VRM->
hasPhys(FirstOpVirtReg))
1301 getSubReg(VRM->
getPhys(FirstOpVirtReg), FirstOpSubReg);
1302 for (
unsigned I = 0;
I < Order.
size(); ++
I)
1303 if (
MCRegister R = getSubReg(Order[
I], AArch64::zsub0))
1304 if (R == TupleStartReg)
1317 else if (hasStackRealignment(MF))
1330 ((DstRC->
getID() == AArch64::GPR64RegClassID) ||
1331 (DstRC->
getID() == AArch64::GPR64commonRegClassID)) &&
1332 MI->getOperand(0).getSubReg() &&
MI->getOperand(1).getSubReg())
1339 switch (
MI.getOpcode()) {
1340 case AArch64::COALESCER_BARRIER_FPR16:
1341 case AArch64::COALESCER_BARRIER_FPR32:
1342 case AArch64::COALESCER_BARRIER_FPR64:
1343 case AArch64::COALESCER_BARRIER_FPR128:
1359 if (
MI->isCopy() &&
SubReg != DstSubReg &&
1360 (AArch64::ZPRRegClass.hasSubClassEq(DstRC) ||
1361 AArch64::ZPRRegClass.hasSubClassEq(SrcRC))) {
1362 unsigned SrcReg =
MI->getOperand(1).getReg();
1363 if (
any_of(
MRI.def_instructions(SrcReg), IsCoalescerBarrier))
1365 unsigned DstReg =
MI->getOperand(0).getReg();
1366 if (
any_of(
MRI.use_nodbg_instructions(DstReg), IsCoalescerBarrier))
1375 return R == AArch64::VG;
1379 return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
1380 (LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
unsigned const MachineRegisterInfo * MRI
static bool isTargetWindows(const MachineFunction &MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Register createScratchRegisterForInstruction(MachineInstr &MI, unsigned FIOperandNum, const AArch64InstrInfo *TII)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
MachineInstr unsigned OpIdx
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
const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) 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
bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallVectorImpl< MCPhysReg > &Hints, const MachineFunction &MF, const VirtRegMap *VRM, const LiveRegMatrix *Matrix) 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
const MCPhysReg * getDarwinCalleeSavedRegs(const MachineFunction *MF) const
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
std::optional< std::string > explainReservedReg(const MachineFunction &MF, MCRegister PhysReg) const override
bool requiresFrameIndexScavenging(const MachineFunction &MF) const override
bool isTargetWindows() 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 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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
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.
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.
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.
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
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,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI void setCalleeSavedRegs(ArrayRef< MCPhysReg > CSRs)
Sets the updated Callee Saved Registers list.
Wrapper class representing virtual and physical registers.
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.
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
unsigned getID() const
Return the register class ID number.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
virtual bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallVectorImpl< MCPhysReg > &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
#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)
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.
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.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
@ 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.
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.