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