1 //===- AArch64RegisterInfo.cpp - AArch64 Register Information -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the AArch64 implementation of the TargetRegisterInfo
10 // class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "AArch64RegisterInfo.h"
15 #include "AArch64FrameLowering.h"
16 #include "AArch64InstrInfo.h"
17 #include "AArch64MachineFunctionInfo.h"
18 #include "AArch64Subtarget.h"
19 #include "MCTargetDesc/AArch64AddressingModes.h"
20 #include "MCTargetDesc/AArch64InstPrinter.h"
21 #include "Utils/AArch64SMEAttributes.h"
22 #include "llvm/ADT/BitVector.h"
23 #include "llvm/BinaryFormat/Dwarf.h"
24 #include "llvm/CodeGen/LiveRegMatrix.h"
25 #include "llvm/CodeGen/MachineFrameInfo.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/MachineRegisterInfo.h"
28 #include "llvm/CodeGen/RegisterScavenging.h"
29 #include "llvm/CodeGen/TargetFrameLowering.h"
30 #include "llvm/IR/DebugInfoMetadata.h"
31 #include "llvm/IR/DiagnosticInfo.h"
32 #include "llvm/IR/Function.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/TargetParser/Triple.h"
35
36 using namespace llvm;
37
38 #define GET_CC_REGISTER_LISTS
39 #include "AArch64GenCallingConv.inc"
40 #define GET_REGINFO_TARGET_DESC
41 #include "AArch64GenRegisterInfo.inc"
42
AArch64RegisterInfo(const Triple & TT,unsigned HwMode)43 AArch64RegisterInfo::AArch64RegisterInfo(const Triple &TT, unsigned HwMode)
44 : AArch64GenRegisterInfo(AArch64::LR, 0, 0, 0, HwMode), TT(TT) {
45 AArch64_MC::initLLVMToCVRegMapping(this);
46 }
47
48 /// Return whether the register needs a CFI entry. Not all unwinders may know
49 /// about SVE registers, so we assume the lowest common denominator, i.e. the
50 /// callee-saves required by the base ABI. For the SVE registers z8-z15 only the
51 /// lower 64-bits (d8-d15) need to be saved. The lower 64-bits subreg is
52 /// returned in \p RegToUseForCFI.
regNeedsCFI(MCRegister Reg,MCRegister & RegToUseForCFI) const53 bool AArch64RegisterInfo::regNeedsCFI(MCRegister Reg,
54 MCRegister &RegToUseForCFI) const {
55 if (AArch64::PPRRegClass.contains(Reg))
56 return false;
57
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)
62 return true;
63 }
64 return false;
65 }
66
67 RegToUseForCFI = Reg;
68 return true;
69 }
70
71 const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const72 AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
73 assert(MF && "Invalid MachineFunction pointer.");
74
75 if (MF->getFunction().getCallingConv() == CallingConv::GHC)
76 // GHC set of callee saved regs is empty as all those regs are
77 // used for passing STG regs around
78 return CSR_AArch64_NoRegs_SaveList;
79 if (MF->getFunction().getCallingConv() == CallingConv::PreserveNone)
80 return CSR_AArch64_NoneRegs_SaveList;
81 if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
82 return CSR_AArch64_AllRegs_SaveList;
83
84 if (MF->getFunction().getCallingConv() == CallingConv::ARM64EC_Thunk_X64)
85 return CSR_Win_AArch64_Arm64EC_Thunk_SaveList;
86
87 // Darwin has its own CSR_AArch64_AAPCS_SaveList, which means most CSR save
88 // lists depending on that will need to have their Darwin variant as well.
89 if (MF->getSubtarget<AArch64Subtarget>().isTargetDarwin())
90 return getDarwinCalleeSavedRegs(MF);
91
92 if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
93 return CSR_Win_AArch64_CFGuard_Check_SaveList;
94 if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows()) {
95 if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering()
96 ->supportSwiftError() &&
97 MF->getFunction().getAttributes().hasAttrSomewhere(
98 Attribute::SwiftError))
99 return CSR_Win_AArch64_AAPCS_SwiftError_SaveList;
100 if (MF->getFunction().getCallingConv() == CallingConv::SwiftTail)
101 return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList;
102 if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall)
103 return CSR_Win_AArch64_AAVPCS_SaveList;
104 if (MF->getFunction().getCallingConv() ==
105 CallingConv::AArch64_SVE_VectorCall)
106 return CSR_Win_AArch64_SVE_AAPCS_SaveList;
107 if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
108 return CSR_Win_AArch64_SVE_AAPCS_SaveList;
109 return CSR_Win_AArch64_AAPCS_SaveList;
110 }
111 if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall)
112 return CSR_AArch64_AAVPCS_SaveList;
113 if (MF->getFunction().getCallingConv() == CallingConv::AArch64_SVE_VectorCall)
114 return CSR_AArch64_SVE_AAPCS_SaveList;
115 if (MF->getFunction().getCallingConv() ==
116 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0)
117 report_fatal_error(
118 "Calling convention "
119 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is only "
120 "supported to improve calls to SME ACLE save/restore/disable-za "
121 "functions, and is not intended to be used beyond that scope.");
122 if (MF->getFunction().getCallingConv() ==
123 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1)
124 report_fatal_error(
125 "Calling convention "
126 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
127 "only supported to improve calls to SME ACLE __arm_get_current_vg "
128 "function, and is not intended to be used beyond that scope.");
129 if (MF->getFunction().getCallingConv() ==
130 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2)
131 report_fatal_error(
132 "Calling convention "
133 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
134 "only supported to improve calls to SME ACLE __arm_sme_state "
135 "and is not intended to be used beyond that scope.");
136 if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering()
137 ->supportSwiftError() &&
138 MF->getFunction().getAttributes().hasAttrSomewhere(
139 Attribute::SwiftError))
140 return CSR_AArch64_AAPCS_SwiftError_SaveList;
141 if (MF->getFunction().getCallingConv() == CallingConv::SwiftTail)
142 return CSR_AArch64_AAPCS_SwiftTail_SaveList;
143 if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
144 return CSR_AArch64_RT_MostRegs_SaveList;
145 if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll)
146 return CSR_AArch64_RT_AllRegs_SaveList;
147 if (MF->getFunction().getCallingConv() == CallingConv::Win64)
148 // This is for OSes other than Windows; Windows is a separate case further
149 // above.
150 return CSR_AArch64_AAPCS_X18_SaveList;
151 if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
152 return CSR_AArch64_SVE_AAPCS_SaveList;
153 return CSR_AArch64_AAPCS_SaveList;
154 }
155
156 const MCPhysReg *
getDarwinCalleeSavedRegs(const MachineFunction * MF) const157 AArch64RegisterInfo::getDarwinCalleeSavedRegs(const MachineFunction *MF) const {
158 assert(MF && "Invalid MachineFunction pointer.");
159 assert(MF->getSubtarget<AArch64Subtarget>().isTargetDarwin() &&
160 "Invalid subtarget for getDarwinCalleeSavedRegs");
161
162 if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
163 report_fatal_error(
164 "Calling convention CFGuard_Check is unsupported on Darwin.");
165 if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall)
166 return CSR_Darwin_AArch64_AAVPCS_SaveList;
167 if (MF->getFunction().getCallingConv() == CallingConv::AArch64_SVE_VectorCall)
168 report_fatal_error(
169 "Calling convention SVE_VectorCall is unsupported on Darwin.");
170 if (MF->getFunction().getCallingConv() ==
171 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0)
172 report_fatal_error(
173 "Calling convention "
174 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is "
175 "only supported to improve calls to SME ACLE save/restore/disable-za "
176 "functions, and is not intended to be used beyond that scope.");
177 if (MF->getFunction().getCallingConv() ==
178 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1)
179 report_fatal_error(
180 "Calling convention "
181 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
182 "only supported to improve calls to SME ACLE __arm_get_current_vg "
183 "function, and is not intended to be used beyond that scope.");
184 if (MF->getFunction().getCallingConv() ==
185 CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2)
186 report_fatal_error(
187 "Calling convention "
188 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
189 "only supported to improve calls to SME ACLE __arm_sme_state "
190 "and is not intended to be used beyond that scope.");
191 if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS)
192 return MF->getInfo<AArch64FunctionInfo>()->isSplitCSR()
193 ? CSR_Darwin_AArch64_CXX_TLS_PE_SaveList
194 : CSR_Darwin_AArch64_CXX_TLS_SaveList;
195 if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering()
196 ->supportSwiftError() &&
197 MF->getFunction().getAttributes().hasAttrSomewhere(
198 Attribute::SwiftError))
199 return CSR_Darwin_AArch64_AAPCS_SwiftError_SaveList;
200 if (MF->getFunction().getCallingConv() == CallingConv::SwiftTail)
201 return CSR_Darwin_AArch64_AAPCS_SwiftTail_SaveList;
202 if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
203 return CSR_Darwin_AArch64_RT_MostRegs_SaveList;
204 if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll)
205 return CSR_Darwin_AArch64_RT_AllRegs_SaveList;
206 if (MF->getFunction().getCallingConv() == CallingConv::Win64)
207 return CSR_Darwin_AArch64_AAPCS_Win64_SaveList;
208 if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
209 return CSR_Darwin_AArch64_SVE_AAPCS_SaveList;
210 return CSR_Darwin_AArch64_AAPCS_SaveList;
211 }
212
getCalleeSavedRegsViaCopy(const MachineFunction * MF) const213 const MCPhysReg *AArch64RegisterInfo::getCalleeSavedRegsViaCopy(
214 const MachineFunction *MF) const {
215 assert(MF && "Invalid MachineFunction pointer.");
216 if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS &&
217 MF->getInfo<AArch64FunctionInfo>()->isSplitCSR())
218 return CSR_Darwin_AArch64_CXX_TLS_ViaCopy_SaveList;
219 return nullptr;
220 }
221
UpdateCustomCalleeSavedRegs(MachineFunction & MF) const222 void AArch64RegisterInfo::UpdateCustomCalleeSavedRegs(
223 MachineFunction &MF) const {
224 const MCPhysReg *CSRs = getCalleeSavedRegs(&MF);
225 SmallVector<MCPhysReg, 32> UpdatedCSRs;
226 for (const MCPhysReg *I = CSRs; *I; ++I)
227 UpdatedCSRs.push_back(*I);
228
229 for (size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
230 if (MF.getSubtarget<AArch64Subtarget>().isXRegCustomCalleeSaved(i)) {
231 UpdatedCSRs.push_back(AArch64::GPR64commonRegClass.getRegister(i));
232 }
233 }
234 // Register lists are zero-terminated.
235 UpdatedCSRs.push_back(0);
236 MF.getRegInfo().setCalleeSavedRegs(UpdatedCSRs);
237 }
238
239 const TargetRegisterClass *
getSubClassWithSubReg(const TargetRegisterClass * RC,unsigned Idx) const240 AArch64RegisterInfo::getSubClassWithSubReg(const TargetRegisterClass *RC,
241 unsigned Idx) const {
242 // edge case for GPR/FPR register classes
243 if (RC == &AArch64::GPR32allRegClass && Idx == AArch64::hsub)
244 return &AArch64::FPR32RegClass;
245 else if (RC == &AArch64::GPR64allRegClass && Idx == AArch64::hsub)
246 return &AArch64::FPR64RegClass;
247
248 // Forward to TableGen's default version.
249 return AArch64GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
250 }
251
252 const uint32_t *
getDarwinCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const253 AArch64RegisterInfo::getDarwinCallPreservedMask(const MachineFunction &MF,
254 CallingConv::ID CC) const {
255 assert(MF.getSubtarget<AArch64Subtarget>().isTargetDarwin() &&
256 "Invalid subtarget for getDarwinCallPreservedMask");
257
258 if (CC == CallingConv::CXX_FAST_TLS)
259 return CSR_Darwin_AArch64_CXX_TLS_RegMask;
260 if (CC == CallingConv::AArch64_VectorCall)
261 return CSR_Darwin_AArch64_AAVPCS_RegMask;
262 if (CC == CallingConv::AArch64_SVE_VectorCall)
263 return CSR_Darwin_AArch64_SVE_AAPCS_RegMask;
264 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0)
265 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
266 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1)
267 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
268 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2)
269 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
270 if (CC == CallingConv::CFGuard_Check)
271 report_fatal_error(
272 "Calling convention CFGuard_Check is unsupported on Darwin.");
273 if (MF.getSubtarget<AArch64Subtarget>()
274 .getTargetLowering()
275 ->supportSwiftError() &&
276 MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
277 return CSR_Darwin_AArch64_AAPCS_SwiftError_RegMask;
278 if (CC == CallingConv::SwiftTail)
279 return CSR_Darwin_AArch64_AAPCS_SwiftTail_RegMask;
280 if (CC == CallingConv::PreserveMost)
281 return CSR_Darwin_AArch64_RT_MostRegs_RegMask;
282 if (CC == CallingConv::PreserveAll)
283 return CSR_Darwin_AArch64_RT_AllRegs_RegMask;
284 return CSR_Darwin_AArch64_AAPCS_RegMask;
285 }
286
287 const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const288 AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
289 CallingConv::ID CC) const {
290 bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
291 if (CC == CallingConv::GHC)
292 // This is academic because all GHC calls are (supposed to be) tail calls
293 return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
294 if (CC == CallingConv::PreserveNone)
295 return SCS ? CSR_AArch64_NoneRegs_SCS_RegMask
296 : CSR_AArch64_NoneRegs_RegMask;
297 if (CC == CallingConv::AnyReg)
298 return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
299
300 // All the following calling conventions are handled differently on Darwin.
301 if (MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) {
302 if (SCS)
303 report_fatal_error("ShadowCallStack attribute not supported on Darwin.");
304 return getDarwinCallPreservedMask(MF, CC);
305 }
306
307 if (CC == CallingConv::AArch64_VectorCall)
308 return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
309 if (CC == CallingConv::AArch64_SVE_VectorCall)
310 return SCS ? CSR_AArch64_SVE_AAPCS_SCS_RegMask
311 : CSR_AArch64_SVE_AAPCS_RegMask;
312 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0)
313 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
314 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1)
315 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
316 if (CC == CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2)
317 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
318 if (CC == CallingConv::CFGuard_Check)
319 return CSR_Win_AArch64_CFGuard_Check_RegMask;
320 if (MF.getSubtarget<AArch64Subtarget>().getTargetLowering()
321 ->supportSwiftError() &&
322 MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
323 return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
324 : CSR_AArch64_AAPCS_SwiftError_RegMask;
325 if (CC == CallingConv::SwiftTail) {
326 if (SCS)
327 report_fatal_error("ShadowCallStack attribute not supported with swifttail");
328 return CSR_AArch64_AAPCS_SwiftTail_RegMask;
329 }
330 if (CC == CallingConv::PreserveMost)
331 return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
332 : CSR_AArch64_RT_MostRegs_RegMask;
333 if (CC == CallingConv::PreserveAll)
334 return SCS ? CSR_AArch64_RT_AllRegs_SCS_RegMask
335 : CSR_AArch64_RT_AllRegs_RegMask;
336
337 return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
338 }
339
getCustomEHPadPreservedMask(const MachineFunction & MF) const340 const uint32_t *AArch64RegisterInfo::getCustomEHPadPreservedMask(
341 const MachineFunction &MF) const {
342 if (MF.getSubtarget<AArch64Subtarget>().isTargetLinux())
343 return CSR_AArch64_AAPCS_RegMask;
344
345 return nullptr;
346 }
347
getTLSCallPreservedMask() const348 const uint32_t *AArch64RegisterInfo::getTLSCallPreservedMask() const {
349 if (TT.isOSDarwin())
350 return CSR_Darwin_AArch64_TLS_RegMask;
351
352 assert(TT.isOSBinFormatELF() && "Invalid target");
353 return CSR_AArch64_TLS_ELF_RegMask;
354 }
355
UpdateCustomCallPreservedMask(MachineFunction & MF,const uint32_t ** Mask) const356 void AArch64RegisterInfo::UpdateCustomCallPreservedMask(MachineFunction &MF,
357 const uint32_t **Mask) const {
358 uint32_t *UpdatedMask = MF.allocateRegMask();
359 unsigned RegMaskSize = MachineOperand::getRegMaskSize(getNumRegs());
360 memcpy(UpdatedMask, *Mask, sizeof(UpdatedMask[0]) * RegMaskSize);
361
362 for (size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
363 if (MF.getSubtarget<AArch64Subtarget>().isXRegCustomCalleeSaved(i)) {
364 for (MCPhysReg SubReg :
365 subregs_inclusive(AArch64::GPR64commonRegClass.getRegister(i))) {
366 // See TargetRegisterInfo::getCallPreservedMask for how to interpret the
367 // register mask.
368 UpdatedMask[SubReg / 32] |= 1u << (SubReg % 32);
369 }
370 }
371 }
372 *Mask = UpdatedMask;
373 }
374
getSMStartStopCallPreservedMask() const375 const uint32_t *AArch64RegisterInfo::getSMStartStopCallPreservedMask() const {
376 return CSR_AArch64_SMStartStop_RegMask;
377 }
378
379 const uint32_t *
SMEABISupportRoutinesCallPreservedMaskFromX0() const380 AArch64RegisterInfo::SMEABISupportRoutinesCallPreservedMaskFromX0() const {
381 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
382 }
383
getNoPreservedMask() const384 const uint32_t *AArch64RegisterInfo::getNoPreservedMask() const {
385 return CSR_AArch64_NoRegs_RegMask;
386 }
387
388 const uint32_t *
getThisReturnPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const389 AArch64RegisterInfo::getThisReturnPreservedMask(const MachineFunction &MF,
390 CallingConv::ID CC) const {
391 // This should return a register mask that is the same as that returned by
392 // getCallPreservedMask but that additionally preserves the register used for
393 // the first i64 argument (which must also be the register used to return a
394 // single i64 return value)
395 //
396 // In case that the calling convention does not use the same register for
397 // both, the function should return NULL (does not currently apply)
398 assert(CC != CallingConv::GHC && "should not be GHC calling convention.");
399 if (MF.getSubtarget<AArch64Subtarget>().isTargetDarwin())
400 return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask;
401 return CSR_AArch64_AAPCS_ThisReturn_RegMask;
402 }
403
getWindowsStackProbePreservedMask() const404 const uint32_t *AArch64RegisterInfo::getWindowsStackProbePreservedMask() const {
405 return CSR_AArch64_StackProbe_Windows_RegMask;
406 }
407
408 std::optional<std::string>
explainReservedReg(const MachineFunction & MF,MCRegister PhysReg) const409 AArch64RegisterInfo::explainReservedReg(const MachineFunction &MF,
410 MCRegister PhysReg) const {
411 if (hasBasePointer(MF) && MCRegisterInfo::regsOverlap(PhysReg, AArch64::X19))
412 return std::string("X19 is used as the frame base pointer register.");
413
414 if (MF.getSubtarget<AArch64Subtarget>().isWindowsArm64EC()) {
415 bool warn = false;
416 if (MCRegisterInfo::regsOverlap(PhysReg, AArch64::X13) ||
417 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X14) ||
418 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X23) ||
419 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X24) ||
420 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X28))
421 warn = true;
422
423 for (unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
424 if (MCRegisterInfo::regsOverlap(PhysReg, i))
425 warn = true;
426
427 if (warn)
428 return std::string(AArch64InstPrinter::getRegisterName(PhysReg)) +
429 " is clobbered by asynchronous signals when using Arm64EC.";
430 }
431
432 return {};
433 }
434
435 BitVector
getStrictlyReservedRegs(const MachineFunction & MF) const436 AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const {
437 const AArch64FrameLowering *TFI = getFrameLowering(MF);
438
439 // FIXME: avoid re-calculating this every time.
440 BitVector Reserved(getNumRegs());
441 markSuperRegs(Reserved, AArch64::WSP);
442 markSuperRegs(Reserved, AArch64::WZR);
443
444 if (TFI->isFPReserved(MF))
445 markSuperRegs(Reserved, AArch64::W29);
446
447 if (MF.getSubtarget<AArch64Subtarget>().isWindowsArm64EC()) {
448 // x13, x14, x23, x24, x28, and v16-v31 are clobbered by asynchronous
449 // signals, so we can't ever use them.
450 markSuperRegs(Reserved, AArch64::W13);
451 markSuperRegs(Reserved, AArch64::W14);
452 markSuperRegs(Reserved, AArch64::W23);
453 markSuperRegs(Reserved, AArch64::W24);
454 markSuperRegs(Reserved, AArch64::W28);
455 for (unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
456 markSuperRegs(Reserved, i);
457 }
458
459 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
460 if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(i))
461 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
462 }
463
464 if (hasBasePointer(MF))
465 markSuperRegs(Reserved, AArch64::W19);
466
467 // SLH uses register W16/X16 as the taint register.
468 if (MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening))
469 markSuperRegs(Reserved, AArch64::W16);
470
471 // FFR is modelled as global state that cannot be allocated.
472 if (MF.getSubtarget<AArch64Subtarget>().hasSVE())
473 Reserved.set(AArch64::FFR);
474
475 // SME tiles are not allocatable.
476 if (MF.getSubtarget<AArch64Subtarget>().hasSME()) {
477 for (MCPhysReg SubReg : subregs_inclusive(AArch64::ZA))
478 Reserved.set(SubReg);
479 }
480
481 // VG cannot be allocated
482 Reserved.set(AArch64::VG);
483
484 if (MF.getSubtarget<AArch64Subtarget>().hasSME2()) {
485 for (MCSubRegIterator SubReg(AArch64::ZT0, this, /*self=*/true);
486 SubReg.isValid(); ++SubReg)
487 Reserved.set(*SubReg);
488 }
489
490 markSuperRegs(Reserved, AArch64::FPCR);
491 markSuperRegs(Reserved, AArch64::FPMR);
492 markSuperRegs(Reserved, AArch64::FPSR);
493
494 if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) {
495 markSuperRegs(Reserved, AArch64::X27);
496 markSuperRegs(Reserved, AArch64::X28);
497 markSuperRegs(Reserved, AArch64::W27);
498 markSuperRegs(Reserved, AArch64::W28);
499 }
500
501 assert(checkAllSuperRegsMarked(Reserved));
502
503 // Add _HI registers after checkAllSuperRegsMarked as this check otherwise
504 // becomes considerably more expensive.
505 Reserved.set(AArch64::WSP_HI);
506 Reserved.set(AArch64::WZR_HI);
507 static_assert(AArch64::W30_HI - AArch64::W0_HI == 30,
508 "Unexpected order of registers");
509 Reserved.set(AArch64::W0_HI, AArch64::W30_HI);
510 static_assert(AArch64::B31_HI - AArch64::B0_HI == 31,
511 "Unexpected order of registers");
512 Reserved.set(AArch64::B0_HI, AArch64::B31_HI);
513 static_assert(AArch64::H31_HI - AArch64::H0_HI == 31,
514 "Unexpected order of registers");
515 Reserved.set(AArch64::H0_HI, AArch64::H31_HI);
516 static_assert(AArch64::S31_HI - AArch64::S0_HI == 31,
517 "Unexpected order of registers");
518 Reserved.set(AArch64::S0_HI, AArch64::S31_HI);
519 static_assert(AArch64::D31_HI - AArch64::D0_HI == 31,
520 "Unexpected order of registers");
521 Reserved.set(AArch64::D0_HI, AArch64::D31_HI);
522 static_assert(AArch64::Q31_HI - AArch64::Q0_HI == 31,
523 "Unexpected order of registers");
524 Reserved.set(AArch64::Q0_HI, AArch64::Q31_HI);
525
526 return Reserved;
527 }
528
529 BitVector
getUserReservedRegs(const MachineFunction & MF) const530 AArch64RegisterInfo::getUserReservedRegs(const MachineFunction &MF) const {
531 BitVector Reserved(getNumRegs());
532 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
533 // ReserveXRegister is set for registers manually reserved
534 // through +reserve-x#i.
535 if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(i))
536 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
537 }
538 return Reserved;
539 }
540
541 BitVector
getReservedRegs(const MachineFunction & MF) const542 AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
543 BitVector Reserved(getNumRegs());
544 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
545 if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReservedForRA(i))
546 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
547 }
548
549 if (MF.getSubtarget<AArch64Subtarget>().isLRReservedForRA()) {
550 // In order to prevent the register allocator from using LR, we need to
551 // mark it as reserved. However we don't want to keep it reserved throughout
552 // the pipeline since it prevents other infrastructure from reasoning about
553 // it's liveness. We use the NoVRegs property instead of IsSSA because
554 // IsSSA is removed before VirtRegRewriter runs.
555 if (!MF.getProperties().hasNoVRegs())
556 markSuperRegs(Reserved, AArch64::LR);
557 }
558
559 assert(checkAllSuperRegsMarked(Reserved));
560
561 // Handle strictlyReservedRegs separately to avoid re-evaluating the assert,
562 // which becomes considerably expensive when considering the _HI registers.
563 Reserved |= getStrictlyReservedRegs(MF);
564
565 return Reserved;
566 }
567
isReservedReg(const MachineFunction & MF,MCRegister Reg) const568 bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF,
569 MCRegister Reg) const {
570 return getReservedRegs(MF)[Reg];
571 }
572
isUserReservedReg(const MachineFunction & MF,MCRegister Reg) const573 bool AArch64RegisterInfo::isUserReservedReg(const MachineFunction &MF,
574 MCRegister Reg) const {
575 return getUserReservedRegs(MF)[Reg];
576 }
577
isStrictlyReservedReg(const MachineFunction & MF,MCRegister Reg) const578 bool AArch64RegisterInfo::isStrictlyReservedReg(const MachineFunction &MF,
579 MCRegister Reg) const {
580 return getStrictlyReservedRegs(MF)[Reg];
581 }
582
isAnyArgRegReserved(const MachineFunction & MF) const583 bool AArch64RegisterInfo::isAnyArgRegReserved(const MachineFunction &MF) const {
584 return llvm::any_of(*AArch64::GPR64argRegClass.MC, [this, &MF](MCPhysReg r) {
585 return isStrictlyReservedReg(MF, r);
586 });
587 }
588
emitReservedArgRegCallError(const MachineFunction & MF) const589 void AArch64RegisterInfo::emitReservedArgRegCallError(
590 const MachineFunction &MF) const {
591 const Function &F = MF.getFunction();
592 F.getContext().diagnose(DiagnosticInfoUnsupported{F, ("AArch64 doesn't support"
593 " function calls if any of the argument registers is reserved.")});
594 }
595
isAsmClobberable(const MachineFunction & MF,MCRegister PhysReg) const596 bool AArch64RegisterInfo::isAsmClobberable(const MachineFunction &MF,
597 MCRegister PhysReg) const {
598 // SLH uses register X16 as the taint register but it will fallback to a different
599 // method if the user clobbers it. So X16 is not reserved for inline asm but is
600 // for normal codegen.
601 if (MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening) &&
602 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X16))
603 return true;
604
605 // ZA/ZT0 registers are reserved but may be permitted in the clobber list.
606 if (PhysReg == AArch64::ZA || PhysReg == AArch64::ZT0)
607 return true;
608
609 return !isReservedReg(MF, PhysReg);
610 }
611
612 const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const613 AArch64RegisterInfo::getPointerRegClass(const MachineFunction &MF,
614 unsigned Kind) const {
615 return &AArch64::GPR64spRegClass;
616 }
617
618 const TargetRegisterClass *
getCrossCopyRegClass(const TargetRegisterClass * RC) const619 AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
620 if (RC == &AArch64::CCRRegClass)
621 return &AArch64::GPR64RegClass; // Only MSR & MRS copy NZCV.
622 return RC;
623 }
624
getBaseRegister() const625 unsigned AArch64RegisterInfo::getBaseRegister() const { return AArch64::X19; }
626
hasBasePointer(const MachineFunction & MF) const627 bool AArch64RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
628 const MachineFrameInfo &MFI = MF.getFrameInfo();
629
630 // In the presence of variable sized objects or funclets, if the fixed stack
631 // size is large enough that referencing from the FP won't result in things
632 // being in range relatively often, we can use a base pointer to allow access
633 // from the other direction like the SP normally works.
634 //
635 // Furthermore, if both variable sized objects are present, and the
636 // stack needs to be dynamically re-aligned, the base pointer is the only
637 // reliable way to reference the locals.
638 if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) {
639 if (hasStackRealignment(MF))
640 return true;
641
642 auto &ST = MF.getSubtarget<AArch64Subtarget>();
643 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
644 if (ST.hasSVE() || ST.isStreaming()) {
645 // Frames that have variable sized objects and scalable SVE objects,
646 // should always use a basepointer.
647 if (!AFI->hasCalculatedStackSizeSVE() || AFI->getStackSizeSVE())
648 return true;
649 }
650
651 // Frames with hazard padding can have a large offset between the frame
652 // pointer and GPR locals, which includes the emergency spill slot. If the
653 // emergency spill slot is not within range of the load/store instructions
654 // (which have a signed 9-bit range), we will fail to compile if it is used.
655 // Since hasBasePointer() is called before we know if we have hazard padding
656 // or an emergency spill slot we need to enable the basepointer
657 // conservatively.
658 if (ST.getStreamingHazardSize() &&
659 !AFI->getSMEFnAttrs().hasNonStreamingInterfaceAndBody()) {
660 return true;
661 }
662
663 // Conservatively estimate whether the negative offset from the frame
664 // pointer will be sufficient to reach. If a function has a smallish
665 // frame, it's less likely to have lots of spills and callee saved
666 // space, so it's all more likely to be within range of the frame pointer.
667 // If it's wrong, we'll materialize the constant and still get to the
668 // object; it's just suboptimal. Negative offsets use the unscaled
669 // load/store instructions, which have a 9-bit signed immediate.
670 return MFI.getLocalFrameSize() >= 256;
671 }
672
673 return false;
674 }
675
isArgumentRegister(const MachineFunction & MF,MCRegister Reg) const676 bool AArch64RegisterInfo::isArgumentRegister(const MachineFunction &MF,
677 MCRegister Reg) const {
678 CallingConv::ID CC = MF.getFunction().getCallingConv();
679 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
680 bool IsVarArg = STI.isCallingConvWin64(MF.getFunction().getCallingConv(),
681 MF.getFunction().isVarArg());
682
683 auto HasReg = [](ArrayRef<MCRegister> RegList, MCRegister Reg) {
684 return llvm::is_contained(RegList, Reg);
685 };
686
687 switch (CC) {
688 default:
689 report_fatal_error("Unsupported calling convention.");
690 case CallingConv::GHC:
691 return HasReg(CC_AArch64_GHC_ArgRegs, Reg);
692 case CallingConv::PreserveNone:
693 if (!MF.getFunction().isVarArg())
694 return HasReg(CC_AArch64_Preserve_None_ArgRegs, Reg);
695 [[fallthrough]];
696 case CallingConv::C:
697 case CallingConv::Fast:
698 case CallingConv::PreserveMost:
699 case CallingConv::PreserveAll:
700 case CallingConv::CXX_FAST_TLS:
701 case CallingConv::Swift:
702 case CallingConv::SwiftTail:
703 case CallingConv::Tail:
704 if (STI.isTargetWindows()) {
705 if (IsVarArg)
706 return HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
707 switch (CC) {
708 default:
709 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
710 case CallingConv::Swift:
711 case CallingConv::SwiftTail:
712 return HasReg(CC_AArch64_Win64PCS_Swift_ArgRegs, Reg) ||
713 HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
714 }
715 }
716 if (!STI.isTargetDarwin()) {
717 switch (CC) {
718 default:
719 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
720 case CallingConv::Swift:
721 case CallingConv::SwiftTail:
722 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg) ||
723 HasReg(CC_AArch64_AAPCS_Swift_ArgRegs, Reg);
724 }
725 }
726 if (!IsVarArg) {
727 switch (CC) {
728 default:
729 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg);
730 case CallingConv::Swift:
731 case CallingConv::SwiftTail:
732 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg) ||
733 HasReg(CC_AArch64_DarwinPCS_Swift_ArgRegs, Reg);
734 }
735 }
736 if (STI.isTargetILP32())
737 return HasReg(CC_AArch64_DarwinPCS_ILP32_VarArg_ArgRegs, Reg);
738 return HasReg(CC_AArch64_DarwinPCS_VarArg_ArgRegs, Reg);
739 case CallingConv::Win64:
740 if (IsVarArg)
741 HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
742 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
743 case CallingConv::CFGuard_Check:
744 return HasReg(CC_AArch64_Win64_CFGuard_Check_ArgRegs, Reg);
745 case CallingConv::AArch64_VectorCall:
746 case CallingConv::AArch64_SVE_VectorCall:
747 case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0:
748 case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1:
749 case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2:
750 if (STI.isTargetWindows())
751 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
752 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
753 }
754 }
755
756 Register
getFrameRegister(const MachineFunction & MF) const757 AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
758 const AArch64FrameLowering *TFI = getFrameLowering(MF);
759 return TFI->hasFP(MF) ? AArch64::FP : AArch64::SP;
760 }
761
requiresRegisterScavenging(const MachineFunction & MF) const762 bool AArch64RegisterInfo::requiresRegisterScavenging(
763 const MachineFunction &MF) const {
764 return true;
765 }
766
requiresVirtualBaseRegisters(const MachineFunction & MF) const767 bool AArch64RegisterInfo::requiresVirtualBaseRegisters(
768 const MachineFunction &MF) const {
769 return true;
770 }
771
772 bool
useFPForScavengingIndex(const MachineFunction & MF) const773 AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
774 // This function indicates whether the emergency spillslot should be placed
775 // close to the beginning of the stackframe (closer to FP) or the end
776 // (closer to SP).
777 //
778 // The beginning works most reliably if we have a frame pointer.
779 // In the presence of any non-constant space between FP and locals,
780 // (e.g. in case of stack realignment or a scalable SVE area), it is
781 // better to use SP or BP.
782 const AArch64FrameLowering &TFI = *getFrameLowering(MF);
783 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
784 assert((!MF.getSubtarget<AArch64Subtarget>().hasSVE() ||
785 AFI->hasCalculatedStackSizeSVE()) &&
786 "Expected SVE area to be calculated by this point");
787 return TFI.hasFP(MF) && !hasStackRealignment(MF) && !AFI->getStackSizeSVE() &&
788 !AFI->hasStackHazardSlotIndex();
789 }
790
requiresFrameIndexScavenging(const MachineFunction & MF) const791 bool AArch64RegisterInfo::requiresFrameIndexScavenging(
792 const MachineFunction &MF) const {
793 return true;
794 }
795
796 bool
cannotEliminateFrame(const MachineFunction & MF) const797 AArch64RegisterInfo::cannotEliminateFrame(const MachineFunction &MF) const {
798 const MachineFrameInfo &MFI = MF.getFrameInfo();
799 if (MF.getTarget().Options.DisableFramePointerElim(MF) && MFI.adjustsStack())
800 return true;
801 return MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
802 }
803
804 /// needsFrameBaseReg - Returns true if the instruction's frame index
805 /// reference would be better served by a base register other than FP
806 /// or SP. Used by LocalStackFrameAllocation to determine which frame index
807 /// references it should create new base registers for.
needsFrameBaseReg(MachineInstr * MI,int64_t Offset) const808 bool AArch64RegisterInfo::needsFrameBaseReg(MachineInstr *MI,
809 int64_t Offset) const {
810 for (unsigned i = 0; !MI->getOperand(i).isFI(); ++i)
811 assert(i < MI->getNumOperands() &&
812 "Instr doesn't have FrameIndex operand!");
813
814 // It's the load/store FI references that cause issues, as it can be difficult
815 // to materialize the offset if it won't fit in the literal field. Estimate
816 // based on the size of the local frame and some conservative assumptions
817 // about the rest of the stack frame (note, this is pre-regalloc, so
818 // we don't know everything for certain yet) whether this offset is likely
819 // to be out of range of the immediate. Return true if so.
820
821 // We only generate virtual base registers for loads and stores, so
822 // return false for everything else.
823 if (!MI->mayLoad() && !MI->mayStore())
824 return false;
825
826 // Without a virtual base register, if the function has variable sized
827 // objects, all fixed-size local references will be via the frame pointer,
828 // Approximate the offset and see if it's legal for the instruction.
829 // Note that the incoming offset is based on the SP value at function entry,
830 // so it'll be negative.
831 MachineFunction &MF = *MI->getParent()->getParent();
832 const AArch64FrameLowering *TFI = getFrameLowering(MF);
833 MachineFrameInfo &MFI = MF.getFrameInfo();
834
835 // Estimate an offset from the frame pointer.
836 // Conservatively assume all GPR callee-saved registers get pushed.
837 // FP, LR, X19-X28, D8-D15. 64-bits each.
838 int64_t FPOffset = Offset - 16 * 20;
839 // Estimate an offset from the stack pointer.
840 // The incoming offset is relating to the SP at the start of the function,
841 // but when we access the local it'll be relative to the SP after local
842 // allocation, so adjust our SP-relative offset by that allocation size.
843 Offset += MFI.getLocalFrameSize();
844 // Assume that we'll have at least some spill slots allocated.
845 // FIXME: This is a total SWAG number. We should run some statistics
846 // and pick a real one.
847 Offset += 128; // 128 bytes of spill slots
848
849 // If there is a frame pointer, try using it.
850 // The FP is only available if there is no dynamic realignment. We
851 // don't know for sure yet whether we'll need that, so we guess based
852 // on whether there are any local variables that would trigger it.
853 if (TFI->hasFP(MF) && isFrameOffsetLegal(MI, AArch64::FP, FPOffset))
854 return false;
855
856 // If we can reference via the stack pointer or base pointer, try that.
857 // FIXME: This (and the code that resolves the references) can be improved
858 // to only disallow SP relative references in the live range of
859 // the VLA(s). In practice, it's unclear how much difference that
860 // would make, but it may be worth doing.
861 if (isFrameOffsetLegal(MI, AArch64::SP, Offset))
862 return false;
863
864 // If even offset 0 is illegal, we don't want a virtual base register.
865 if (!isFrameOffsetLegal(MI, AArch64::SP, 0))
866 return false;
867
868 // The offset likely isn't legal; we want to allocate a virtual base register.
869 return true;
870 }
871
isFrameOffsetLegal(const MachineInstr * MI,Register BaseReg,int64_t Offset) const872 bool AArch64RegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
873 Register BaseReg,
874 int64_t Offset) const {
875 assert(MI && "Unable to get the legal offset for nil instruction.");
876 StackOffset SaveOffset = StackOffset::getFixed(Offset);
877 return isAArch64FrameOffsetLegal(*MI, SaveOffset) & AArch64FrameOffsetIsLegal;
878 }
879
880 /// Insert defining instruction(s) for BaseReg to be a pointer to FrameIdx
881 /// at the beginning of the basic block.
882 Register
materializeFrameBaseRegister(MachineBasicBlock * MBB,int FrameIdx,int64_t Offset) const883 AArch64RegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB,
884 int FrameIdx,
885 int64_t Offset) const {
886 MachineBasicBlock::iterator Ins = MBB->begin();
887 DebugLoc DL; // Defaults to "unknown"
888 if (Ins != MBB->end())
889 DL = Ins->getDebugLoc();
890 const MachineFunction &MF = *MBB->getParent();
891 const AArch64InstrInfo *TII =
892 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
893 const MCInstrDesc &MCID = TII->get(AArch64::ADDXri);
894 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
895 Register BaseReg = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
896 MRI.constrainRegClass(BaseReg, TII->getRegClass(MCID, 0, this, MF));
897 unsigned Shifter = AArch64_AM::getShifterImm(AArch64_AM::LSL, 0);
898
899 BuildMI(*MBB, Ins, DL, MCID, BaseReg)
900 .addFrameIndex(FrameIdx)
901 .addImm(Offset)
902 .addImm(Shifter);
903
904 return BaseReg;
905 }
906
resolveFrameIndex(MachineInstr & MI,Register BaseReg,int64_t Offset) const907 void AArch64RegisterInfo::resolveFrameIndex(MachineInstr &MI, Register BaseReg,
908 int64_t Offset) const {
909 // ARM doesn't need the general 64-bit offsets
910 StackOffset Off = StackOffset::getFixed(Offset);
911
912 unsigned i = 0;
913 while (!MI.getOperand(i).isFI()) {
914 ++i;
915 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
916 }
917
918 const MachineFunction *MF = MI.getParent()->getParent();
919 const AArch64InstrInfo *TII =
920 MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
921 bool Done = rewriteAArch64FrameIndex(MI, i, BaseReg, Off, TII);
922 assert(Done && "Unable to resolve frame index!");
923 (void)Done;
924 }
925
926 // Create a scratch register for the frame index elimination in an instruction.
927 // This function has special handling of stack tagging loop pseudos, in which
928 // case it can also change the instruction opcode.
929 static Register
createScratchRegisterForInstruction(MachineInstr & MI,unsigned FIOperandNum,const AArch64InstrInfo * TII)930 createScratchRegisterForInstruction(MachineInstr &MI, unsigned FIOperandNum,
931 const AArch64InstrInfo *TII) {
932 // ST*Gloop have a reserved scratch register in operand 1. Use it, and also
933 // replace the instruction with the writeback variant because it will now
934 // satisfy the operand constraints for it.
935 Register ScratchReg;
936 if (MI.getOpcode() == AArch64::STGloop ||
937 MI.getOpcode() == AArch64::STZGloop) {
938 assert(FIOperandNum == 3 &&
939 "Wrong frame index operand for STGloop/STZGloop");
940 unsigned Op = MI.getOpcode() == AArch64::STGloop ? AArch64::STGloop_wback
941 : AArch64::STZGloop_wback;
942 ScratchReg = MI.getOperand(1).getReg();
943 MI.getOperand(3).ChangeToRegister(ScratchReg, false, false, true);
944 MI.setDesc(TII->get(Op));
945 MI.tieOperands(1, 3);
946 } else {
947 ScratchReg =
948 MI.getMF()->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
949 MI.getOperand(FIOperandNum)
950 .ChangeToRegister(ScratchReg, false, false, true);
951 }
952 return ScratchReg;
953 }
954
getOffsetOpcodes(const StackOffset & Offset,SmallVectorImpl<uint64_t> & Ops) const955 void AArch64RegisterInfo::getOffsetOpcodes(
956 const StackOffset &Offset, SmallVectorImpl<uint64_t> &Ops) const {
957 // The smallest scalable element supported by scaled SVE addressing
958 // modes are predicates, which are 2 scalable bytes in size. So the scalable
959 // byte offset must always be a multiple of 2.
960 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
961
962 // Add fixed-sized offset using existing DIExpression interface.
963 DIExpression::appendOffset(Ops, Offset.getFixed());
964
965 unsigned VG = getDwarfRegNum(AArch64::VG, true);
966 int64_t VGSized = Offset.getScalable() / 2;
967 if (VGSized > 0) {
968 Ops.push_back(dwarf::DW_OP_constu);
969 Ops.push_back(VGSized);
970 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
971 Ops.push_back(dwarf::DW_OP_mul);
972 Ops.push_back(dwarf::DW_OP_plus);
973 } else if (VGSized < 0) {
974 Ops.push_back(dwarf::DW_OP_constu);
975 Ops.push_back(-VGSized);
976 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
977 Ops.push_back(dwarf::DW_OP_mul);
978 Ops.push_back(dwarf::DW_OP_minus);
979 }
980 }
981
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const982 bool AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
983 int SPAdj, unsigned FIOperandNum,
984 RegScavenger *RS) const {
985 assert(SPAdj == 0 && "Unexpected");
986
987 MachineInstr &MI = *II;
988 MachineBasicBlock &MBB = *MI.getParent();
989 MachineFunction &MF = *MBB.getParent();
990 const MachineFrameInfo &MFI = MF.getFrameInfo();
991 const AArch64InstrInfo *TII =
992 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
993 const AArch64FrameLowering *TFI = getFrameLowering(MF);
994 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
995 bool Tagged =
996 MI.getOperand(FIOperandNum).getTargetFlags() & AArch64II::MO_TAGGED;
997 Register FrameReg;
998
999 // Special handling of dbg_value, stackmap patchpoint statepoint instructions.
1000 if (MI.getOpcode() == TargetOpcode::STACKMAP ||
1001 MI.getOpcode() == TargetOpcode::PATCHPOINT ||
1002 MI.getOpcode() == TargetOpcode::STATEPOINT) {
1003 StackOffset Offset =
1004 TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg,
1005 /*PreferFP=*/true,
1006 /*ForSimm=*/false);
1007 Offset += StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
1008 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
1009 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
1010 return false;
1011 }
1012
1013 if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) {
1014 MachineOperand &FI = MI.getOperand(FIOperandNum);
1015 StackOffset Offset = TFI->getNonLocalFrameIndexReference(MF, FrameIndex);
1016 assert(!Offset.getScalable() &&
1017 "Frame offsets with a scalable component are not supported");
1018 FI.ChangeToImmediate(Offset.getFixed());
1019 return false;
1020 }
1021
1022 StackOffset Offset;
1023 if (MI.getOpcode() == AArch64::TAGPstack) {
1024 // TAGPstack must use the virtual frame register in its 3rd operand.
1025 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1026 FrameReg = MI.getOperand(3).getReg();
1027 Offset = StackOffset::getFixed(MFI.getObjectOffset(FrameIndex) +
1028 AFI->getTaggedBasePointerOffset());
1029 } else if (Tagged) {
1030 StackOffset SPOffset = StackOffset::getFixed(
1031 MFI.getObjectOffset(FrameIndex) + (int64_t)MFI.getStackSize());
1032 if (MFI.hasVarSizedObjects() ||
1033 isAArch64FrameOffsetLegal(MI, SPOffset, nullptr, nullptr, nullptr) !=
1034 (AArch64FrameOffsetCanUpdate | AArch64FrameOffsetIsLegal)) {
1035 // Can't update to SP + offset in place. Precalculate the tagged pointer
1036 // in a scratch register.
1037 Offset = TFI->resolveFrameIndexReference(
1038 MF, FrameIndex, FrameReg, /*PreferFP=*/false, /*ForSimm=*/true);
1039 Register ScratchReg =
1040 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1041 emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset,
1042 TII);
1043 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(AArch64::LDG), ScratchReg)
1044 .addReg(ScratchReg)
1045 .addReg(ScratchReg)
1046 .addImm(0);
1047 MI.getOperand(FIOperandNum)
1048 .ChangeToRegister(ScratchReg, false, false, true);
1049 return false;
1050 }
1051 FrameReg = AArch64::SP;
1052 Offset = StackOffset::getFixed(MFI.getObjectOffset(FrameIndex) +
1053 (int64_t)MFI.getStackSize());
1054 } else {
1055 Offset = TFI->resolveFrameIndexReference(
1056 MF, FrameIndex, FrameReg, /*PreferFP=*/false, /*ForSimm=*/true);
1057 }
1058
1059 // Modify MI as necessary to handle as much of 'Offset' as possible
1060 if (rewriteAArch64FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
1061 return true;
1062
1063 assert((!RS || !RS->isScavengingFrameIndex(FrameIndex)) &&
1064 "Emergency spill slot is out of reach");
1065
1066 // If we get here, the immediate doesn't fit into the instruction. We folded
1067 // as much as possible above. Handle the rest, providing a register that is
1068 // SP+LargeImm.
1069 Register ScratchReg =
1070 createScratchRegisterForInstruction(MI, FIOperandNum, TII);
1071 emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset, TII);
1072 return false;
1073 }
1074
getRegPressureLimit(const TargetRegisterClass * RC,MachineFunction & MF) const1075 unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
1076 MachineFunction &MF) const {
1077 const AArch64FrameLowering *TFI = getFrameLowering(MF);
1078
1079 switch (RC->getID()) {
1080 default:
1081 return 0;
1082 case AArch64::GPR32RegClassID:
1083 case AArch64::GPR32spRegClassID:
1084 case AArch64::GPR32allRegClassID:
1085 case AArch64::GPR64spRegClassID:
1086 case AArch64::GPR64allRegClassID:
1087 case AArch64::GPR64RegClassID:
1088 case AArch64::GPR32commonRegClassID:
1089 case AArch64::GPR64commonRegClassID:
1090 return 32 - 1 // XZR/SP
1091 - (TFI->hasFP(MF) || TT.isOSDarwin()) // FP
1092 - MF.getSubtarget<AArch64Subtarget>().getNumXRegisterReserved()
1093 - hasBasePointer(MF); // X19
1094 case AArch64::FPR8RegClassID:
1095 case AArch64::FPR16RegClassID:
1096 case AArch64::FPR32RegClassID:
1097 case AArch64::FPR64RegClassID:
1098 case AArch64::FPR128RegClassID:
1099 return 32;
1100
1101 case AArch64::MatrixIndexGPR32_8_11RegClassID:
1102 case AArch64::MatrixIndexGPR32_12_15RegClassID:
1103 return 4;
1104
1105 case AArch64::DDRegClassID:
1106 case AArch64::DDDRegClassID:
1107 case AArch64::DDDDRegClassID:
1108 case AArch64::QQRegClassID:
1109 case AArch64::QQQRegClassID:
1110 case AArch64::QQQQRegClassID:
1111 return 32;
1112
1113 case AArch64::FPR128_loRegClassID:
1114 case AArch64::FPR64_loRegClassID:
1115 case AArch64::FPR16_loRegClassID:
1116 return 16;
1117 case AArch64::FPR128_0to7RegClassID:
1118 return 8;
1119 }
1120 }
1121
1122 // FORM_TRANSPOSED_REG_TUPLE nodes are created to improve register allocation
1123 // where a consecutive multi-vector tuple is constructed from the same indices
1124 // of multiple strided loads. This may still result in unnecessary copies
1125 // between the loads and the tuple. Here we try to return a hint to assign the
1126 // contiguous ZPRMulReg starting at the same register as the first operand of
1127 // the pseudo, which should be a subregister of the first strided load.
1128 //
1129 // For example, if the first strided load has been assigned $z16_z20_z24_z28
1130 // and the operands of the pseudo are each accessing subregister zsub2, we
1131 // should look through through Order to find a contiguous register which
1132 // begins with $z24 (i.e. $z24_z25_z26_z27).
1133 //
getRegAllocationHints(Register VirtReg,ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const MachineFunction & MF,const VirtRegMap * VRM,const LiveRegMatrix * Matrix) const1134 bool AArch64RegisterInfo::getRegAllocationHints(
1135 Register VirtReg, ArrayRef<MCPhysReg> Order,
1136 SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
1137 const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
1138
1139 auto &ST = MF.getSubtarget<AArch64Subtarget>();
1140 if (!ST.hasSME() || !ST.isStreaming())
1141 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
1142 VRM);
1143
1144 // The SVE calling convention preserves registers Z8-Z23. As a result, there
1145 // are no ZPR2Strided or ZPR4Strided registers that do not overlap with the
1146 // callee-saved registers and so by default these will be pushed to the back
1147 // of the allocation order for the ZPRStridedOrContiguous classes.
1148 // If any of the instructions which define VirtReg are used by the
1149 // FORM_TRANSPOSED_REG_TUPLE pseudo, we want to favour reducing copy
1150 // instructions over reducing the number of clobbered callee-save registers,
1151 // so we add the strided registers as a hint.
1152 const MachineRegisterInfo &MRI = MF.getRegInfo();
1153 unsigned RegID = MRI.getRegClass(VirtReg)->getID();
1154 if (RegID == AArch64::ZPR2StridedOrContiguousRegClassID ||
1155 RegID == AArch64::ZPR4StridedOrContiguousRegClassID) {
1156
1157 // Look through uses of the register for FORM_TRANSPOSED_REG_TUPLE.
1158 for (const MachineInstr &Use : MRI.use_nodbg_instructions(VirtReg)) {
1159 if (Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO &&
1160 Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO)
1161 continue;
1162
1163 unsigned UseOps = Use.getNumOperands() - 1;
1164 const TargetRegisterClass *StridedRC;
1165 switch (RegID) {
1166 case AArch64::ZPR2StridedOrContiguousRegClassID:
1167 StridedRC = &AArch64::ZPR2StridedRegClass;
1168 break;
1169 case AArch64::ZPR4StridedOrContiguousRegClassID:
1170 StridedRC = &AArch64::ZPR4StridedRegClass;
1171 break;
1172 default:
1173 llvm_unreachable("Unexpected RegID");
1174 }
1175
1176 SmallVector<MCPhysReg, 4> StridedOrder;
1177 for (MCPhysReg Reg : Order)
1178 if (StridedRC->contains(Reg))
1179 StridedOrder.push_back(Reg);
1180
1181 int OpIdx = Use.findRegisterUseOperandIdx(VirtReg, this);
1182 assert(OpIdx != -1 && "Expected operand index from register use.");
1183
1184 unsigned TupleID = MRI.getRegClass(Use.getOperand(0).getReg())->getID();
1185 bool IsMulZPR = TupleID == AArch64::ZPR2Mul2RegClassID ||
1186 TupleID == AArch64::ZPR4Mul4RegClassID;
1187
1188 const MachineOperand *AssignedRegOp = llvm::find_if(
1189 make_range(Use.operands_begin() + 1, Use.operands_end()),
1190 [&VRM](const MachineOperand &Op) {
1191 return VRM->hasPhys(Op.getReg());
1192 });
1193
1194 // Example:
1195 //
1196 // When trying to find a suitable register allocation for VirtReg %v2 in:
1197 //
1198 // %v0:zpr2stridedorcontiguous = ld1 p0/z, [...]
1199 // %v1:zpr2stridedorcontiguous = ld1 p0/z, [...]
1200 // %v2:zpr2stridedorcontiguous = ld1 p0/z, [...]
1201 // %v3:zpr2stridedorcontiguous = ld1 p0/z, [...]
1202 // %v4:zpr4mul4 = FORM_TRANSPOSED_X4 %v0:0, %v1:0, %v2:0, %v3:0
1203 //
1204 // One such suitable allocation would be:
1205 //
1206 // { z0, z8 } = ld1 p0/z, [...]
1207 // { z1, z9 } = ld1 p0/z, [...]
1208 // { z2, z10 } = ld1 p0/z, [...]
1209 // { z3, z11 } = ld1 p0/z, [...]
1210 // { z0, z1, z2, z3 } =
1211 // FORM_TRANSPOSED_X4 {z0, z8}:0, {z1, z9}:0, {z2, z10}:0, {z3, z11}:0
1212 //
1213 // Below we distinguish two cases when trying to find a register:
1214 // * None of the registers used by FORM_TRANSPOSED_X4 have been assigned
1215 // yet. In this case the code muse ensure that there are at least UseOps
1216 // free consecutive registers. If IsMulZPR is true, then the first of
1217 // registers must also be a multiple of UseOps, e.g. { z0, z1, z2, z3 }
1218 // is valid but { z1, z2, z3, z5 } is not.
1219 // * One or more of the registers used by FORM_TRANSPOSED_X4 is already
1220 // assigned a physical register, which means only checking that a
1221 // consecutive range of free tuple registers exists which includes
1222 // the assigned register.
1223 // e.g. in the example above, if { z0, z8 } is already allocated for
1224 // %v0, we just need to ensure that { z1, z9 }, { z2, z10 } and
1225 // { z3, z11 } are also free. If so, we add { z2, z10 }.
1226
1227 if (AssignedRegOp == Use.operands_end()) {
1228 // There are no registers already assigned to any of the pseudo
1229 // operands. Look for a valid starting register for the group.
1230 for (unsigned I = 0; I < StridedOrder.size(); ++I) {
1231 MCPhysReg Reg = StridedOrder[I];
1232
1233 // If the FORM_TRANSPOSE nodes use the ZPRMul classes, the starting
1234 // register of the first load should be a multiple of 2 or 4.
1235 unsigned SubRegIdx = Use.getOperand(OpIdx).getSubReg();
1236 if (IsMulZPR && (getSubReg(Reg, SubRegIdx) - AArch64::Z0) % UseOps !=
1237 ((unsigned)OpIdx - 1))
1238 continue;
1239
1240 // In the example above, if VirtReg is the third operand of the
1241 // tuple (%v2) and Reg == Z2_Z10, then we need to make sure that
1242 // Z0_Z8, Z1_Z9 and Z3_Z11 are also available.
1243 auto IsFreeConsecutiveReg = [&](unsigned UseOp) {
1244 unsigned R = Reg - (OpIdx - 1) + UseOp;
1245 return StridedRC->contains(R) &&
1246 (UseOp == 0 ||
1247 ((getSubReg(R, AArch64::zsub0) - AArch64::Z0) ==
1248 (getSubReg(R - 1, AArch64::zsub0) - AArch64::Z0) + 1)) &&
1249 !Matrix->isPhysRegUsed(R);
1250 };
1251 if (all_of(iota_range<unsigned>(0U, UseOps, /*Inclusive=*/false),
1252 IsFreeConsecutiveReg))
1253 Hints.push_back(Reg);
1254 }
1255 } else {
1256 // At least one operand already has a physical register assigned.
1257 // Find the starting sub-register of this and use it to work out the
1258 // correct strided register to suggest based on the current op index.
1259 MCPhysReg TargetStartReg =
1260 getSubReg(VRM->getPhys(AssignedRegOp->getReg()), AArch64::zsub0) +
1261 (OpIdx - AssignedRegOp->getOperandNo());
1262
1263 for (unsigned I = 0; I < StridedOrder.size(); ++I)
1264 if (getSubReg(StridedOrder[I], AArch64::zsub0) == TargetStartReg)
1265 Hints.push_back(StridedOrder[I]);
1266 }
1267
1268 if (!Hints.empty())
1269 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints,
1270 MF, VRM);
1271 }
1272 }
1273
1274 for (MachineInstr &MI : MRI.def_instructions(VirtReg)) {
1275 if (MI.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO &&
1276 MI.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO)
1277 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints,
1278 MF, VRM);
1279
1280 unsigned FirstOpSubReg = MI.getOperand(1).getSubReg();
1281 switch (FirstOpSubReg) {
1282 case AArch64::zsub0:
1283 case AArch64::zsub1:
1284 case AArch64::zsub2:
1285 case AArch64::zsub3:
1286 break;
1287 default:
1288 continue;
1289 }
1290
1291 // Look up the physical register mapped to the first operand of the pseudo.
1292 Register FirstOpVirtReg = MI.getOperand(1).getReg();
1293 if (!VRM->hasPhys(FirstOpVirtReg))
1294 continue;
1295
1296 MCRegister TupleStartReg =
1297 getSubReg(VRM->getPhys(FirstOpVirtReg), FirstOpSubReg);
1298 for (unsigned I = 0; I < Order.size(); ++I)
1299 if (MCRegister R = getSubReg(Order[I], AArch64::zsub0))
1300 if (R == TupleStartReg)
1301 Hints.push_back(Order[I]);
1302 }
1303
1304 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
1305 VRM);
1306 }
1307
getLocalAddressRegister(const MachineFunction & MF) const1308 unsigned AArch64RegisterInfo::getLocalAddressRegister(
1309 const MachineFunction &MF) const {
1310 const auto &MFI = MF.getFrameInfo();
1311 if (!MF.hasEHFunclets() && !MFI.hasVarSizedObjects())
1312 return AArch64::SP;
1313 else if (hasStackRealignment(MF))
1314 return getBaseRegister();
1315 return getFrameRegister(MF);
1316 }
1317
1318 /// SrcRC and DstRC will be morphed into NewRC if this returns true
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const1319 bool AArch64RegisterInfo::shouldCoalesce(
1320 MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg,
1321 const TargetRegisterClass *DstRC, unsigned DstSubReg,
1322 const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
1323 MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
1324
1325 if (MI->isCopy() &&
1326 ((DstRC->getID() == AArch64::GPR64RegClassID) ||
1327 (DstRC->getID() == AArch64::GPR64commonRegClassID)) &&
1328 MI->getOperand(0).getSubReg() && MI->getOperand(1).getSubReg())
1329 // Do not coalesce in the case of a 32-bit subregister copy
1330 // which implements a 32 to 64 bit zero extension
1331 // which relies on the upper 32 bits being zeroed.
1332 return false;
1333
1334 auto IsCoalescerBarrier = [](const MachineInstr &MI) {
1335 switch (MI.getOpcode()) {
1336 case AArch64::COALESCER_BARRIER_FPR16:
1337 case AArch64::COALESCER_BARRIER_FPR32:
1338 case AArch64::COALESCER_BARRIER_FPR64:
1339 case AArch64::COALESCER_BARRIER_FPR128:
1340 return true;
1341 default:
1342 return false;
1343 }
1344 };
1345
1346 // For calls that temporarily have to toggle streaming mode as part of the
1347 // call-sequence, we need to be more careful when coalescing copy instructions
1348 // so that we don't end up coalescing the NEON/FP result or argument register
1349 // with a whole Z-register, such that after coalescing the register allocator
1350 // will try to spill/reload the entire Z register.
1351 //
1352 // We do this by checking if the node has any defs/uses that are
1353 // COALESCER_BARRIER pseudos. These are 'nops' in practice, but they exist to
1354 // instruct the coalescer to avoid coalescing the copy.
1355 if (MI->isCopy() && SubReg != DstSubReg &&
1356 (AArch64::ZPRRegClass.hasSubClassEq(DstRC) ||
1357 AArch64::ZPRRegClass.hasSubClassEq(SrcRC))) {
1358 unsigned SrcReg = MI->getOperand(1).getReg();
1359 if (any_of(MRI.def_instructions(SrcReg), IsCoalescerBarrier))
1360 return false;
1361 unsigned DstReg = MI->getOperand(0).getReg();
1362 if (any_of(MRI.use_nodbg_instructions(DstReg), IsCoalescerBarrier))
1363 return false;
1364 }
1365
1366 return true;
1367 }
1368
shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const1369 bool AArch64RegisterInfo::shouldAnalyzePhysregInMachineLoopInfo(
1370 MCRegister R) const {
1371 return R == AArch64::VG;
1372 }
1373
isIgnoredCVReg(MCRegister LLVMReg) const1374 bool AArch64RegisterInfo::isIgnoredCVReg(MCRegister LLVMReg) const {
1375 return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
1376 (LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
1377 }
1378