LLVM 24.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"
34
35using namespace llvm;
36
37#define GET_CC_REGISTER_LISTS
38#include "AArch64GenCallingConv.inc"
39#define GET_REGINFO_TARGET_DESC
40#include "AArch64GenRegisterInfo.inc"
41
43 : AArch64GenRegisterInfo(AArch64::LR, 0, 0, 0, HwMode), TT(TT) {
45}
46
47/// Return whether the register needs a CFI entry. Not all unwinders may know
48/// about SVE registers, so we assume the lowest common denominator, i.e. the
49/// callee-saves required by the base ABI. For the SVE registers z8-z15 only the
50/// lower 64-bits (d8-d15) need to be saved. The lower 64-bits subreg is
51/// returned in \p RegToUseForCFI.
53 MCRegister &RegToUseForCFI) const {
54 if (AArch64::PPRRegClass.contains(Reg))
55 return false;
56
57 if (AArch64::ZPRRegClass.contains(Reg)) {
58 RegToUseForCFI = getSubReg(Reg, AArch64::dsub);
59 for (int I = 0; CSR_AArch64_AAPCS_SaveList[I]; ++I) {
60 if (CSR_AArch64_AAPCS_SaveList[I] == RegToUseForCFI)
61 return true;
62 }
63 return false;
64 }
65
66 RegToUseForCFI = Reg;
67 return true;
68}
69
70const MCPhysReg *
72 assert(MF && "Invalid MachineFunction pointer.");
73
74 auto &AFI = *MF->getInfo<AArch64FunctionInfo>();
75 const auto &F = MF->getFunction();
76 const auto *TLI = MF->getSubtarget<AArch64Subtarget>().getTargetLowering();
77 const bool Darwin = MF->getSubtarget<AArch64Subtarget>().isTargetDarwin();
78 const bool Windows = MF->getSubtarget<AArch64Subtarget>().isTargetWindows();
79
80 if (TLI->supportSwiftError() &&
81 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError)) {
82 if (Darwin)
83 return CSR_Darwin_AArch64_AAPCS_SwiftError_SaveList;
84 if (Windows)
85 return CSR_Win_AArch64_AAPCS_SwiftError_SaveList;
86 return CSR_AArch64_AAPCS_SwiftError_SaveList;
87 }
88
89 switch (F.getCallingConv()) {
91 // GHC set of callee saved regs is empty as all those regs are
92 // used for passing STG regs around
93 return CSR_AArch64_NoRegs_SaveList;
94
96 // FIXME: Windows likely need this to be altered for properly unwinding.
97 return CSR_AArch64_NoneRegs_SaveList;
98
100 return CSR_AArch64_AllRegs_SaveList;
101
103 return CSR_Win_AArch64_Arm64EC_Thunk_SaveList;
104
106 if (Darwin)
107 return CSR_Darwin_AArch64_RT_MostRegs_SaveList;
108 if (Windows)
109 return CSR_Win_AArch64_RT_MostRegs_SaveList;
110 return CSR_AArch64_RT_MostRegs_SaveList;
111
113 if (Darwin)
114 return CSR_Darwin_AArch64_RT_AllRegs_SaveList;
115 if (Windows)
116 return CSR_Win_AArch64_RT_AllRegs_SaveList;
117 return CSR_AArch64_RT_AllRegs_SaveList;
118
120 if (Darwin)
122 "Calling convention CFGuard_Check is unsupported on Darwin.");
123 return CSR_Win_AArch64_CFGuard_Check_SaveList;
124
126 if (Darwin)
127 return CSR_Darwin_AArch64_AAPCS_SwiftTail_SaveList;
128 if (Windows)
129 return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList;
130 return CSR_AArch64_AAPCS_SwiftTail_SaveList;
131
133 if (Darwin)
134 return CSR_Darwin_AArch64_AAVPCS_SaveList;
135 if (Windows)
136 return CSR_Win_AArch64_AAVPCS_SaveList;
137 return CSR_AArch64_AAVPCS_SaveList;
138
140 if (Darwin)
142 "Calling convention SVE_VectorCall is unsupported on Darwin.");
143 if (Windows)
144 return CSR_Win_AArch64_SVE_AAPCS_SaveList;
145 return CSR_AArch64_SVE_AAPCS_SaveList;
146
149 "Calling convention "
150 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 is only "
151 "supported to improve calls to SME ACLE save/restore/disable-za "
152 "functions, and is not intended to be used beyond that scope.");
153
156 "Calling convention "
157 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1 is "
158 "only supported to improve calls to SME ACLE __arm_get_current_vg "
159 "function, and is not intended to be used beyond that scope.");
160
163 "Calling convention "
164 "AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 is "
165 "only supported to improve calls to SME ACLE __arm_sme_state "
166 "and is not intended to be used beyond that scope.");
167
169 if (Darwin)
170 return CSR_Darwin_AArch64_AAPCS_Win64_SaveList;
171 if (Windows)
172 return CSR_Win_AArch64_AAPCS_SaveList;
173 return CSR_AArch64_AAPCS_X18_SaveList;
174
176 if (Darwin)
177 return AFI.isSplitCSR() ? CSR_Darwin_AArch64_CXX_TLS_PE_SaveList
178 : CSR_Darwin_AArch64_CXX_TLS_SaveList;
179 // FIXME: this likely should be a `report_fatal_error` condition, however,
180 // that would be a departure from the previously implemented behaviour.
182
183 default:
184 if (Darwin)
185 return AFI.hasSVE_AAPCS(*MF) ? CSR_Darwin_AArch64_SVE_AAPCS_SaveList
186 : CSR_Darwin_AArch64_AAPCS_SaveList;
187 if (Windows)
188 return AFI.hasSVE_AAPCS(*MF) ? CSR_Win_AArch64_SVE_AAPCS_SaveList
189 : CSR_Win_AArch64_AAPCS_SaveList;
190 return AFI.hasSVE_AAPCS(*MF) ? CSR_AArch64_SVE_AAPCS_SaveList
191 : CSR_AArch64_AAPCS_SaveList;
192 }
193}
194
196 const MachineFunction *MF) const {
197 assert(MF && "Invalid MachineFunction pointer.");
200 return CSR_Darwin_AArch64_CXX_TLS_ViaCopy_SaveList;
201 return nullptr;
202}
203
205 MachineFunction &MF) const {
206 const MCPhysReg *CSRs = getCalleeSavedRegs(&MF);
207 SmallVector<MCPhysReg, 32> UpdatedCSRs;
208 for (const MCPhysReg *I = CSRs; *I; ++I)
209 UpdatedCSRs.push_back(*I);
210
211 for (size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
213 UpdatedCSRs.push_back(AArch64::GPR64commonRegClass.getRegister(i));
214 }
215 }
216 // Register lists are zero-terminated.
217 UpdatedCSRs.push_back(0);
218 MF.getRegInfo().setCalleeSavedRegs(UpdatedCSRs);
219}
220
223 unsigned Idx) const {
224 // edge case for GPR/FPR register classes
225 if (RC == &AArch64::GPR32allRegClass && Idx == AArch64::hsub)
226 return &AArch64::FPR32RegClass;
227 else if (RC == &AArch64::GPR64allRegClass && Idx == AArch64::hsub)
228 return &AArch64::FPR64RegClass;
229
230 // Forward to TableGen's default version.
231 return AArch64GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
232}
233
234const uint32_t *
236 CallingConv::ID CC) const {
238 "Invalid subtarget for getDarwinCallPreservedMask");
239
241 return CSR_Darwin_AArch64_CXX_TLS_RegMask;
243 return CSR_Darwin_AArch64_AAVPCS_RegMask;
245 return CSR_Darwin_AArch64_SVE_AAPCS_RegMask;
247 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
249 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
251 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
254 "Calling convention CFGuard_Check is unsupported on Darwin.");
257 ->supportSwiftError() &&
258 MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
259 return CSR_Darwin_AArch64_AAPCS_SwiftError_RegMask;
260 if (CC == CallingConv::SwiftTail)
261 return CSR_Darwin_AArch64_AAPCS_SwiftTail_RegMask;
263 return CSR_Darwin_AArch64_RT_MostRegs_RegMask;
264 if (CC == CallingConv::PreserveAll)
265 return CSR_Darwin_AArch64_RT_AllRegs_RegMask;
266 return CSR_Darwin_AArch64_AAPCS_RegMask;
267}
268
269const uint32_t *
271 CallingConv::ID CC) const {
272 bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
273 if (CC == CallingConv::GHC)
274 // This is academic because all GHC calls are (supposed to be) tail calls
275 return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
277 return SCS ? CSR_AArch64_NoneRegs_SCS_RegMask
278 : CSR_AArch64_NoneRegs_RegMask;
279 if (CC == CallingConv::AnyReg)
280 return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
281
282 // All the following calling conventions are handled differently on Darwin.
284 if (SCS)
285 report_fatal_error("ShadowCallStack attribute not supported on Darwin.");
286 return getDarwinCallPreservedMask(MF, CC);
287 }
288
290 return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
292 return SCS ? CSR_AArch64_SVE_AAPCS_SCS_RegMask
293 : CSR_AArch64_SVE_AAPCS_RegMask;
295 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
297 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1_RegMask;
299 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2_RegMask;
301 return CSR_Win_AArch64_CFGuard_Check_RegMask;
303 ->supportSwiftError() &&
304 MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
305 return SCS ? CSR_AArch64_AAPCS_SwiftError_SCS_RegMask
306 : CSR_AArch64_AAPCS_SwiftError_RegMask;
307 if (CC == CallingConv::SwiftTail) {
308 if (SCS)
309 report_fatal_error("ShadowCallStack attribute not supported with swifttail");
310 return CSR_AArch64_AAPCS_SwiftTail_RegMask;
311 }
313 return SCS ? CSR_AArch64_RT_MostRegs_SCS_RegMask
314 : CSR_AArch64_RT_MostRegs_RegMask;
315 if (CC == CallingConv::PreserveAll)
316 return SCS ? CSR_AArch64_RT_AllRegs_SCS_RegMask
317 : CSR_AArch64_RT_AllRegs_RegMask;
318
319 return SCS ? CSR_AArch64_AAPCS_SCS_RegMask : CSR_AArch64_AAPCS_RegMask;
320}
321
323 const MachineFunction &MF) const {
325 return CSR_AArch64_AAPCS_RegMask;
326
327 return nullptr;
328}
329
331 if (TT.isOSDarwin())
332 return CSR_Darwin_AArch64_TLS_RegMask;
333
334 assert(TT.isOSBinFormatELF() && "Invalid target");
335 return CSR_AArch64_TLS_ELF_RegMask;
336}
337
339 const uint32_t **Mask) const {
340 uint32_t *UpdatedMask = MF.allocateRegMask();
341 unsigned RegMaskSize = MachineOperand::getRegMaskSize(getNumRegs());
342 memcpy(UpdatedMask, *Mask, sizeof(UpdatedMask[0]) * RegMaskSize);
343
344 for (size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) {
346 for (MCPhysReg SubReg :
347 subregs_inclusive(AArch64::GPR64commonRegClass.getRegister(i))) {
348 // See TargetRegisterInfo::getCallPreservedMask for how to interpret the
349 // register mask.
350 UpdatedMask[SubReg / 32] |= 1u << (SubReg % 32);
351 }
352 }
353 }
354 *Mask = UpdatedMask;
355}
356
358 return CSR_AArch64_SMStartStop_RegMask;
359}
360
361const uint32_t *
363 return CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0_RegMask;
364}
365
367 return CSR_AArch64_NoRegs_RegMask;
368}
369
370const uint32_t *
372 CallingConv::ID CC) const {
373 // This should return a register mask that is the same as that returned by
374 // getCallPreservedMask but that additionally preserves the register used for
375 // the first i64 argument (which must also be the register used to return a
376 // single i64 return value)
377 //
378 // In case that the calling convention does not use the same register for
379 // both, the function should return NULL (does not currently apply)
380 assert(CC != CallingConv::GHC && "should not be GHC calling convention.");
382 return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask;
383 return CSR_AArch64_AAPCS_ThisReturn_RegMask;
384}
385
387 return CSR_AArch64_StackProbe_Windows_RegMask;
388}
389
390std::optional<std::string>
392 MCRegister PhysReg) const {
393 if (hasBasePointer(MF) && MCRegisterInfo::regsOverlap(PhysReg, AArch64::X19))
394 return std::string("X19 is used as the frame base pointer register.");
395
397 bool warn = false;
398 if (MCRegisterInfo::regsOverlap(PhysReg, AArch64::X13) ||
399 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X14) ||
400 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X23) ||
401 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X24) ||
402 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X28))
403 warn = true;
404
405 for (unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
406 if (MCRegisterInfo::regsOverlap(PhysReg, i))
407 warn = true;
408
409 if (warn)
410 return std::string(AArch64InstPrinter::getRegisterName(PhysReg)) +
411 " is clobbered by asynchronous signals when using Arm64EC.";
412 }
413
414 return {};
415}
416
419 const AArch64FrameLowering *TFI = getFrameLowering(MF);
420
421 BitVector Reserved(getNumRegs());
422 markSuperRegs(Reserved, AArch64::WSP);
423 markSuperRegs(Reserved, AArch64::WZR);
424
425 if (TFI->isFPReserved(MF))
426 markSuperRegs(Reserved, AArch64::W29);
427
429 // x13, x14, x23, x24, x28, and v16-v31 are clobbered by asynchronous
430 // signals, so we can't ever use them.
431 markSuperRegs(Reserved, AArch64::W13);
432 markSuperRegs(Reserved, AArch64::W14);
433 markSuperRegs(Reserved, AArch64::W23);
434 markSuperRegs(Reserved, AArch64::W24);
435 markSuperRegs(Reserved, AArch64::W28);
436 for (unsigned i = AArch64::B16; i <= AArch64::B31; ++i)
437 markSuperRegs(Reserved, i);
438 }
439
440 if (MF.getSubtarget<AArch64Subtarget>().isLFI()) {
441 markSuperRegs(Reserved, AArch64::W28);
442 markSuperRegs(Reserved, AArch64::W27);
443 markSuperRegs(Reserved, AArch64::W26);
444 markSuperRegs(Reserved, AArch64::W25);
445 if (!MF.getProperties().hasNoVRegs()) {
446 markSuperRegs(Reserved, AArch64::LR);
447 markSuperRegs(Reserved, AArch64::W30);
448 }
449 }
450
451 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
453 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
454 }
455
456 if (hasBasePointer(MF))
457 markSuperRegs(Reserved, AArch64::W19);
458
459 // SLH uses register W16/X16 as the taint register.
460 if (MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening))
461 markSuperRegs(Reserved, AArch64::W16);
462
463 // FFR is modelled as global state that cannot be allocated.
464 if (MF.getSubtarget<AArch64Subtarget>().hasSVE())
465 Reserved.set(AArch64::FFR);
466
467 // SME tiles are not allocatable.
468 if (MF.getSubtarget<AArch64Subtarget>().hasSME()) {
469 for (MCPhysReg SubReg : subregs_inclusive(AArch64::ZA))
470 Reserved.set(SubReg);
471 }
472
473 // VG cannot be allocated
474 Reserved.set(AArch64::VG);
475
476 if (MF.getSubtarget<AArch64Subtarget>().hasSME2()) {
477 for (MCSubRegIterator SubReg(AArch64::ZT0, this, /*self=*/true);
478 SubReg.isValid(); ++SubReg)
479 Reserved.set(*SubReg);
480 }
481
482 markSuperRegs(Reserved, AArch64::FPCR);
483 markSuperRegs(Reserved, AArch64::FPMR);
484 markSuperRegs(Reserved, AArch64::FPSR);
485
487 markSuperRegs(Reserved, AArch64::X27);
488 markSuperRegs(Reserved, AArch64::X28);
489 markSuperRegs(Reserved, AArch64::W27);
490 markSuperRegs(Reserved, AArch64::W28);
491 }
492
493 assert(checkAllSuperRegsMarked(Reserved));
494
495 // Add _HI registers after checkAllSuperRegsMarked as this check otherwise
496 // becomes considerably more expensive.
497 Reserved.set(AArch64::WSP_HI);
498 Reserved.set(AArch64::WZR_HI);
499 static_assert(AArch64::W30_HI - AArch64::W0_HI == 30,
500 "Unexpected order of registers");
501 Reserved.set(AArch64::W0_HI, AArch64::W30_HI + 1);
502 static_assert(AArch64::B31_HI - AArch64::B0_HI == 31,
503 "Unexpected order of registers");
504 Reserved.set(AArch64::B0_HI, AArch64::B31_HI + 1);
505 static_assert(AArch64::H31_HI - AArch64::H0_HI == 31,
506 "Unexpected order of registers");
507 Reserved.set(AArch64::H0_HI, AArch64::H31_HI + 1);
508 static_assert(AArch64::S31_HI - AArch64::S0_HI == 31,
509 "Unexpected order of registers");
510 Reserved.set(AArch64::S0_HI, AArch64::S31_HI + 1);
511 static_assert(AArch64::D31_HI - AArch64::D0_HI == 31,
512 "Unexpected order of registers");
513 Reserved.set(AArch64::D0_HI, AArch64::D31_HI + 1);
514 static_assert(AArch64::Q31_HI - AArch64::Q0_HI == 31,
515 "Unexpected order of registers");
516 Reserved.set(AArch64::Q0_HI, AArch64::Q31_HI + 1);
517
518 return Reserved;
519}
520
523 BitVector Reserved(getNumRegs());
524 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
525 // ReserveXRegister is set for registers manually reserved
526 // through +reserve-x#i.
528 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
529 }
530 return Reserved;
531}
532
535 BitVector Reserved(getNumRegs());
536 for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
538 markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
539 }
540
542 // In order to prevent the register allocator from using LR, we need to
543 // mark it as reserved. However we don't want to keep it reserved throughout
544 // the pipeline since it prevents other infrastructure from reasoning about
545 // it's liveness. We use the NoVRegs property instead of IsSSA because
546 // IsSSA is removed before VirtRegRewriter runs.
547 if (!MF.getProperties().hasNoVRegs())
548 // Reserve LR (X30) by marking from its subregister W30 because otherwise
549 // the register allocator could clobber the subregister.
550 markSuperRegs(Reserved, AArch64::W30);
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 for (size_t i = 0; i < 8; ++i) {
580 return true;
581 }
582 return false;
583}
584
586 const MachineFunction &MF) const {
587 const Function &F = MF.getFunction();
588 F.getContext().diagnose(DiagnosticInfoUnsupported{F, ("AArch64 doesn't support"
589 " function calls if any of the argument registers is reserved.")});
590}
591
593 MCRegister PhysReg) const {
594 // SLH uses register X16 as the taint register but it will fallback to a different
595 // method if the user clobbers it. So X16 is not reserved for inline asm but is
596 // for normal codegen.
597 if (MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening) &&
598 MCRegisterInfo::regsOverlap(PhysReg, AArch64::X16))
599 return true;
600
601 // ZA/ZT0 registers are reserved but may be permitted in the clobber list.
602 if (PhysReg == AArch64::ZA || PhysReg == AArch64::ZT0)
603 return true;
604
605 return !isReservedReg(MF, PhysReg);
606}
607
610 if (RC == &AArch64::CCRRegClass)
611 return &AArch64::GPR64RegClass; // Only MSR & MRS copy NZCV.
612 return RC;
613}
614
615MCRegister AArch64RegisterInfo::getBaseRegister() const { return AArch64::X19; }
616
618 const MachineFrameInfo &MFI = MF.getFrameInfo();
619
620 // In the presence of variable sized objects or funclets, if the fixed stack
621 // size is large enough that referencing from the FP won't result in things
622 // being in range relatively often, we can use a base pointer to allow access
623 // from the other direction like the SP normally works.
624 //
625 // Furthermore, if both variable sized objects are present, and the
626 // stack needs to be dynamically re-aligned, the base pointer is the only
627 // reliable way to reference the locals.
628 if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) {
629 if (hasStackRealignment(MF))
630 return true;
631
632 auto &ST = MF.getSubtarget<AArch64Subtarget>();
634 if (ST.hasSVE() || ST.isStreaming()) {
635 // Frames that have variable sized objects and scalable SVE objects,
636 // should always use a basepointer.
637 if (!AFI->hasCalculatedStackSizeSVE() || AFI->hasSVEStackSize())
638 return true;
639 }
640
641 // Frames with hazard padding can have a large offset between the frame
642 // pointer and GPR locals, which includes the emergency spill slot. If the
643 // emergency spill slot is not within range of the load/store instructions
644 // (which have a signed 9-bit range), we will fail to compile if it is used.
645 // Since hasBasePointer() is called before we know if we have hazard padding
646 // or an emergency spill slot we need to enable the basepointer
647 // conservatively.
648 if (ST.getStreamingHazardSize() &&
649 !AFI->getSMEFnAttrs().hasNonStreamingInterfaceAndBody()) {
650 return true;
651 }
652
653 // Conservatively estimate whether the negative offset from the frame
654 // pointer will be sufficient to reach. If a function has a smallish
655 // frame, it's less likely to have lots of spills and callee saved
656 // space, so it's all more likely to be within range of the frame pointer.
657 // If it's wrong, we'll materialize the constant and still get to the
658 // object; it's just suboptimal. Negative offsets use the unscaled
659 // load/store instructions, which have a 9-bit signed immediate.
660 return MFI.getLocalFrameSize() >= 256;
661 }
662
663 return false;
664}
665
667 MCRegister Reg) const {
670 bool IsVarArg = STI.isCallingConvWin64(MF.getFunction().getCallingConv(),
671 MF.getFunction().isVarArg());
672
673 auto HasReg = [](ArrayRef<MCRegister> RegList, MCRegister Reg) {
674 return llvm::is_contained(RegList, Reg);
675 };
676
677 switch (CC) {
678 default:
679 report_fatal_error("Unsupported calling convention.");
680 case CallingConv::GHC:
681 return HasReg(CC_AArch64_GHC_ArgRegs, Reg);
683 if (!MF.getFunction().isVarArg())
684 return HasReg(CC_AArch64_Preserve_None_ArgRegs, Reg);
685 [[fallthrough]];
686 case CallingConv::C:
694 if (STI.isTargetWindows()) {
695 if (IsVarArg)
696 return HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
697 switch (CC) {
698 default:
699 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
702 return HasReg(CC_AArch64_Win64PCS_Swift_ArgRegs, Reg) ||
703 HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
704 }
705 }
706 if (!STI.isTargetDarwin()) {
707 switch (CC) {
708 default:
709 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
712 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg) ||
713 HasReg(CC_AArch64_AAPCS_Swift_ArgRegs, Reg);
714 }
715 }
716 if (!IsVarArg) {
717 switch (CC) {
718 default:
719 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg);
722 return HasReg(CC_AArch64_DarwinPCS_ArgRegs, Reg) ||
723 HasReg(CC_AArch64_DarwinPCS_Swift_ArgRegs, Reg);
724 }
725 }
726 if (STI.isTargetILP32())
727 return HasReg(CC_AArch64_DarwinPCS_ILP32_VarArg_ArgRegs, Reg);
728 return HasReg(CC_AArch64_DarwinPCS_VarArg_ArgRegs, Reg);
730 if (IsVarArg)
731 HasReg(CC_AArch64_Win64_VarArg_ArgRegs, Reg);
732 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
734 return HasReg(CC_AArch64_Win64_CFGuard_Check_ArgRegs, Reg);
740 if (STI.isTargetWindows())
741 return HasReg(CC_AArch64_Win64PCS_ArgRegs, Reg);
742 return HasReg(CC_AArch64_AAPCS_ArgRegs, Reg);
743 }
744}
745
748 const AArch64FrameLowering *TFI = getFrameLowering(MF);
749 return TFI->hasFP(MF) ? AArch64::FP : AArch64::SP;
750}
751
753 const MachineFunction &MF) const {
754 return true;
755}
756
758 const MachineFunction &MF) const {
759 return true;
760}
761
762bool
764 // This function indicates whether the emergency spillslot should be placed
765 // close to the beginning of the stackframe (closer to FP) or the end
766 // (closer to SP).
767 //
768 // The beginning works most reliably if we have a frame pointer.
769 // In the presence of any non-constant space between FP and locals,
770 // (e.g. in case of stack realignment or a scalable SVE area), it is
771 // better to use SP or BP.
772 const AArch64FrameLowering &TFI = *getFrameLowering(MF);
774 assert((!MF.getSubtarget<AArch64Subtarget>().hasSVE() ||
776 "Expected SVE area to be calculated by this point");
777 return TFI.hasFP(MF) && !hasStackRealignment(MF) && !AFI->hasSVEStackSize() &&
779}
780
782 const MachineFunction &MF) const {
783 return true;
784}
785
786bool
788 const MachineFrameInfo &MFI = MF.getFrameInfo();
789 if (MF.disableFramePointerElim() && MFI.adjustsStack())
790 return true;
791 return MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
792}
793
794/// needsFrameBaseReg - Returns true if the instruction's frame index
795/// reference would be better served by a base register other than FP
796/// or SP. Used by LocalStackFrameAllocation to determine which frame index
797/// references it should create new base registers for.
799 int64_t Offset) const {
800 for (unsigned i = 0; !MI->getOperand(i).isFI(); ++i)
801 assert(i < MI->getNumOperands() &&
802 "Instr doesn't have FrameIndex operand!");
803
804 // It's the load/store FI references that cause issues, as it can be difficult
805 // to materialize the offset if it won't fit in the literal field. Estimate
806 // based on the size of the local frame and some conservative assumptions
807 // about the rest of the stack frame (note, this is pre-regalloc, so
808 // we don't know everything for certain yet) whether this offset is likely
809 // to be out of range of the immediate. Return true if so.
810
811 // We only generate virtual base registers for loads and stores, so
812 // return false for everything else.
813 if (!MI->mayLoad() && !MI->mayStore())
814 return false;
815
816 // Without a virtual base register, if the function has variable sized
817 // objects, all fixed-size local references will be via the frame pointer,
818 // Approximate the offset and see if it's legal for the instruction.
819 // Note that the incoming offset is based on the SP value at function entry,
820 // so it'll be negative.
821 MachineFunction &MF = *MI->getParent()->getParent();
822 const AArch64FrameLowering *TFI = getFrameLowering(MF);
823 MachineFrameInfo &MFI = MF.getFrameInfo();
824
825 // Estimate an offset from the frame pointer.
826 // Conservatively assume all GPR callee-saved registers get pushed.
827 // FP, LR, X19-X28, D8-D15. 64-bits each.
828 int64_t FPOffset = Offset - 16 * 20;
829 // Estimate an offset from the stack pointer.
830 // The incoming offset is relating to the SP at the start of the function,
831 // but when we access the local it'll be relative to the SP after local
832 // allocation, so adjust our SP-relative offset by that allocation size.
833 Offset += MFI.getLocalFrameSize();
834 // Assume that we'll have at least some spill slots allocated.
835 // FIXME: This is a total SWAG number. We should run some statistics
836 // and pick a real one.
837 Offset += 128; // 128 bytes of spill slots
838
839 // If there is a frame pointer, try using it.
840 // The FP is only available if there is no dynamic realignment. We
841 // don't know for sure yet whether we'll need that, so we guess based
842 // on whether there are any local variables that would trigger it.
843 if (TFI->hasFP(MF) && isFrameOffsetLegal(MI, AArch64::FP, FPOffset))
844 return false;
845
846 // If we can reference via the stack pointer or base pointer, try that.
847 // FIXME: This (and the code that resolves the references) can be improved
848 // to only disallow SP relative references in the live range of
849 // the VLA(s). In practice, it's unclear how much difference that
850 // would make, but it may be worth doing.
851 if (isFrameOffsetLegal(MI, AArch64::SP, Offset))
852 return false;
853
854 // If even offset 0 is illegal, we don't want a virtual base register.
855 if (!isFrameOffsetLegal(MI, AArch64::SP, 0))
856 return false;
857
858 // The offset likely isn't legal; we want to allocate a virtual base register.
859 return true;
860}
861
863 Register BaseReg,
864 int64_t Offset) const {
865 assert(MI && "Unable to get the legal offset for nil instruction.");
868}
869
870/// Insert defining instruction(s) for BaseReg to be a pointer to FrameIdx
871/// at the beginning of the basic block.
874 int FrameIdx,
875 int64_t Offset) const {
876 MachineBasicBlock::iterator Ins = MBB->begin();
877 DebugLoc DL; // Defaults to "unknown"
878 if (Ins != MBB->end())
879 DL = Ins->getDebugLoc();
880 const MachineFunction &MF = *MBB->getParent();
881 const AArch64InstrInfo *TII =
882 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
883 const MCInstrDesc &MCID = TII->get(AArch64::ADDXri);
884 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
885 Register BaseReg = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
886 MRI.constrainRegClass(BaseReg, TII->getRegClass(MCID, 0));
887 unsigned Shifter = AArch64_AM::getShifterImm(AArch64_AM::LSL, 0);
888
889 BuildMI(*MBB, Ins, DL, MCID, BaseReg)
890 .addFrameIndex(FrameIdx)
891 .addImm(Offset)
892 .addImm(Shifter);
893
894 return BaseReg;
895}
896
898 int64_t Offset) const {
899 // ARM doesn't need the general 64-bit offsets
901
902 unsigned i = 0;
903 while (!MI.getOperand(i).isFI()) {
904 ++i;
905 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
906 }
907
908 const MachineFunction *MF = MI.getParent()->getParent();
909 const AArch64InstrInfo *TII =
910 MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
911 bool Done = rewriteAArch64FrameIndex(MI, i, BaseReg, Off, TII);
912 assert(Done && "Unable to resolve frame index!");
913 (void)Done;
914}
915
916// Create a scratch register for the frame index elimination in an instruction.
917// This function has special handling of stack tagging loop pseudos, in which
918// case it can also change the instruction opcode.
919static Register
921 const AArch64InstrInfo *TII) {
922 // ST*Gloop have a reserved scratch register in operand 1. Use it, and also
923 // replace the instruction with the writeback variant because it will now
924 // satisfy the operand constraints for it.
925 Register ScratchReg;
926 if (MI.getOpcode() == AArch64::STGloop ||
927 MI.getOpcode() == AArch64::STZGloop) {
928 assert(FIOperandNum == 3 &&
929 "Wrong frame index operand for STGloop/STZGloop");
930 unsigned Op = MI.getOpcode() == AArch64::STGloop ? AArch64::STGloop_wback
931 : AArch64::STZGloop_wback;
932 ScratchReg = MI.getOperand(1).getReg();
933 MI.getOperand(3).ChangeToRegister(ScratchReg, false, false, true);
934 MI.setDesc(TII->get(Op));
935 MI.tieOperands(1, 3);
936 } else {
937 ScratchReg =
938 MI.getMF()->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
939 MI.getOperand(FIOperandNum)
940 .ChangeToRegister(ScratchReg, false, false, true);
941 }
942 return ScratchReg;
943}
944
947 // The smallest scalable element supported by scaled SVE addressing
948 // modes are predicates, which are 2 scalable bytes in size. So the scalable
949 // byte offset must always be a multiple of 2.
950 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
951
952 // Add fixed-sized offset using existing DIExpression interface.
954
955 unsigned VG = getDwarfRegNum(AArch64::VG, true);
956 int64_t VGSized = Offset.getScalable() / 2;
957 if (VGSized > 0) {
958 Ops.push_back(dwarf::DW_OP_constu);
959 Ops.push_back(VGSized);
960 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
961 Ops.push_back(dwarf::DW_OP_mul);
962 Ops.push_back(dwarf::DW_OP_plus);
963 } else if (VGSized < 0) {
964 Ops.push_back(dwarf::DW_OP_constu);
965 Ops.push_back(-VGSized);
966 Ops.append({dwarf::DW_OP_bregx, VG, 0ULL});
967 Ops.push_back(dwarf::DW_OP_mul);
968 Ops.push_back(dwarf::DW_OP_minus);
969 }
970}
971
973 int SPAdj, unsigned FIOperandNum,
974 RegScavenger *RS) const {
975 assert(SPAdj == 0 && "Unexpected");
976
977 MachineInstr &MI = *II;
978 MachineBasicBlock &MBB = *MI.getParent();
979 MachineFunction &MF = *MBB.getParent();
980 const MachineFrameInfo &MFI = MF.getFrameInfo();
981 const AArch64InstrInfo *TII =
982 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
983 const AArch64FrameLowering *TFI = getFrameLowering(MF);
984 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
985 bool Tagged =
986 MI.getOperand(FIOperandNum).getTargetFlags() & AArch64II::MO_TAGGED;
987 Register FrameReg;
988
989 // Special handling of dbg_value, stackmap patchpoint statepoint instructions.
990 if (MI.getOpcode() == TargetOpcode::STACKMAP ||
991 MI.getOpcode() == TargetOpcode::PATCHPOINT ||
992 MI.getOpcode() == TargetOpcode::STATEPOINT) {
994 TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg,
995 /*PreferFP=*/true,
996 /*ForSimm=*/false);
997 Offset += StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
998 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
999 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
1000 return false;
1001 }
1002
1003 if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) {
1004 MachineOperand &FI = MI.getOperand(FIOperandNum);
1005 StackOffset Offset = TFI->getNonLocalFrameIndexReference(MF, FrameIndex);
1006 assert(!Offset.getScalable() &&
1007 "Frame offsets with a scalable component are not supported");
1008 FI.ChangeToImmediate(Offset.getFixed());
1009 return false;
1010 }
1011
1013 if (MI.getOpcode() == AArch64::TAGPstack) {
1014 // TAGPstack must use the virtual frame register in its 3rd operand.
1016 FrameReg = MI.getOperand(3).getReg();
1017 Offset = StackOffset::getFixed(MFI.getObjectOffset(FrameIndex) +
1019 } else if (Tagged) {
1021 MFI.getObjectOffset(FrameIndex) + (int64_t)MFI.getStackSize());
1022 if (MFI.hasVarSizedObjects() ||
1023 isAArch64FrameOffsetLegal(MI, SPOffset, nullptr, nullptr, nullptr) !=
1025 // Can't update to SP + offset in place. Precalculate the tagged pointer
1026 // in a scratch register.
1028 MF, FrameIndex, FrameReg, /*PreferFP=*/false, /*ForSimm=*/true);
1029 Register ScratchReg =
1030 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
1031 emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset,
1032 TII);
1033 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(AArch64::LDG), ScratchReg)
1034 .addReg(ScratchReg)
1035 .addReg(ScratchReg)
1036 .addImm(0);
1037 MI.getOperand(FIOperandNum)
1038 .ChangeToRegister(ScratchReg, false, false, true);
1039 return false;
1040 }
1041 FrameReg = AArch64::SP;
1042 Offset = StackOffset::getFixed(MFI.getObjectOffset(FrameIndex) +
1043 (int64_t)MFI.getStackSize());
1044 } else {
1046 MF, FrameIndex, FrameReg, /*PreferFP=*/false, /*ForSimm=*/true);
1047 }
1048
1049 // Modify MI as necessary to handle as much of 'Offset' as possible
1050 if (rewriteAArch64FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
1051 return true;
1052
1053 assert((!RS || !RS->isScavengingFrameIndex(FrameIndex)) &&
1054 "Emergency spill slot is out of reach");
1055
1056 // If we get here, the immediate doesn't fit into the instruction. We folded
1057 // as much as possible above. Handle the rest, providing a register that is
1058 // SP+LargeImm.
1059 Register ScratchReg =
1061 emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset, TII);
1062 return false;
1063}
1064
1066 MachineFunction &MF) const {
1067 const AArch64FrameLowering *TFI = getFrameLowering(MF);
1068
1069 switch (RC->getID()) {
1070 default:
1071 return 0;
1072 case AArch64::GPR32RegClassID:
1073 case AArch64::GPR32spRegClassID:
1074 case AArch64::GPR32allRegClassID:
1075 case AArch64::GPR64spRegClassID:
1076 case AArch64::GPR64allRegClassID:
1077 case AArch64::GPR64RegClassID:
1078 case AArch64::GPR32commonRegClassID:
1079 case AArch64::GPR64commonRegClassID:
1080 return 32 - 1 // XZR/SP
1081 - (TFI->hasFP(MF) || TT.isOSDarwin()) // FP
1082 - MF.getSubtarget<AArch64Subtarget>().getNumXRegisterReserved()
1083 - hasBasePointer(MF); // X19
1084 case AArch64::FPR8RegClassID:
1085 case AArch64::FPR16RegClassID:
1086 case AArch64::FPR32RegClassID:
1087 case AArch64::FPR64RegClassID:
1088 case AArch64::FPR128RegClassID:
1089 return 32;
1090
1091 case AArch64::MatrixIndexGPR32_8_11RegClassID:
1092 case AArch64::MatrixIndexGPR32_12_15RegClassID:
1093 return 4;
1094
1095 case AArch64::DDRegClassID:
1096 case AArch64::DDDRegClassID:
1097 case AArch64::DDDDRegClassID:
1098 case AArch64::QQRegClassID:
1099 case AArch64::QQQRegClassID:
1100 case AArch64::QQQQRegClassID:
1101 return 32;
1102
1103 case AArch64::FPR128_loRegClassID:
1104 case AArch64::FPR64_loRegClassID:
1105 case AArch64::FPR16_loRegClassID:
1106 return 16;
1107 case AArch64::FPR128_0to7RegClassID:
1108 return 8;
1109 }
1110}
1111
1113 Register VirtReg, ArrayRef<MCPhysReg> Order,
1114 SmallVectorImpl<MCPhysReg> &Hints, const VirtRegMap *VRM,
1115 const MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
1116 const AArch64Subtarget &ST, const LiveRegMatrix *Matrix) {
1117 const TargetRegisterClass *RegRC = MRI.getRegClass(VirtReg);
1118 if (!ST.useDistinctPredicateDstReg() ||
1119 !AArch64::PPRRegClass.hasSubClassEq(RegRC) || !MRI.hasOneDef(VirtReg) ||
1120 Order.size() < 2)
1121 return false;
1122
1123 const MachineInstr *DefInst = MRI.getOneDef(VirtReg)->getParent();
1124 if ((TII.get(DefInst->getOpcode()).TSFlags &
1126 return false;
1127
1128 Register Op1Reg = DefInst->getOperand(1).getReg();
1129 if (Op1Reg.isVirtual())
1130 Op1Reg = VRM->getPhys(Op1Reg);
1131
1132 // If no register is allocated for the general-predicate, it's not yet
1133 // possible to choose a distinct register.
1134 if (!Op1Reg.isValid())
1135 return false;
1136
1137 // Move Op1Reg as the least preferred register.
1138 //
1139 // This might result in callee-save spills when the function takes/returns
1140 // arguments in SVE registers (i.e. needs to preserve p4-p15) and can't reuse
1141 // p0-p3. That's why we limit it to non-callee saved registers or to
1142 // callee-saved registers that have already been allocated for other uses in
1143 // the function.
1144 DenseSet<unsigned> CSRs;
1145 for (unsigned I = 0;; ++I) {
1146 Register R = MRI.getCalleeSavedRegs()[I];
1147 if (!R.isValid())
1148 break;
1149 if (AArch64::PPRRegClass.contains(R))
1150 CSRs.insert(R);
1151 }
1152
1153 Hints.append(Order.begin(), Order.end());
1154 auto CanUseReg = [&](Register R) {
1155 return !CSRs.contains(R) || !MRI.def_empty(R) || Matrix->isPhysRegUsed(R);
1156 };
1157 llvm::stable_sort(Hints, [&](Register A, Register B) {
1158 bool PrefA = (A != Op1Reg) && CanUseReg(A);
1159 bool PrefB = (B != Op1Reg) && CanUseReg(B);
1160 return PrefA && !PrefB;
1161 });
1162 return true;
1163}
1164
1165// We add regalloc hints for different cases:
1166// * Choosing a better destination operand for predicated SVE instructions
1167// where the inactive lanes are undef, by choosing a register that is not
1168// unique to the other operands of the instruction.
1169//
1170// * Improve register allocation for SME multi-vector instructions where we can
1171// benefit from the strided- and contiguous register multi-vector tuples.
1172//
1173// Here COPY_INTO_TRANSPOSED_TUPLE nodes are created to improve register
1174// allocation where a consecutive multi-vector tuple is constructed from the
1175// same indices of multiple strided loads. This may still result in
1176// unnecessary copies between the loads and the tuple. Here we try to return a
1177// hint to assign the contiguous ZPRMulReg starting at the same register as
1178// the first operand of the pseudo, which should be a subregister of the first
1179// strided load.
1180//
1181// For example, if the first strided load has been assigned $z16_z20_z24_z28
1182// and the operands of the pseudo are each accessing subregister zsub2, we
1183// should look through through Order to find a contiguous register which
1184// begins with $z24 (i.e. $z24_z25_z26_z27).
1186 Register VirtReg, ArrayRef<MCPhysReg> Order,
1188 const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
1189 auto &ST = MF.getSubtarget<AArch64Subtarget>();
1190 const AArch64InstrInfo *TII =
1191 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
1192 const MachineRegisterInfo &MRI = MF.getRegInfo();
1193
1194 bool ConsiderOnlyHints =
1195 TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM);
1196
1197 // For predicated SVE instructions where the inactive lanes are undef,
1198 // pick a destination register that is not unique to avoid introducing
1199 // a movprfx.
1200 const TargetRegisterClass *RegRC = MRI.getRegClass(VirtReg);
1201 if (AArch64::ZPRRegClass.hasSubClassEq(RegRC)) {
1202 for (const MachineOperand &DefOp : MRI.def_operands(VirtReg)) {
1203 const MachineInstr &Def = *DefOp.getParent();
1204 if (DefOp.isImplicit() ||
1205 (TII->get(Def.getOpcode()).TSFlags & AArch64::FalseLanesMask) !=
1207 continue;
1208
1209 unsigned InstFlags =
1210 TII->get(AArch64::getSVEPseudoMap(Def.getOpcode())).TSFlags;
1211
1212 for (MCPhysReg R : Order) {
1213 auto AddHintIfSuitable = [&](MCPhysReg R,
1214 const MachineOperand &MO) -> bool {
1215 // R is a suitable register hint if R can reuse one of the other
1216 // source operands.
1217 MCPhysReg PhysReg = VRM->getPhys(MO.getReg());
1218 if (PhysReg && MO.getSubReg())
1219 PhysReg = getSubReg(PhysReg, MO.getSubReg());
1220 if (PhysReg != R)
1221 return false;
1222 Hints.push_back(R);
1223 return true;
1224 };
1225
1226 switch (InstFlags & AArch64::DestructiveInstTypeMask) {
1227 default:
1228 break;
1230 AddHintIfSuitable(R, Def.getOperand(2)) ||
1231 AddHintIfSuitable(R, Def.getOperand(3)) ||
1232 AddHintIfSuitable(R, Def.getOperand(4));
1233 break;
1236 AddHintIfSuitable(R, Def.getOperand(2)) ||
1237 AddHintIfSuitable(R, Def.getOperand(3));
1238 break;
1241 AddHintIfSuitable(R, Def.getOperand(2));
1242 break;
1244 AddHintIfSuitable(R, Def.getOperand(3));
1245 break;
1248 AddHintIfSuitable(R, Def.getOperand(1));
1249 break;
1250 }
1251 }
1252 }
1253
1254 if (Hints.size())
1255 return ConsiderOnlyHints;
1256 }
1257
1258 if (HandleDestructivePredicateHint(VirtReg, Order, Hints, VRM, MRI, *TII, ST,
1259 Matrix))
1260 return ConsiderOnlyHints;
1261
1262 if (!ST.hasSME() || !ST.isStreaming())
1263 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
1264 VRM);
1265
1266 // The SVE calling convention preserves registers Z8-Z23. As a result, there
1267 // are no ZPR2Strided or ZPR4Strided registers that do not overlap with the
1268 // callee-saved registers and so by default these will be pushed to the back
1269 // of the allocation order for the ZPRStridedOrContiguous classes.
1270 // If any of the instructions which define VirtReg are used by the
1271 // COPY_INTO_TRANSPOSED_TUPLE pseudos, we want to favour reducing copy
1272 // instructions over reducing the number of clobbered callee-save registers,
1273 // so we add the strided registers as a hint.
1274 unsigned RegID = RegRC->getID();
1275 if (RegID == AArch64::ZPR2StridedOrContiguousRegClassID ||
1276 RegID == AArch64::ZPR4StridedOrContiguousRegClassID) {
1277
1278 // Look through uses of the register for COPY_INTO_TRANSPOSED_TUPLE.
1279 for (const MachineInstr &Use : MRI.use_nodbg_instructions(VirtReg)) {
1280 if (Use.getOpcode() != AArch64::COPY_INTO_TRANSPOSED_TUPLE)
1281 continue;
1282
1283 const MachineOperand &Src = Use.getOperand(1);
1284 const MachineOperand &Dst = Use.getOperand(0);
1285
1286 if (!Src.getSubReg() || !Dst.getSubReg())
1287 continue;
1288
1289 const TargetRegisterClass *StridedRC;
1290 switch (RegID) {
1291 case AArch64::ZPR2StridedOrContiguousRegClassID:
1292 StridedRC = &AArch64::ZPR2StridedRegClass;
1293 break;
1294 case AArch64::ZPR4StridedOrContiguousRegClassID:
1295 StridedRC = &AArch64::ZPR4StridedRegClass;
1296 break;
1297 default:
1298 llvm_unreachable("Unexpected RegID");
1299 }
1300
1301 SmallVector<MCPhysReg, 4> StridedOrder;
1302 for (MCPhysReg Reg : Order)
1303 if (StridedRC->contains(Reg))
1304 StridedOrder.push_back(Reg);
1305
1306 unsigned TupleSize = Use.getOperand(2).getImm();
1307 unsigned TupIdx = Dst.getSubReg() - AArch64::zsub0;
1308
1309 unsigned TupleID = MRI.getRegClass(Dst.getReg())->getID();
1310 bool IsMulZPR = TupleID == AArch64::ZPR2Mul2RegClassID ||
1311 TupleID == AArch64::ZPR4Mul4RegClassID;
1312
1313 iterator_range Copies = MRI.def_instructions(Dst.getReg());
1314 MachineRegisterInfo::def_instr_iterator CopyWithAssignedSrc =
1315 llvm::find_if(Copies, [&](const MachineInstr &Def) {
1316 auto &Src = Def.getOperand(1);
1317 return Def.getOpcode() == Use.getOpcode() &&
1318 VRM->hasPhys(Src.getReg());
1319 });
1320
1321 // Example:
1322 //
1323 // When trying to find a suitable register allocation for VirtReg %v2 in:
1324 //
1325 // %v0:zpr2stridedorcontiguous = ld1 p0/z, [...]
1326 // %v1:zpr2stridedorcontiguous = ld1 p0/z, [...]
1327 // %v2:zpr2stridedorcontiguous = ld1 p0/z, [...]
1328 // %v3:zpr2stridedorcontiguous = ld1 p0/z, [...]
1329 // %v4.zsub0:zpr4mul4 = COPY_INTO_TRANSPOSED_TUPLE %v0:0
1330 // %v4.zsub1:zpr4mul4 = COPY_INTO_TRANSPOSED_TUPLE %v1:0
1331 // %v4.zsub2:zpr4mul4 = COPY_INTO_TRANSPOSED_TUPLE %v2:0
1332 // %v4.zsub3:zpr4mul4 = COPY_INTO_TRANSPOSED_TUPLE %v3:0
1333 //
1334 // One such suitable allocation would be:
1335 //
1336 // { z0, z8 } = ld1 p0/z, [...]
1337 // { z1, z9 } = ld1 p0/z, [...]
1338 // { z2, z10 } = ld1 p0/z, [...]
1339 // { z3, z11 } = ld1 p0/z, [...]
1340 // z0 = COPY_INTO_TRANSPOSED_TUPLE {z0, z8}:0
1341 // z1 = COPY_INTO_TRANSPOSED_TUPLE {z1, z9}:0
1342 // z2 = COPY_INTO_TRANSPOSED_TUPLE {z2, z10}:0
1343 // z3 = COPY_INTO_TRANSPOSED_TUPLE {z3, z11}:0
1344 //
1345 // Below we distinguish two cases when trying to find a register:
1346 // * None of the sources of the copies have been assigned a register yet.
1347 // In this case the code must ensure that there are at least TupleSize
1348 // free consecutive registers. If IsMulZPR is true, then the first of
1349 // registers must also be a multiple of TupleSize, e.g.
1350 // { z0, z1, z2, z3 } is valid but { z1, z2, z3, z5 } is not.
1351 // * One or more copies already have registers assigned to their sources,
1352 // which means only checking that a consecutive range of free tuple
1353 // registers exists which includes the assigned register.
1354 // e.g. in the example above, if { z0, z8 } is already allocated for
1355 // %v0, we just need to ensure that { z1, z9 }, { z2, z10 } and
1356 // { z3, z11 } are also free. If so, we add { z2, z10 }.
1357
1358 if (CopyWithAssignedSrc == Copies.end()) {
1359 // There are no registers already assigned to any of the pseudo
1360 // operands. Look for a valid starting register for the group.
1361 for (unsigned I = 0; I < StridedOrder.size(); ++I) {
1362 MCPhysReg Reg = StridedOrder[I];
1363
1364 // If the COPY_INTO_TRANSPOSED_TUPLE nodes use the ZPRMul classes, the
1365 // starting register of the first load should be a multiple of 2 or 4.
1366 unsigned SubRegIdx = Src.getSubReg();
1367 if (IsMulZPR &&
1368 (getSubReg(Reg, SubRegIdx) - AArch64::Z0) % TupleSize != TupIdx)
1369 continue;
1370
1371 // In the example above, if VirtReg is the third operand of the
1372 // tuple (%v2) and Reg == Z2_Z10, then we need to make sure that
1373 // Z0_Z8, Z1_Z9 and Z3_Z11 are also available.
1374 auto IsFreeConsecutiveReg = [&](unsigned I) {
1375 unsigned R = Reg - TupIdx + I;
1376 return StridedRC->contains(R) &&
1377 (I == 0 ||
1378 ((getSubReg(R, AArch64::zsub0) - AArch64::Z0) ==
1379 (getSubReg(R - 1, AArch64::zsub0) - AArch64::Z0) + 1)) &&
1380 !Matrix->isPhysRegUsed(R);
1381 };
1382 if (all_of(seq(0U, TupleSize), IsFreeConsecutiveReg))
1383 Hints.push_back(Reg);
1384 }
1385 } else {
1386 // At least copy already has a physical register assigned to its source.
1387 // Find the starting sub-register of this and use it to work out the
1388 // correct strided register to suggest based on the current op index.
1389 MachineOperand &AssignedSrc = CopyWithAssignedSrc->getOperand(1);
1390 MachineOperand &AssignedDst = CopyWithAssignedSrc->getOperand(0);
1391
1392 if (!AssignedSrc.getSubReg() || !AssignedDst.getSubReg())
1393 continue;
1394
1395 unsigned AssignedTupIdx = AssignedDst.getSubReg() - AArch64::zsub0;
1396 MCPhysReg TargetStartReg =
1397 getSubReg(VRM->getPhys(AssignedSrc.getReg()), AArch64::zsub0) +
1398 (TupIdx - AssignedTupIdx);
1399
1400 for (unsigned I = 0; I < StridedOrder.size(); ++I)
1401 if (getSubReg(StridedOrder[I], AArch64::zsub0) == TargetStartReg)
1402 Hints.push_back(StridedOrder[I]);
1403 }
1404
1405 if (!Hints.empty())
1406 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints,
1407 MF, VRM);
1408 }
1409 }
1410
1411 for (auto &Def : MRI.def_instructions(VirtReg)) {
1412 if (Def.getOpcode() != AArch64::COPY_INTO_TRANSPOSED_TUPLE)
1413 continue;
1414
1415 MachineOperand &Src = Def.getOperand(1);
1416 MachineOperand &Dst = Def.getOperand(0);
1417
1418 if (!Src.getSubReg() || !Dst.getSubReg())
1419 continue;
1420
1421 // FIXME: This is fragile. If we allocate a register to the Dst before Src,
1422 // our hints are won't have any effect... This is currently mitigated by
1423 // by trying to schedule copies immediately before their uses. This gives
1424 // them a short live range (so they're low priority to allocate).
1425 if (!VRM->hasPhys(Src.getReg()))
1426 continue;
1427
1428 // Find the ZPR register mapped to the source of the copy.
1429 MCPhysReg SrcZPR = getSubReg(VRM->getPhys(Src.getReg()), Src.getSubReg());
1430
1431 // Try to pick a tuple register for Dst with Src as a member.
1432 for (MCPhysReg R : Order) {
1433 if (getSubReg(R, Dst.getSubReg()) == SrcZPR)
1434 Hints.push_back(R);
1435 }
1436 }
1437
1438 return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
1439 VRM);
1440}
1441
1443 const MachineFunction &MF) const {
1444 const auto &MFI = MF.getFrameInfo();
1445 if (!MF.hasEHFunclets() && !MFI.hasVarSizedObjects())
1446 return AArch64::SP;
1447 else if (hasStackRealignment(MF))
1448 return getBaseRegister();
1449 return getFrameRegister(MF);
1450}
1451
1452/// SrcRC and DstRC will be morphed into NewRC if this returns true
1454 MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg,
1455 const TargetRegisterClass *DstRC, unsigned DstSubReg,
1456 const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
1457 MachineFunction &MF = *MI->getMF();
1458 MachineRegisterInfo &MRI = MF.getRegInfo();
1459
1460 if (MI->isSubregToReg() && MRI.subRegLivenessEnabled() &&
1462 return false;
1463
1464 if (MI->isCopy() &&
1465 ((DstRC->getID() == AArch64::GPR64RegClassID) ||
1466 (DstRC->getID() == AArch64::GPR64commonRegClassID)) &&
1467 MI->getOperand(0).getSubReg() && MI->getOperand(1).getSubReg())
1468 // Do not coalesce in the case of a 32-bit subregister copy
1469 // which implements a 32 to 64 bit zero extension
1470 // which relies on the upper 32 bits being zeroed.
1471 return false;
1472
1473 auto IsCoalescerBarrier = [](const MachineInstr &MI) {
1474 switch (MI.getOpcode()) {
1475 case AArch64::COALESCER_BARRIER_FPR16:
1476 case AArch64::COALESCER_BARRIER_FPR32:
1477 case AArch64::COALESCER_BARRIER_FPR64:
1478 case AArch64::COALESCER_BARRIER_FPR128:
1479 return true;
1480 default:
1481 return false;
1482 }
1483 };
1484
1485 // For calls that temporarily have to toggle streaming mode as part of the
1486 // call-sequence, we need to be more careful when coalescing copy instructions
1487 // so that we don't end up coalescing the NEON/FP result or argument register
1488 // with a whole Z-register, such that after coalescing the register allocator
1489 // will try to spill/reload the entire Z register.
1490 //
1491 // We do this by checking if the node has any defs/uses that are
1492 // COALESCER_BARRIER pseudos. These are 'nops' in practice, but they exist to
1493 // instruct the coalescer to avoid coalescing the copy.
1494 if (MI->isCopy() && SubReg != DstSubReg &&
1495 (AArch64::ZPRRegClass.hasSubClassEq(DstRC) ||
1496 AArch64::ZPRRegClass.hasSubClassEq(SrcRC))) {
1497 unsigned SrcReg = MI->getOperand(1).getReg();
1498 if (any_of(MRI.def_instructions(SrcReg), IsCoalescerBarrier))
1499 return false;
1500 unsigned DstReg = MI->getOperand(0).getReg();
1501 if (any_of(MRI.use_nodbg_instructions(DstReg), IsCoalescerBarrier))
1502 return false;
1503 }
1504
1505 return true;
1506}
1507
1509 MCRegister R) const {
1510 return R == AArch64::VG;
1511}
1512
1514 return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
1515 (LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
1516}
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)
static bool HandleDestructivePredicateHint(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallVectorImpl< MCPhysReg > &Hints, const VirtRegMap *VRM, const MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const AArch64Subtarget &ST, const LiveRegMatrix *Matrix)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition Compiler.h:421
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
uint64_t IntrinsicInst * II
This file declares the machine register scavenger class.
SI Lower i1 Copies
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
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
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 enableSRLTSubregToRegMitigation() const
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
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:126
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
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:273
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:329
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition Function.h:230
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.
unsigned getID() const
getID() - Return the register class ID number.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool regsOverlap(MCRegister RegA, MCRegister RegB) const
Returns true if the two registers are equal or alias each other.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
MCSubRegIterator enumerates all sub-registers of Reg.
bool isValid() const
Returns true if this iterator is not yet at the end.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
int64_t getLocalFrameSize() const
Get the size of the local object blob.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
uint32_t * allocateRegMask()
Allocate and initialize a register mask with NumRegister bits.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static unsigned getRegMaskSize(unsigned NumRegs)
Returns number of elements needed for a regmask array.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< def_instr_iterator > def_instructions(Register Reg) const
MachineOperand * getOneDef(Register Reg) const
Returns the defining operand if there is exactly one operand defining the specified register,...
defusechain_instr_iterator< false, true, false, true > def_instr_iterator
def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the specified register,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
iterator_range< def_iterator > def_operands(Register Reg) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
LLVM_ABI void setCalleeSavedRegs(ArrayRef< MCPhysReg > CSRs)
Sets the updated Callee Saved Registers list.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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.
TargetInstrInfo - Interface to description of machine instruction set.
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:48
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
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
A range adaptor for a pair of iterators.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void initLLVMToCVRegMapping(MCRegisterInfo *MRI)
int32_t getSVEPseudoMap(uint32_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:577
void stable_sort(R &&Range)
Definition STLExtras.h:2132
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:1755
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
@ 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:1762
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:163
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:1788
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
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:1963
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58