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