1//===- AArch64FrameLowering.cpp - AArch64 Frame Lowering -------*- C++ -*-====//
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 TargetFrameLowering class.
10//
11// On AArch64, stack frames are structured as follows:
12//
13// The stack grows downward.
14//
15// All of the individual frame areas on the frame below are optional, i.e. it's
16// possible to create a function so that the particular area isn't present
17// in the frame.
18//
19// At function entry, the "frame" looks as follows:
20//
21// | | Higher address
22// |-----------------------------------|
23// | |
24// | arguments passed on the stack |
25// | |
26// |-----------------------------------| <- sp
27// | | Lower address
28//
29//
30// After the prologue has run, the frame has the following general structure.
31// Note that this doesn't depict the case where a red-zone is used. Also,
32// technically the last frame area (VLAs) doesn't get created until in the
33// main function body, after the prologue is run. However, it's depicted here
34// for completeness.
35//
36// | | Higher address
37// |-----------------------------------|
38// | |
39// | arguments passed on the stack |
40// | |
41// |-----------------------------------|
42// | |
43// | (Win64 only) varargs from reg |
44// | |
45// |-----------------------------------|
46// | |
47// | (Win64 only) callee-saved SVE reg |
48// | |
49// |-----------------------------------|
50// | |
51// | callee-saved gpr registers | <--.
52// | | | On Darwin platforms these
53// |- - - - - - - - - - - - - - - - - -| | callee saves are swapped,
54// | prev_lr | | (frame record first)
55// | prev_fp | <--'
56// | async context if needed |
57// | (a.k.a. "frame record") |
58// |-----------------------------------| <- fp(=x29)
59// Default SVE stack layout Split SVE objects
60// (aarch64-split-sve-objects=false) (aarch64-split-sve-objects=true)
61// |-----------------------------------| |-----------------------------------|
62// | <hazard padding> | | callee-saved PPR registers |
63// |-----------------------------------| |-----------------------------------|
64// | | | PPR stack objects |
65// | callee-saved fp/simd/SVE regs | |-----------------------------------|
66// | | | <hazard padding> |
67// |-----------------------------------| |-----------------------------------|
68// | | | callee-saved ZPR/FPR registers |
69// | SVE stack objects | |-----------------------------------|
70// | | | ZPR stack objects |
71// |-----------------------------------| |-----------------------------------|
72// ^ NB: FPR CSRs are promoted to ZPRs
73// |-----------------------------------|
74// |.empty.space.to.make.part.below....|
75// |.aligned.in.case.it.needs.more.than| (size of this area is unknown at
76// |.the.standard.16-byte.alignment....| compile time; if present)
77// |-----------------------------------|
78// | local variables of fixed size |
79// | including spill slots |
80// | <FPR> |
81// | <hazard padding> |
82// | <GPR> |
83// |-----------------------------------| <- bp(not defined by ABI,
84// |.variable-sized.local.variables....| LLVM chooses X19)
85// |.(VLAs)............................| (size of this area is unknown at
86// |...................................| compile time)
87// |-----------------------------------| <- sp
88// | | Lower address
89//
90//
91// To access the data in a frame, at-compile time, a constant offset must be
92// computable from one of the pointers (fp, bp, sp) to access it. The size
93// of the areas with a dotted background cannot be computed at compile-time
94// if they are present, making it required to have all three of fp, bp and
95// sp to be set up to be able to access all contents in the frame areas,
96// assuming all of the frame areas are non-empty.
97//
98// For most functions, some of the frame areas are empty. For those functions,
99// it may not be necessary to set up fp or bp:
100// * A base pointer is definitely needed when there are both VLAs and local
101// variables with more-than-default alignment requirements.
102// * A frame pointer is definitely needed when there are local variables with
103// more-than-default alignment requirements.
104//
105// For Darwin platforms the frame-record (fp, lr) is stored at the top of the
106// callee-saved area, since the unwind encoding does not allow for encoding
107// this dynamically and existing tools depend on this layout. For other
108// platforms, the frame-record is stored at the bottom of the (gpr) callee-saved
109// area to allow SVE stack objects (allocated directly below the callee-saves,
110// if available) to be accessed directly from the framepointer.
111// The SVE spill/fill instructions have VL-scaled addressing modes such
112// as:
113// ldr z8, [fp, #-7 mul vl]
114// For SVE the size of the vector length (VL) is not known at compile-time, so
115// '#-7 mul vl' is an offset that can only be evaluated at runtime. With this
116// layout, we don't need to add an unscaled offset to the framepointer before
117// accessing the SVE object in the frame.
118//
119// In some cases when a base pointer is not strictly needed, it is generated
120// anyway when offsets from the frame pointer to access local variables become
121// so large that the offset can't be encoded in the immediate fields of loads
122// or stores.
123//
124// Outgoing function arguments must be at the bottom of the stack frame when
125// calling another function. If we do not have variable-sized stack objects, we
126// can allocate a "reserved call frame" area at the bottom of the local
127// variable area, large enough for all outgoing calls. If we do have VLAs, then
128// the stack pointer must be decremented and incremented around each call to
129// make space for the arguments below the VLAs.
130//
131// FIXME: also explain the redzone concept.
132//
133// About stack hazards: Under some SME contexts, a coprocessor with its own
134// separate cache can used for FP operations. This can create hazards if the CPU
135// and the SME unit try to access the same area of memory, including if the
136// access is to an area of the stack. To try to alleviate this we attempt to
137// introduce extra padding into the stack frame between FP and GPR accesses,
138// controlled by the aarch64-stack-hazard-size option. Without changing the
139// layout of the stack frame in the diagram above, a stack object of size
140// aarch64-stack-hazard-size is added between GPR and FPR CSRs. Another is added
141// to the stack objects section, and stack objects are sorted so that FPR >
142// Hazard padding slot > GPRs (where possible). Unfortunately some things are
143// not handled well (VLA area, arguments on the stack, objects with both GPR and
144// FPR accesses), but if those are controlled by the user then the entire stack
145// frame becomes GPR at the start/end with FPR in the middle, surrounded by
146// Hazard padding.
147//
148// An example of the prologue:
149//
150// .globl __foo
151// .align 2
152// __foo:
153// Ltmp0:
154// .cfi_startproc
155// .cfi_personality 155, ___gxx_personality_v0
156// Leh_func_begin:
157// .cfi_lsda 16, Lexception33
158//
159// stp xa,bx, [sp, -#offset]!
160// ...
161// stp x28, x27, [sp, #offset-32]
162// stp fp, lr, [sp, #offset-16]
163// add fp, sp, #offset - 16
164// sub sp, sp, #1360
165//
166// The Stack:
167// +-------------------------------------------+
168// 10000 | ........ | ........ | ........ | ........ |
169// 10004 | ........ | ........ | ........ | ........ |
170// +-------------------------------------------+
171// 10008 | ........ | ........ | ........ | ........ |
172// 1000c | ........ | ........ | ........ | ........ |
173// +===========================================+
174// 10010 | X28 Register |
175// 10014 | X28 Register |
176// +-------------------------------------------+
177// 10018 | X27 Register |
178// 1001c | X27 Register |
179// +===========================================+
180// 10020 | Frame Pointer |
181// 10024 | Frame Pointer |
182// +-------------------------------------------+
183// 10028 | Link Register |
184// 1002c | Link Register |
185// +===========================================+
186// 10030 | ........ | ........ | ........ | ........ |
187// 10034 | ........ | ........ | ........ | ........ |
188// +-------------------------------------------+
189// 10038 | ........ | ........ | ........ | ........ |
190// 1003c | ........ | ........ | ........ | ........ |
191// +-------------------------------------------+
192//
193// [sp] = 10030 :: >>initial value<<
194// sp = 10020 :: stp fp, lr, [sp, #-16]!
195// fp = sp == 10020 :: mov fp, sp
196// [sp] == 10020 :: stp x28, x27, [sp, #-16]!
197// sp == 10010 :: >>final value<<
198//
199// The frame pointer (w29) points to address 10020. If we use an offset of
200// '16' from 'w29', we get the CFI offsets of -8 for w30, -16 for w29, -24
201// for w27, and -32 for w28:
202//
203// Ltmp1:
204// .cfi_def_cfa w29, 16
205// Ltmp2:
206// .cfi_offset w30, -8
207// Ltmp3:
208// .cfi_offset w29, -16
209// Ltmp4:
210// .cfi_offset w27, -24
211// Ltmp5:
212// .cfi_offset w28, -32
213//
214//===----------------------------------------------------------------------===//
215
216#include "AArch64FrameLowering.h"
217#include "AArch64InstrInfo.h"
218#include "AArch64MachineFunctionInfo.h"
219#include "AArch64PrologueEpilogue.h"
220#include "AArch64RegisterInfo.h"
221#include "AArch64SMEAttributes.h"
222#include "AArch64Subtarget.h"
223#include "MCTargetDesc/AArch64AddressingModes.h"
224#include "MCTargetDesc/AArch64MCTargetDesc.h"
225#include "llvm/ADT/ScopeExit.h"
226#include "llvm/ADT/SmallVector.h"
227#include "llvm/Analysis/ValueTracking.h"
228#include "llvm/CodeGen/CFIInstBuilder.h"
229#include "llvm/CodeGen/LivePhysRegs.h"
230#include "llvm/CodeGen/MachineBasicBlock.h"
231#include "llvm/CodeGen/MachineFrameInfo.h"
232#include "llvm/CodeGen/MachineFunction.h"
233#include "llvm/CodeGen/MachineInstr.h"
234#include "llvm/CodeGen/MachineInstrBuilder.h"
235#include "llvm/CodeGen/MachineMemOperand.h"
236#include "llvm/CodeGen/MachineModuleInfo.h"
237#include "llvm/CodeGen/MachineOperand.h"
238#include "llvm/CodeGen/MachineRegisterInfo.h"
239#include "llvm/CodeGen/RegisterScavenging.h"
240#include "llvm/CodeGen/TargetInstrInfo.h"
241#include "llvm/CodeGen/TargetRegisterInfo.h"
242#include "llvm/CodeGen/TargetSubtargetInfo.h"
243#include "llvm/CodeGen/WinEHFuncInfo.h"
244#include "llvm/IR/Attributes.h"
245#include "llvm/IR/CallingConv.h"
246#include "llvm/IR/DataLayout.h"
247#include "llvm/IR/DebugLoc.h"
248#include "llvm/IR/Function.h"
249#include "llvm/MC/MCAsmInfo.h"
250#include "llvm/MC/MCDwarf.h"
251#include "llvm/Support/CommandLine.h"
252#include "llvm/Support/Debug.h"
253#include "llvm/Support/ErrorHandling.h"
254#include "llvm/Support/FormatVariadic.h"
255#include "llvm/Support/MathExtras.h"
256#include "llvm/Support/raw_ostream.h"
257#include "llvm/Target/TargetMachine.h"
258#include <cassert>
259#include <cstdint>
260#include <iterator>
261#include <optional>
262#include <vector>
263
264using namespace llvm;
265
266#define DEBUG_TYPE "frame-info"
267
268static cl::opt<bool> EnableRedZone("aarch64-redzone",
269 cl::desc("enable use of redzone on AArch64"),
270 cl::init(Val: false), cl::Hidden);
271
272static cl::opt<bool> StackTaggingMergeSetTag(
273 "stack-tagging-merge-settag",
274 cl::desc("merge settag instruction in function epilog"), cl::init(Val: true),
275 cl::Hidden);
276
277static cl::opt<bool> OrderFrameObjects("aarch64-order-frame-objects",
278 cl::desc("sort stack allocations"),
279 cl::init(Val: true), cl::Hidden);
280
281static cl::opt<bool>
282 SplitSVEObjects("aarch64-split-sve-objects",
283 cl::desc("Split allocation of ZPR & PPR objects"),
284 cl::init(Val: true), cl::Hidden);
285
286cl::opt<bool> EnableHomogeneousPrologEpilog(
287 "homogeneous-prolog-epilog", cl::Hidden,
288 cl::desc("Emit homogeneous prologue and epilogue for the size "
289 "optimization (default = off)"));
290
291// Stack hazard size for analysis remarks. StackHazardSize takes precedence.
292static cl::opt<unsigned>
293 StackHazardRemarkSize("aarch64-stack-hazard-remark-size", cl::init(Val: 0),
294 cl::Hidden);
295// Whether to insert padding into non-streaming functions (for testing).
296static cl::opt<bool>
297 StackHazardInNonStreaming("aarch64-stack-hazard-in-non-streaming",
298 cl::init(Val: false), cl::Hidden);
299
300static cl::opt<bool> DisableMultiVectorSpillFill(
301 "aarch64-disable-multivector-spill-fill",
302 cl::desc("Disable use of LD/ST pairs for SME2 or SVE2p1"), cl::init(Val: false),
303 cl::Hidden);
304
305int64_t
306AArch64FrameLowering::getArgumentStackToRestore(MachineFunction &MF,
307 MachineBasicBlock &MBB) const {
308 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
309 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
310 bool IsTailCallReturn = (MBB.end() != MBBI)
311 ? AArch64InstrInfo::isTailCallReturnInst(MI: *MBBI)
312 : false;
313
314 int64_t ArgumentPopSize = 0;
315 if (IsTailCallReturn) {
316 MachineOperand &StackAdjust = MBBI->getOperand(i: 1);
317
318 // For a tail-call in a callee-pops-arguments environment, some or all of
319 // the stack may actually be in use for the call's arguments, this is
320 // calculated during LowerCall and consumed here...
321 ArgumentPopSize = StackAdjust.getImm();
322 } else {
323 // ... otherwise the amount to pop is *all* of the argument space,
324 // conveniently stored in the MachineFunctionInfo by
325 // LowerFormalArguments. This will, of course, be zero for the C calling
326 // convention.
327 ArgumentPopSize = AFI->getArgumentStackToRestore();
328 }
329
330 return ArgumentPopSize;
331}
332
333static bool produceCompactUnwindFrame(const AArch64FrameLowering &,
334 MachineFunction &MF);
335
336enum class AssignObjectOffsets { No, Yes };
337/// Process all the SVE stack objects and the SVE stack size and offsets for
338/// each object. If AssignOffsets is "Yes", the offsets get assigned (and SVE
339/// stack sizes set). Returns the size of the SVE stack.
340static SVEStackSizes determineSVEStackSizes(MachineFunction &MF,
341 AssignObjectOffsets AssignOffsets);
342
343static unsigned getStackHazardSize(const MachineFunction &MF) {
344 return MF.getSubtarget<AArch64Subtarget>().getStreamingHazardSize();
345}
346
347StackOffset
348AArch64FrameLowering::getZPRStackSize(const MachineFunction &MF) const {
349 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
350 return StackOffset::getScalable(Scalable: AFI->getStackSizeZPR());
351}
352
353StackOffset
354AArch64FrameLowering::getPPRStackSize(const MachineFunction &MF) const {
355 // With split SVE objects, the hazard padding is added to the PPR region,
356 // which places it between the [GPR, PPR] area and the [ZPR, FPR] area. This
357 // avoids hazards between both GPRs and FPRs and ZPRs and PPRs.
358 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
359 return StackOffset::get(Fixed: AFI->hasSplitSVEObjects() ? getStackHazardSize(MF)
360 : 0,
361 Scalable: AFI->getStackSizePPR());
362}
363
364// Conservatively, returns true if the function is likely to have SVE vectors
365// on the stack. This function is safe to be called before callee-saves or
366// object offsets have been determined.
367static bool isLikelyToHaveSVEStack(const AArch64FrameLowering &AFL,
368 const MachineFunction &MF) {
369 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
370 if (AFI->isSVECC())
371 return true;
372
373 if (AFI->hasCalculatedStackSizeSVE())
374 return bool(AFL.getSVEStackSize(MF));
375
376 const MachineFrameInfo &MFI = MF.getFrameInfo();
377 for (int FI = MFI.getObjectIndexBegin(); FI < MFI.getObjectIndexEnd(); FI++) {
378 if (MFI.hasScalableStackID(ObjectIdx: FI))
379 return true;
380 }
381
382 return false;
383}
384
385static bool isTargetWindows(const MachineFunction &MF) {
386 // TODO: Should this include targets like UEFI (which use Windows CFI)?
387 // Note: Currently, there is not AArch64 support for UEFI. The value returned
388 // here must align with the predicate used for returning the list of callee
389 // saved regs in AArch64RegisterInfo::getCalleeSavedRegs(), so that we use
390 // invalidateWindowsRegisterPairing() where appropriate.
391 return MF.getSubtarget<AArch64Subtarget>().isTargetWindows();
392}
393
394bool AArch64FrameLowering::hasSVECalleeSavesAboveFrameRecord(
395 const MachineFunction &MF) const {
396 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
397 return isTargetWindows(MF) && AFI->getSVECalleeSavedStackSize();
398}
399
400/// Returns true if a homogeneous prolog or epilog code can be emitted
401/// for the size optimization. If possible, a frame helper call is injected.
402/// When Exit block is given, this check is for epilog.
403bool AArch64FrameLowering::homogeneousPrologEpilog(
404 MachineFunction &MF, MachineBasicBlock *Exit) const {
405 if (!MF.getFunction().hasMinSize())
406 return false;
407 if (!EnableHomogeneousPrologEpilog)
408 return false;
409 if (EnableRedZone)
410 return false;
411
412 // TODO: Window is supported yet.
413 if (isTargetWindows(MF))
414 return false;
415
416 // TODO: SVE is not supported yet.
417 if (isLikelyToHaveSVEStack(AFL: *this, MF))
418 return false;
419
420 // Bail on stack adjustment needed on return for simplicity.
421 const MachineFrameInfo &MFI = MF.getFrameInfo();
422 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
423 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF))
424 return false;
425 if (Exit && getArgumentStackToRestore(MF, MBB&: *Exit))
426 return false;
427
428 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
429 if (AFI->hasSwiftAsyncContext() || AFI->hasStreamingModeChanges())
430 return false;
431
432 // If there are an odd number of GPRs before LR and FP in the CSRs list,
433 // they will not be paired into one RegPairInfo, which is incompatible with
434 // the assumption made by the homogeneous prolog epilog pass.
435 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
436 unsigned NumGPRs = 0;
437 for (unsigned I = 0; CSRegs[I]; ++I) {
438 Register Reg = CSRegs[I];
439 if (Reg == AArch64::LR) {
440 assert(CSRegs[I + 1] == AArch64::FP);
441 if (NumGPRs % 2 != 0)
442 return false;
443 break;
444 }
445 if (AArch64::GPR64RegClass.contains(Reg))
446 ++NumGPRs;
447 }
448
449 return true;
450}
451
452/// Returns true if CSRs should be paired.
453bool AArch64FrameLowering::producePairRegisters(MachineFunction &MF) const {
454 return produceCompactUnwindFrame(*this, MF) || homogeneousPrologEpilog(MF);
455}
456
457/// This is the biggest offset to the stack pointer we can encode in aarch64
458/// instructions (without using a separate calculation and a temp register).
459/// Note that the exception here are vector stores/loads which cannot encode any
460/// displacements (see estimateRSStackSizeLimit(), isAArch64FrameOffsetLegal()).
461static const unsigned DefaultSafeSPDisplacement = 255;
462
463/// Look at each instruction that references stack frames and return the stack
464/// size limit beyond which some of these instructions will require a scratch
465/// register during their expansion later.
466static unsigned estimateRSStackSizeLimit(MachineFunction &MF) {
467 // FIXME: For now, just conservatively guesstimate based on unscaled indexing
468 // range. We'll end up allocating an unnecessary spill slot a lot, but
469 // realistically that's not a big deal at this stage of the game.
470 for (MachineBasicBlock &MBB : MF) {
471 for (MachineInstr &MI : MBB) {
472 if (MI.isDebugInstr() || MI.isPseudo() ||
473 MI.getOpcode() == AArch64::ADDXri ||
474 MI.getOpcode() == AArch64::ADDSXri)
475 continue;
476
477 for (const MachineOperand &MO : MI.operands()) {
478 if (!MO.isFI())
479 continue;
480
481 StackOffset Offset;
482 if (isAArch64FrameOffsetLegal(MI, Offset, OutUseUnscaledOp: nullptr, OutUnscaledOp: nullptr, EmittableOffset: nullptr) ==
483 AArch64FrameOffsetCannotUpdate)
484 return 0;
485 }
486 }
487 }
488 return DefaultSafeSPDisplacement;
489}
490
491TargetStackID::Value
492AArch64FrameLowering::getStackIDForScalableVectors() const {
493 return TargetStackID::ScalableVector;
494}
495
496unsigned
497AArch64FrameLowering::getFixedObjectSize(const MachineFunction &MF,
498 const AArch64FunctionInfo *AFI,
499 bool IsWin64, bool IsFunclet) const {
500 assert(AFI->getTailCallReservedStack() % 16 == 0 &&
501 "Tail call reserved stack must be aligned to 16 bytes");
502 if (!IsWin64 || IsFunclet) {
503 return AFI->getTailCallReservedStack();
504 } else {
505 if (AFI->getTailCallReservedStack() != 0 &&
506 !MF.getFunction().getAttributes().hasAttrSomewhere(
507 Kind: Attribute::SwiftAsync))
508 report_fatal_error(reason: "cannot generate ABI-changing tail call for Win64");
509 unsigned FixedObjectSize = AFI->getTailCallReservedStack();
510
511 // Var args are stored here in the primary function.
512 FixedObjectSize += AFI->getVarArgsGPRSize();
513
514 if (MF.hasEHFunclets()) {
515 // Catch objects are stored here in the primary function.
516 const MachineFrameInfo &MFI = MF.getFrameInfo();
517 const WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo();
518 SmallSetVector<int, 8> CatchObjFrameIndices;
519 for (const WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
520 for (const WinEHHandlerType &H : TBME.HandlerArray) {
521 int FrameIndex = H.CatchObj.FrameIndex;
522 if ((FrameIndex != INT_MAX) &&
523 CatchObjFrameIndices.insert(X: FrameIndex)) {
524 FixedObjectSize = alignTo(Value: FixedObjectSize,
525 Align: MFI.getObjectAlign(ObjectIdx: FrameIndex).value()) +
526 MFI.getObjectSize(ObjectIdx: FrameIndex);
527 }
528 }
529 }
530 // To support EH funclets we allocate an UnwindHelp object
531 FixedObjectSize += 8;
532 }
533 return alignTo(Value: FixedObjectSize, Align: 16);
534 }
535}
536
537bool AArch64FrameLowering::canUseRedZone(const MachineFunction &MF) const {
538 if (!EnableRedZone)
539 return false;
540
541 // Don't use the red zone if the function explicitly asks us not to.
542 // This is typically used for kernel code.
543 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
544 const unsigned RedZoneSize =
545 Subtarget.getTargetLowering()->getRedZoneSize(F: MF.getFunction());
546 if (!RedZoneSize)
547 return false;
548
549 const MachineFrameInfo &MFI = MF.getFrameInfo();
550 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
551 uint64_t NumBytes = AFI->getLocalStackSize();
552
553 // If neither NEON or SVE are available, a COPY from one Q-reg to
554 // another requires a spill -> reload sequence. We can do that
555 // using a pre-decrementing store/post-decrementing load, but
556 // if we do so, we can't use the Red Zone.
557 bool LowerQRegCopyThroughMem = Subtarget.hasFPARMv8() &&
558 !Subtarget.isNeonAvailable() &&
559 !Subtarget.hasSVE();
560
561 return !(MFI.hasCalls() || hasFP(MF) || NumBytes > RedZoneSize ||
562 AFI->hasSVEStackSize() || LowerQRegCopyThroughMem);
563}
564
565/// hasFPImpl - Return true if the specified function should have a dedicated
566/// frame pointer register.
567bool AArch64FrameLowering::hasFPImpl(const MachineFunction &MF) const {
568 const MachineFrameInfo &MFI = MF.getFrameInfo();
569 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
570 const AArch64FunctionInfo &AFI = *MF.getInfo<AArch64FunctionInfo>();
571
572 // Win64 EH requires a frame pointer if funclets are present, as the locals
573 // are accessed off the frame pointer in both the parent function and the
574 // funclets.
575 if (MF.hasEHFunclets())
576 return true;
577
578 // When the stack guard is mixed with the frame pointer, a dedicated FP is
579 // required so the guard value remains stable in the presence of dynamic
580 // stack allocations (e.g. _alloca on MSVCRT).
581 if (MFI.hasStackProtectorIndex()) {
582 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
583 if (Subtarget.getTargetLowering()->useStackGuardMixFP())
584 return true;
585 }
586
587 // Retain behavior of always omitting the FP for leaf functions when possible.
588 if (MF.disableFramePointerElim())
589 return true;
590 if (MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() ||
591 MFI.hasStackMap() || MFI.hasPatchPoint() ||
592 RegInfo->hasStackRealignment(MF))
593 return true;
594
595 // If we:
596 //
597 // 1. Have streaming mode changes
598 // OR:
599 // 2. Have a streaming body with SVE stack objects
600 //
601 // Then the value of VG restored when unwinding to this function may not match
602 // the value of VG used to set up the stack.
603 //
604 // This is a problem as the CFA can be described with an expression of the
605 // form: CFA = SP + NumBytes + VG * NumScalableBytes.
606 //
607 // If the value of VG used in that expression does not match the value used to
608 // set up the stack, an incorrect address for the CFA will be computed, and
609 // unwinding will fail.
610 //
611 // We work around this issue by ensuring the frame-pointer can describe the
612 // CFA in either of these cases.
613 if (AFI.needsDwarfUnwindInfo(MF) &&
614 ((requiresSaveVG(MF) || AFI.getSMEFnAttrs().hasStreamingBody()) &&
615 (!AFI.hasCalculatedStackSizeSVE() || AFI.hasSVEStackSize())))
616 return true;
617 // With large callframes around we may need to use FP to access the scavenging
618 // emergency spillslot.
619 //
620 // Unfortunately some calls to hasFP() like machine verifier ->
621 // getReservedReg() -> hasFP in the middle of global isel are too early
622 // to know the max call frame size. Hopefully conservatively returning "true"
623 // in those cases is fine.
624 // DefaultSafeSPDisplacement is fine as we only emergency spill GP regs.
625 if (!MFI.isMaxCallFrameSizeComputed() ||
626 MFI.getMaxCallFrameSize() > DefaultSafeSPDisplacement)
627 return true;
628
629 return false;
630}
631
632/// Should the Frame Pointer be reserved for the current function?
633bool AArch64FrameLowering::isFPReserved(const MachineFunction &MF) const {
634 const TargetMachine &TM = MF.getTarget();
635 const Triple &TT = TM.getTargetTriple();
636
637 // These OSes require the frame chain is valid, even if the current frame does
638 // not use a frame pointer.
639 if (TT.isOSDarwin() || TT.isOSWindows())
640 return true;
641
642 // If the function has a frame pointer, it is reserved.
643 if (hasFP(MF))
644 return true;
645
646 // Frontend has requested to preserve the frame pointer.
647 if (MF.framePointerIsReserved())
648 return true;
649
650 return false;
651}
652
653/// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
654/// not required, we reserve argument space for call sites in the function
655/// immediately on entry to the current function. This eliminates the need for
656/// add/sub sp brackets around call sites. Returns true if the call frame is
657/// included as part of the stack frame.
658bool AArch64FrameLowering::hasReservedCallFrame(
659 const MachineFunction &MF) const {
660 // The stack probing code for the dynamically allocated outgoing arguments
661 // area assumes that the stack is probed at the top - either by the prologue
662 // code, which issues a probe if `hasVarSizedObjects` return true, or by the
663 // most recent variable-sized object allocation. Changing the condition here
664 // may need to be followed up by changes to the probe issuing logic.
665 return !MF.getFrameInfo().hasVarSizedObjects();
666}
667
668MachineBasicBlock::iterator AArch64FrameLowering::eliminateCallFramePseudoInstr(
669 MachineFunction &MF, MachineBasicBlock &MBB,
670 MachineBasicBlock::iterator I) const {
671
672 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
673 const AArch64InstrInfo *TII = Subtarget.getInstrInfo();
674 const AArch64TargetLowering *TLI = Subtarget.getTargetLowering();
675 [[maybe_unused]] MachineFrameInfo &MFI = MF.getFrameInfo();
676 DebugLoc DL = I->getDebugLoc();
677 unsigned Opc = I->getOpcode();
678 bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode();
679 uint64_t CalleePopAmount = IsDestroy ? I->getOperand(i: 1).getImm() : 0;
680
681 if (!hasReservedCallFrame(MF)) {
682 int64_t Amount = I->getOperand(i: 0).getImm();
683 Amount = alignTo(Size: Amount, A: getStackAlign());
684 if (!IsDestroy)
685 Amount = -Amount;
686
687 // N.b. if CalleePopAmount is valid but zero (i.e. callee would pop, but it
688 // doesn't have to pop anything), then the first operand will be zero too so
689 // this adjustment is a no-op.
690 if (CalleePopAmount == 0) {
691 // FIXME: in-function stack adjustment for calls is limited to 24-bits
692 // because there's no guaranteed temporary register available.
693 //
694 // ADD/SUB (immediate) has only LSL #0 and LSL #12 available.
695 // 1) For offset <= 12-bit, we use LSL #0
696 // 2) For 12-bit <= offset <= 24-bit, we use two instructions. One uses
697 // LSL #0, and the other uses LSL #12.
698 //
699 // Most call frames will be allocated at the start of a function so
700 // this is OK, but it is a limitation that needs dealing with.
701 assert(Amount > -0xffffff && Amount < 0xffffff && "call frame too large");
702
703 if (TLI->hasInlineStackProbe(MF) &&
704 -Amount >= AArch64::StackProbeMaxUnprobedStack) {
705 // When stack probing is enabled, the decrement of SP may need to be
706 // probed. We only need to do this if the call site needs 1024 bytes of
707 // space or more, because a region smaller than that is allowed to be
708 // unprobed at an ABI boundary. We rely on the fact that SP has been
709 // probed exactly at this point, either by the prologue or most recent
710 // dynamic allocation.
711 assert(MFI.hasVarSizedObjects() &&
712 "non-reserved call frame without var sized objects?");
713 Register ScratchReg =
714 MF.getRegInfo().createVirtualRegister(RegClass: &AArch64::GPR64RegClass);
715 inlineStackProbeFixed(MBBI: I, ScratchReg, FrameSize: -Amount, CFAOffset: StackOffset::get(Fixed: 0, Scalable: 0));
716 } else {
717 emitFrameOffset(MBB, MBBI: I, DL, DestReg: AArch64::SP, SrcReg: AArch64::SP,
718 Offset: StackOffset::getFixed(Fixed: Amount), TII);
719 }
720 }
721 } else if (CalleePopAmount != 0) {
722 // If the calling convention demands that the callee pops arguments from the
723 // stack, we want to add it back if we have a reserved call frame.
724 assert(CalleePopAmount < 0xffffff && "call frame too large");
725 emitFrameOffset(MBB, MBBI: I, DL, DestReg: AArch64::SP, SrcReg: AArch64::SP,
726 Offset: StackOffset::getFixed(Fixed: -(int64_t)CalleePopAmount), TII);
727 }
728 return MBB.erase(I);
729}
730
731void AArch64FrameLowering::resetCFIToInitialState(
732 MachineBasicBlock &MBB) const {
733
734 MachineFunction &MF = *MBB.getParent();
735 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
736 const auto &TRI = *Subtarget.getRegisterInfo();
737 const auto &MFI = *MF.getInfo<AArch64FunctionInfo>();
738
739 CFIInstBuilder CFIBuilder(MBB, MBB.begin(), MachineInstr::NoFlags);
740
741 // Reset the CFA to `SP + 0`.
742 CFIBuilder.buildDefCFA(Reg: AArch64::SP, Offset: 0);
743
744 // Flip the RA sign state.
745 if (MFI.shouldSignReturnAddress(MF)) {
746 if (MFI.branchProtectionPAuthLR()) {
747 CFIBuilder.buildNegateRAStateWithPC();
748 } else if (!MF.getTarget().getTargetTriple().isOSBinFormatMachO()) {
749 CFIBuilder.buildNegateRAState();
750 }
751 }
752
753 // Shadow call stack uses X18, reset it.
754 if (MFI.needsShadowCallStackPrologueEpilogue(MF))
755 CFIBuilder.buildSameValue(Reg: AArch64::X18);
756
757 // Emit .cfi_same_value for callee-saved registers.
758 const std::vector<CalleeSavedInfo> &CSI =
759 MF.getFrameInfo().getCalleeSavedInfo();
760 for (const auto &Info : CSI) {
761 MCRegister Reg = Info.getReg();
762 if (!TRI.regNeedsCFI(Reg, RegToUseForCFI&: Reg))
763 continue;
764 CFIBuilder.buildSameValue(Reg);
765 }
766}
767
768static MCRegister getRegisterOrZero(MCRegister Reg, bool HasSVE) {
769 switch (Reg.id()) {
770 default:
771 // The called routine is expected to preserve r19-r28
772 // r29 and r30 are used as frame pointer and link register resp.
773 return 0;
774
775 // GPRs
776#define CASE(n) \
777 case AArch64::W##n: \
778 case AArch64::X##n: \
779 return AArch64::X##n
780 CASE(0);
781 CASE(1);
782 CASE(2);
783 CASE(3);
784 CASE(4);
785 CASE(5);
786 CASE(6);
787 CASE(7);
788 CASE(8);
789 CASE(9);
790 CASE(10);
791 CASE(11);
792 CASE(12);
793 CASE(13);
794 CASE(14);
795 CASE(15);
796 CASE(16);
797 CASE(17);
798 CASE(18);
799#undef CASE
800
801 // FPRs
802#define CASE(n) \
803 case AArch64::B##n: \
804 case AArch64::H##n: \
805 case AArch64::S##n: \
806 case AArch64::D##n: \
807 case AArch64::Q##n: \
808 return HasSVE ? AArch64::Z##n : AArch64::Q##n
809 CASE(0);
810 CASE(1);
811 CASE(2);
812 CASE(3);
813 CASE(4);
814 CASE(5);
815 CASE(6);
816 CASE(7);
817 CASE(8);
818 CASE(9);
819 CASE(10);
820 CASE(11);
821 CASE(12);
822 CASE(13);
823 CASE(14);
824 CASE(15);
825 CASE(16);
826 CASE(17);
827 CASE(18);
828 CASE(19);
829 CASE(20);
830 CASE(21);
831 CASE(22);
832 CASE(23);
833 CASE(24);
834 CASE(25);
835 CASE(26);
836 CASE(27);
837 CASE(28);
838 CASE(29);
839 CASE(30);
840 CASE(31);
841#undef CASE
842 }
843}
844
845void AArch64FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
846 MachineBasicBlock &MBB,
847 RegScavenger *) const {
848 // Insertion point.
849 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
850
851 // Fake a debug loc.
852 DebugLoc DL;
853 if (MBBI != MBB.end())
854 DL = MBBI->getDebugLoc();
855
856 const MachineFunction &MF = *MBB.getParent();
857 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
858 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
859
860 BitVector GPRsToZero(TRI.getNumRegs());
861 BitVector FPRsToZero(TRI.getNumRegs());
862 bool HasSVE = STI.isSVEorStreamingSVEAvailable();
863 // Without an FP unit (e.g. -mgeneral-regs-only) the FP/vector registers can't
864 // hold a value and there is no instruction to clear them, so leave them out.
865 bool HasFPR = STI.hasFPARMv8();
866 for (MCRegister Reg : RegsToZero.set_bits()) {
867 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
868 // For GPRs, we only care to clear out the 64-bit register.
869 if (MCRegister XReg = getRegisterOrZero(Reg, HasSVE))
870 GPRsToZero.set(XReg);
871 } else if (HasFPR && AArch64InstrInfo::isFpOrNEON(Reg)) {
872 // For FPRs,
873 if (MCRegister XReg = getRegisterOrZero(Reg, HasSVE))
874 FPRsToZero.set(XReg);
875 }
876 }
877
878 const AArch64InstrInfo &TII = *STI.getInstrInfo();
879
880 // Zero out GPRs.
881 for (MCRegister Reg : GPRsToZero.set_bits())
882 TII.buildClearRegister(Reg, MBB, Iter: MBBI, DL);
883
884 // Zero out FP/vector registers.
885 for (MCRegister Reg : FPRsToZero.set_bits())
886 TII.buildClearRegister(Reg, MBB, Iter: MBBI, DL);
887
888 if (HasSVE) {
889 for (MCRegister PReg :
890 {AArch64::P0, AArch64::P1, AArch64::P2, AArch64::P3, AArch64::P4,
891 AArch64::P5, AArch64::P6, AArch64::P7, AArch64::P8, AArch64::P9,
892 AArch64::P10, AArch64::P11, AArch64::P12, AArch64::P13, AArch64::P14,
893 AArch64::P15}) {
894 if (RegsToZero[PReg])
895 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AArch64::PFALSE), DestReg: PReg);
896 }
897 }
898}
899
900bool AArch64FrameLowering::windowsRequiresStackProbe(
901 const MachineFunction &MF, uint64_t StackSizeInBytes) const {
902 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
903 const AArch64FunctionInfo &MFI = *MF.getInfo<AArch64FunctionInfo>();
904 // TODO: When implementing stack protectors, take that into account
905 // for the probe threshold.
906 return Subtarget.isTargetWindows() && MFI.hasStackProbing() &&
907 StackSizeInBytes >= uint64_t(MFI.getStackProbeSize());
908}
909
910static void getLiveRegsForEntryMBB(LivePhysRegs &LiveRegs,
911 const MachineBasicBlock &MBB) {
912 const MachineFunction *MF = MBB.getParent();
913 LiveRegs.addLiveIns(MBB);
914 // Mark callee saved registers as used so we will not choose them.
915 const MCPhysReg *CSRegs = MF->getRegInfo().getCalleeSavedRegs();
916 for (unsigned i = 0; CSRegs[i]; ++i)
917 LiveRegs.addReg(Reg: CSRegs[i]);
918}
919
920Register
921AArch64FrameLowering::findScratchNonCalleeSaveRegister(MachineBasicBlock *MBB,
922 bool HasCall) const {
923 MachineFunction *MF = MBB->getParent();
924
925 // If MBB is an entry block, use X9 as the scratch register
926 // preserve_none functions may be using X9 to pass arguments,
927 // so prefer to pick an available register below.
928 if (&MF->front() == MBB &&
929 MF->getFunction().getCallingConv() != CallingConv::PreserveNone)
930 return AArch64::X9;
931
932 const AArch64Subtarget &Subtarget = MF->getSubtarget<AArch64Subtarget>();
933 const AArch64RegisterInfo &TRI = *Subtarget.getRegisterInfo();
934 LivePhysRegs LiveRegs(TRI);
935 getLiveRegsForEntryMBB(LiveRegs, MBB: *MBB);
936 if (HasCall) {
937 LiveRegs.addReg(Reg: AArch64::X16);
938 LiveRegs.addReg(Reg: AArch64::X17);
939 LiveRegs.addReg(Reg: AArch64::X18);
940 }
941
942 // Prefer X9 since it was historically used for the prologue scratch reg.
943 const MachineRegisterInfo &MRI = MF->getRegInfo();
944 if (LiveRegs.available(MRI, Reg: AArch64::X9))
945 return AArch64::X9;
946
947 for (unsigned Reg : AArch64::GPR64RegClass) {
948 if (LiveRegs.available(MRI, Reg))
949 return Reg;
950 }
951 return Register();
952}
953
954bool AArch64FrameLowering::canUseAsPrologue(
955 const MachineBasicBlock &MBB) const {
956 const MachineFunction *MF = MBB.getParent();
957 MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB);
958 const AArch64Subtarget &Subtarget = MF->getSubtarget<AArch64Subtarget>();
959 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
960 const AArch64TargetLowering *TLI = Subtarget.getTargetLowering();
961 const AArch64FunctionInfo *AFI = MF->getInfo<AArch64FunctionInfo>();
962
963 if (AFI->hasSwiftAsyncContext()) {
964 const AArch64RegisterInfo &TRI = *Subtarget.getRegisterInfo();
965 const MachineRegisterInfo &MRI = MF->getRegInfo();
966 LivePhysRegs LiveRegs(TRI);
967 getLiveRegsForEntryMBB(LiveRegs, MBB);
968 // The StoreSwiftAsyncContext clobbers X16 and X17. Make sure they are
969 // available.
970 if (!LiveRegs.available(MRI, Reg: AArch64::X16) ||
971 !LiveRegs.available(MRI, Reg: AArch64::X17))
972 return false;
973 }
974
975 // Certain stack probing sequences might clobber flags, then we can't use
976 // the block as a prologue if the flags register is a live-in.
977 if (MF->getInfo<AArch64FunctionInfo>()->hasStackProbing() &&
978 MBB.isLiveIn(Reg: AArch64::NZCV))
979 return false;
980
981 if (RegInfo->hasStackRealignment(MF: *MF) || TLI->hasInlineStackProbe(MF: *MF))
982 if (!findScratchNonCalleeSaveRegister(MBB: TmpMBB).isValid())
983 return false;
984
985 // May need a scratch register (for return value) if require making a special
986 // call
987 if (requiresSaveVG(MF: *MF) ||
988 windowsRequiresStackProbe(MF: *MF, StackSizeInBytes: std::numeric_limits<uint64_t>::max()))
989 if (!findScratchNonCalleeSaveRegister(MBB: TmpMBB, HasCall: true).isValid())
990 return false;
991
992 return true;
993}
994
995bool AArch64FrameLowering::needsWinCFI(const MachineFunction &MF) const {
996 const Function &F = MF.getFunction();
997 return MF.getTarget().getMCAsmInfo().usesWindowsCFI() &&
998 F.needsUnwindTableEntry();
999}
1000
1001bool AArch64FrameLowering::shouldSignReturnAddressEverywhere(
1002 const MachineFunction &MF) const {
1003 // FIXME: With WinCFI, extra care should be taken to place SEH_PACSignLR
1004 // and SEH_EpilogEnd instructions in the correct order.
1005 if (MF.getTarget().getMCAsmInfo().usesWindowsCFI())
1006 return false;
1007 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1008 return AFI->getSignReturnAddressCondition() == SignReturnAddress::All;
1009}
1010
1011// Given a load or a store instruction, generate an appropriate unwinding SEH
1012// code on Windows.
1013MachineBasicBlock::iterator
1014AArch64FrameLowering::insertSEH(MachineBasicBlock::iterator MBBI,
1015 const AArch64InstrInfo &TII,
1016 MachineInstr::MIFlag Flag) const {
1017 unsigned Opc = MBBI->getOpcode();
1018 MachineBasicBlock *MBB = MBBI->getParent();
1019 MachineFunction &MF = *MBB->getParent();
1020 DebugLoc DL = MBBI->getDebugLoc();
1021 unsigned ImmIdx = MBBI->getNumOperands() - 1;
1022 int Imm = MBBI->getOperand(i: ImmIdx).getImm();
1023 MachineInstrBuilder MIB;
1024 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1025 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
1026
1027 switch (Opc) {
1028 default:
1029 report_fatal_error(reason: "No SEH Opcode for this instruction");
1030 case AArch64::STR_ZXI:
1031 case AArch64::LDR_ZXI: {
1032 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1033 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveZReg))
1034 .addImm(Val: Reg0)
1035 .addImm(Val: Imm)
1036 .setMIFlag(Flag);
1037 break;
1038 }
1039 case AArch64::STR_PXI:
1040 case AArch64::LDR_PXI: {
1041 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1042 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SavePReg))
1043 .addImm(Val: Reg0)
1044 .addImm(Val: Imm)
1045 .setMIFlag(Flag);
1046 break;
1047 }
1048 case AArch64::LDPDpost:
1049 Imm = -Imm;
1050 [[fallthrough]];
1051 case AArch64::STPDpre: {
1052 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1053 unsigned Reg1 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 2).getReg());
1054 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFRegP_X))
1055 .addImm(Val: Reg0)
1056 .addImm(Val: Reg1)
1057 .addImm(Val: Imm * 8)
1058 .setMIFlag(Flag);
1059 break;
1060 }
1061 case AArch64::LDPXpost:
1062 Imm = -Imm;
1063 [[fallthrough]];
1064 case AArch64::STPXpre: {
1065 Register Reg0 = MBBI->getOperand(i: 1).getReg();
1066 Register Reg1 = MBBI->getOperand(i: 2).getReg();
1067 if (Reg0 == AArch64::FP && Reg1 == AArch64::LR)
1068 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFPLR_X))
1069 .addImm(Val: Imm * 8)
1070 .setMIFlag(Flag);
1071 else
1072 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveRegP_X))
1073 .addImm(Val: RegInfo->getSEHRegNum(i: Reg0))
1074 .addImm(Val: RegInfo->getSEHRegNum(i: Reg1))
1075 .addImm(Val: Imm * 8)
1076 .setMIFlag(Flag);
1077 break;
1078 }
1079 case AArch64::LDRDpost:
1080 Imm = -Imm;
1081 [[fallthrough]];
1082 case AArch64::STRDpre: {
1083 unsigned Reg = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1084 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFReg_X))
1085 .addImm(Val: Reg)
1086 .addImm(Val: Imm)
1087 .setMIFlag(Flag);
1088 break;
1089 }
1090 case AArch64::LDRXpost:
1091 Imm = -Imm;
1092 [[fallthrough]];
1093 case AArch64::STRXpre: {
1094 unsigned Reg = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1095 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveReg_X))
1096 .addImm(Val: Reg)
1097 .addImm(Val: Imm)
1098 .setMIFlag(Flag);
1099 break;
1100 }
1101 case AArch64::STPDi:
1102 case AArch64::LDPDi: {
1103 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1104 unsigned Reg1 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1105 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFRegP))
1106 .addImm(Val: Reg0)
1107 .addImm(Val: Reg1)
1108 .addImm(Val: Imm * 8)
1109 .setMIFlag(Flag);
1110 break;
1111 }
1112 case AArch64::STPXi:
1113 case AArch64::LDPXi: {
1114 Register Reg0 = MBBI->getOperand(i: 0).getReg();
1115 Register Reg1 = MBBI->getOperand(i: 1).getReg();
1116
1117 int SEHReg0 = RegInfo->getSEHRegNum(i: Reg0);
1118 int SEHReg1 = RegInfo->getSEHRegNum(i: Reg1);
1119
1120 if (Reg0 == AArch64::FP && Reg1 == AArch64::LR)
1121 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFPLR))
1122 .addImm(Val: Imm * 8)
1123 .setMIFlag(Flag);
1124 else if (SEHReg0 >= 19 && SEHReg1 >= 19)
1125 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveRegP))
1126 .addImm(Val: SEHReg0)
1127 .addImm(Val: SEHReg1)
1128 .addImm(Val: Imm * 8)
1129 .setMIFlag(Flag);
1130 else
1131 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveAnyRegIP))
1132 .addImm(Val: SEHReg0)
1133 .addImm(Val: SEHReg1)
1134 .addImm(Val: Imm * 8)
1135 .setMIFlag(Flag);
1136 break;
1137 }
1138 case AArch64::STRXui:
1139 case AArch64::LDRXui: {
1140 int Reg = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1141 if (Reg >= 19)
1142 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveReg))
1143 .addImm(Val: Reg)
1144 .addImm(Val: Imm * 8)
1145 .setMIFlag(Flag);
1146 else
1147 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveAnyRegI))
1148 .addImm(Val: Reg)
1149 .addImm(Val: Imm * 8)
1150 .setMIFlag(Flag);
1151 break;
1152 }
1153 case AArch64::STRDui:
1154 case AArch64::LDRDui: {
1155 unsigned Reg = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1156 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveFReg))
1157 .addImm(Val: Reg)
1158 .addImm(Val: Imm * 8)
1159 .setMIFlag(Flag);
1160 break;
1161 }
1162 case AArch64::STPQi:
1163 case AArch64::LDPQi: {
1164 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 0).getReg());
1165 unsigned Reg1 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1166 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveAnyRegQP))
1167 .addImm(Val: Reg0)
1168 .addImm(Val: Reg1)
1169 .addImm(Val: Imm * 16)
1170 .setMIFlag(Flag);
1171 break;
1172 }
1173 case AArch64::LDPQpost:
1174 Imm = -Imm;
1175 [[fallthrough]];
1176 case AArch64::STPQpre: {
1177 unsigned Reg0 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 1).getReg());
1178 unsigned Reg1 = RegInfo->getSEHRegNum(i: MBBI->getOperand(i: 2).getReg());
1179 MIB = BuildMI(MF, MIMD: DL, MCID: TII.get(Opcode: AArch64::SEH_SaveAnyRegQPX))
1180 .addImm(Val: Reg0)
1181 .addImm(Val: Reg1)
1182 .addImm(Val: Imm * 16)
1183 .setMIFlag(Flag);
1184 break;
1185 }
1186 }
1187 auto I = MBB->insertAfter(I: MBBI, MI: MIB);
1188 return I;
1189}
1190
1191bool AArch64FrameLowering::requiresSaveVG(const MachineFunction &MF) const {
1192 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1193 if (!AFI->needsDwarfUnwindInfo(MF) || !AFI->hasStreamingModeChanges())
1194 return false;
1195 // For Darwin platforms we don't save VG for non-SVE functions, even if SME
1196 // is enabled with streaming mode changes.
1197 auto &ST = MF.getSubtarget<AArch64Subtarget>();
1198 if (ST.isTargetDarwin())
1199 return ST.hasSVE();
1200 return true;
1201}
1202
1203void AArch64FrameLowering::emitPacRetPlusLeafHardening(
1204 MachineFunction &MF) const {
1205 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1206 const AArch64InstrInfo *TII = Subtarget.getInstrInfo();
1207
1208 auto EmitSignRA = [&](MachineBasicBlock &MBB) {
1209 DebugLoc DL; // Set debug location to unknown.
1210 MachineBasicBlock::iterator MBBI = MBB.begin();
1211
1212 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: AArch64::PAUTH_PROLOGUE))
1213 .setMIFlag(MachineInstr::FrameSetup);
1214 };
1215
1216 auto EmitAuthRA = [&](MachineBasicBlock &MBB) {
1217 DebugLoc DL;
1218 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
1219 if (MBBI != MBB.end())
1220 DL = MBBI->getDebugLoc();
1221
1222 TII->createPauthEpilogueInstr(MBB, DL);
1223 };
1224
1225 // This should be in sync with PEIImpl::calculateSaveRestoreBlocks.
1226 EmitSignRA(MF.front());
1227 for (MachineBasicBlock &MBB : MF) {
1228 if (MBB.isEHFuncletEntry())
1229 EmitSignRA(MBB);
1230 if (MBB.isReturnBlock())
1231 EmitAuthRA(MBB);
1232 }
1233}
1234
1235void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1236 MachineBasicBlock &MBB) const {
1237 AArch64PrologueEmitter PrologueEmitter(MF, MBB, *this);
1238 PrologueEmitter.emitPrologue();
1239}
1240
1241void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
1242 MachineBasicBlock &MBB) const {
1243 AArch64EpilogueEmitter EpilogueEmitter(MF, MBB, *this);
1244 EpilogueEmitter.emitEpilogue();
1245}
1246
1247bool AArch64FrameLowering::enableCFIFixup(const MachineFunction &MF) const {
1248 return TargetFrameLowering::enableCFIFixup(MF) &&
1249 MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
1250}
1251
1252bool AArch64FrameLowering::enableFullCFIFixup(const MachineFunction &MF) const {
1253 return enableCFIFixup(MF) &&
1254 MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF);
1255}
1256
1257/// getFrameIndexReference - Provide a base+offset reference to an FI slot for
1258/// debug info. It's the same as what we use for resolving the code-gen
1259/// references for now. FIXME: This can go wrong when references are
1260/// SP-relative and simple call frames aren't used.
1261StackOffset
1262AArch64FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
1263 Register &FrameReg) const {
1264 return resolveFrameIndexReference(
1265 MF, FI, FrameReg,
1266 /*PreferFP=*/
1267 MF.getFunction().hasFnAttribute(Kind: Attribute::SanitizeHWAddress) ||
1268 MF.getFunction().hasFnAttribute(Kind: Attribute::SanitizeMemTag),
1269 /*ForSimm=*/false);
1270}
1271
1272StackOffset
1273AArch64FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
1274 int FI) const {
1275 // This function serves to provide a comparable offset from a single reference
1276 // point (the value of SP at function entry) that can be used for analysis,
1277 // e.g. the stack-frame-layout analysis pass. It is not guaranteed to be
1278 // correct for all objects in the presence of VLA-area objects or dynamic
1279 // stack re-alignment.
1280
1281 const auto &MFI = MF.getFrameInfo();
1282
1283 int64_t ObjectOffset = MFI.getObjectOffset(ObjectIdx: FI);
1284 StackOffset ZPRStackSize = getZPRStackSize(MF);
1285 StackOffset PPRStackSize = getPPRStackSize(MF);
1286 StackOffset SVEStackSize = ZPRStackSize + PPRStackSize;
1287
1288 // For VLA-area objects, just emit an offset at the end of the stack frame.
1289 // Whilst not quite correct, these objects do live at the end of the frame and
1290 // so it is more useful for analysis for the offset to reflect this.
1291 if (MFI.isVariableSizedObjectIndex(ObjectIdx: FI)) {
1292 return StackOffset::getFixed(Fixed: -((int64_t)MFI.getStackSize())) - SVEStackSize;
1293 }
1294
1295 // This is correct in the absence of any SVE stack objects.
1296 if (!SVEStackSize)
1297 return StackOffset::getFixed(Fixed: ObjectOffset - getOffsetOfLocalArea());
1298
1299 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
1300 bool FPAfterSVECalleeSaves = hasSVECalleeSavesAboveFrameRecord(MF);
1301 if (MFI.hasScalableStackID(ObjectIdx: FI)) {
1302 if (FPAfterSVECalleeSaves &&
1303 -ObjectOffset <= (int64_t)AFI->getSVECalleeSavedStackSize()) {
1304 assert(!AFI->hasSplitSVEObjects() &&
1305 "split-sve-objects not supported with FPAfterSVECalleeSaves");
1306 return StackOffset::getScalable(Scalable: ObjectOffset);
1307 }
1308 StackOffset AccessOffset{};
1309 // The scalable vectors are below (lower address) the scalable predicates
1310 // with split SVE objects, so we must subtract the size of the predicates.
1311 if (AFI->hasSplitSVEObjects() &&
1312 MFI.getStackID(ObjectIdx: FI) == TargetStackID::ScalableVector)
1313 AccessOffset = -PPRStackSize;
1314 return AccessOffset +
1315 StackOffset::get(Fixed: -((int64_t)AFI->getCalleeSavedStackSize()),
1316 Scalable: ObjectOffset);
1317 }
1318
1319 bool IsFixed = MFI.isFixedObjectIndex(ObjectIdx: FI);
1320 bool IsCSR =
1321 !IsFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize(MFI));
1322
1323 StackOffset ScalableOffset = {};
1324 if (!IsFixed && !IsCSR) {
1325 ScalableOffset = -SVEStackSize;
1326 } else if (FPAfterSVECalleeSaves && IsCSR) {
1327 ScalableOffset =
1328 -StackOffset::getScalable(Scalable: AFI->getSVECalleeSavedStackSize());
1329 }
1330
1331 return StackOffset::getFixed(Fixed: ObjectOffset) + ScalableOffset;
1332}
1333
1334StackOffset
1335AArch64FrameLowering::getNonLocalFrameIndexReference(const MachineFunction &MF,
1336 int FI) const {
1337 return StackOffset::getFixed(Fixed: getSEHFrameIndexOffset(MF, FI));
1338}
1339
1340StackOffset AArch64FrameLowering::getFPOffset(const MachineFunction &MF,
1341 int64_t ObjectOffset) const {
1342 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
1343 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1344 const Function &F = MF.getFunction();
1345 bool IsWin64 = Subtarget.isCallingConvWin64(CC: F.getCallingConv(), IsVarArg: F.isVarArg());
1346 unsigned FixedObject =
1347 getFixedObjectSize(MF, AFI, IsWin64, /*IsFunclet=*/false);
1348 int64_t CalleeSaveSize = AFI->getCalleeSavedStackSize(MFI: MF.getFrameInfo());
1349 int64_t FPAdjust =
1350 CalleeSaveSize - AFI->getCalleeSaveBaseToFrameRecordOffset();
1351 return StackOffset::getFixed(Fixed: ObjectOffset + FixedObject + FPAdjust);
1352}
1353
1354StackOffset AArch64FrameLowering::getStackOffset(const MachineFunction &MF,
1355 int64_t ObjectOffset) const {
1356 const auto &MFI = MF.getFrameInfo();
1357 return StackOffset::getFixed(Fixed: ObjectOffset + (int64_t)MFI.getStackSize());
1358}
1359
1360// TODO: This function currently does not work for scalable vectors.
1361int AArch64FrameLowering::getSEHFrameIndexOffset(const MachineFunction &MF,
1362 int FI) const {
1363 const AArch64RegisterInfo *RegInfo =
1364 MF.getSubtarget<AArch64Subtarget>().getRegisterInfo();
1365 int ObjectOffset = MF.getFrameInfo().getObjectOffset(ObjectIdx: FI);
1366 return RegInfo->getLocalAddressRegister(MF) == AArch64::FP
1367 ? getFPOffset(MF, ObjectOffset).getFixed()
1368 : getStackOffset(MF, ObjectOffset).getFixed();
1369}
1370
1371StackOffset AArch64FrameLowering::resolveFrameIndexReference(
1372 const MachineFunction &MF, int FI, Register &FrameReg, bool PreferFP,
1373 bool ForSimm) const {
1374 const auto &MFI = MF.getFrameInfo();
1375 int64_t ObjectOffset = MFI.getObjectOffset(ObjectIdx: FI);
1376 bool isFixed = MFI.isFixedObjectIndex(ObjectIdx: FI);
1377 auto StackID = static_cast<TargetStackID::Value>(MFI.getStackID(ObjectIdx: FI));
1378 return resolveFrameOffsetReference(MF, ObjectOffset, isFixed, StackID,
1379 FrameReg, PreferFP, ForSimm);
1380}
1381
1382StackOffset AArch64FrameLowering::resolveFrameOffsetReference(
1383 const MachineFunction &MF, int64_t ObjectOffset, bool isFixed,
1384 TargetStackID::Value StackID, Register &FrameReg, bool PreferFP,
1385 bool ForSimm) const {
1386 const auto &MFI = MF.getFrameInfo();
1387 const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1388 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
1389 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
1390
1391 int64_t FPOffset = getFPOffset(MF, ObjectOffset).getFixed();
1392 int64_t Offset = getStackOffset(MF, ObjectOffset).getFixed();
1393 bool isCSR =
1394 !isFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize(MFI));
1395 bool isSVE = MFI.isScalableStackID(StackID);
1396
1397 StackOffset ZPRStackSize = getZPRStackSize(MF);
1398 StackOffset PPRStackSize = getPPRStackSize(MF);
1399 StackOffset SVEStackSize = ZPRStackSize + PPRStackSize;
1400
1401 // Use frame pointer to reference fixed objects. Use it for locals if
1402 // there are VLAs or a dynamically realigned SP (and thus the SP isn't
1403 // reliable as a base). Make sure useFPForScavengingIndex() does the
1404 // right thing for the emergency spill slot.
1405 bool UseFP = false;
1406 if (AFI->hasStackFrame() && !isSVE) {
1407 // We shouldn't prefer using the FP to access fixed-sized stack objects when
1408 // there are scalable (SVE) objects in between the FP and the fixed-sized
1409 // objects.
1410 PreferFP &= !SVEStackSize;
1411
1412 // Note: Keeping the following as multiple 'if' statements rather than
1413 // merging to a single expression for readability.
1414 //
1415 // Argument access should always use the FP.
1416 if (isFixed) {
1417 UseFP = hasFP(MF);
1418 } else if (isCSR && RegInfo->hasStackRealignment(MF)) {
1419 // References to the CSR area must use FP if we're re-aligning the stack
1420 // since the dynamically-sized alignment padding is between the SP/BP and
1421 // the CSR area.
1422 assert(hasFP(MF) && "Re-aligned stack must have frame pointer");
1423 UseFP = true;
1424 } else if (hasFP(MF) && !RegInfo->hasStackRealignment(MF)) {
1425 // If the FPOffset is negative and we're producing a signed immediate, we
1426 // have to keep in mind that the available offset range for negative
1427 // offsets is smaller than for positive ones. If an offset is available
1428 // via the FP and the SP, use whichever is closest.
1429 bool FPOffsetFits = !ForSimm || FPOffset >= -256;
1430 PreferFP |= Offset > -FPOffset && !SVEStackSize;
1431
1432 if (FPOffset >= 0) {
1433 // If the FPOffset is positive, that'll always be best, as the SP/BP
1434 // will be even further away.
1435 UseFP = true;
1436 } else if (MFI.hasVarSizedObjects()) {
1437 // If we have variable sized objects, we can use either FP or BP, as the
1438 // SP offset is unknown. We can use the base pointer if we have one and
1439 // FP is not preferred. If not, we're stuck with using FP.
1440 bool CanUseBP = RegInfo->hasBasePointer(MF);
1441 if (FPOffsetFits && CanUseBP) // Both are ok. Pick the best.
1442 UseFP = PreferFP;
1443 else if (!CanUseBP) // Can't use BP. Forced to use FP.
1444 UseFP = true;
1445 // else we can use BP and FP, but the offset from FP won't fit.
1446 // That will make us scavenge registers which we can probably avoid by
1447 // using BP. If it won't fit for BP either, we'll scavenge anyway.
1448 } else if (MF.hasEHFunclets() && !RegInfo->hasBasePointer(MF)) {
1449 // Funclets access the locals contained in the parent's stack frame
1450 // via the frame pointer, so we have to use the FP in the parent
1451 // function.
1452 (void) Subtarget;
1453 assert(Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv(),
1454 MF.getFunction().isVarArg()) &&
1455 "Funclets should only be present on Win64");
1456 UseFP = true;
1457 } else {
1458 // We have the choice between FP and (SP or BP).
1459 if (FPOffsetFits && PreferFP) // If FP is the best fit, use it.
1460 UseFP = true;
1461 }
1462 }
1463 }
1464
1465 assert(
1466 ((isFixed || isCSR) || !RegInfo->hasStackRealignment(MF) || !UseFP) &&
1467 "In the presence of dynamic stack pointer realignment, "
1468 "non-argument/CSR objects cannot be accessed through the frame pointer");
1469
1470 bool FPAfterSVECalleeSaves = hasSVECalleeSavesAboveFrameRecord(MF);
1471
1472 if (isSVE) {
1473 StackOffset FPOffset = StackOffset::get(
1474 Fixed: -AFI->getCalleeSaveBaseToFrameRecordOffset(), Scalable: ObjectOffset);
1475 StackOffset SPOffset =
1476 SVEStackSize +
1477 StackOffset::get(Fixed: MFI.getStackSize() - AFI->getCalleeSavedStackSize(),
1478 Scalable: ObjectOffset);
1479
1480 // With split SVE objects the ObjectOffset is relative to the split area
1481 // (i.e. the PPR area or ZPR area respectively).
1482 if (AFI->hasSplitSVEObjects() && StackID == TargetStackID::ScalableVector) {
1483 // If we're accessing an SVE vector with split SVE objects...
1484 // - From the FP we need to move down past the PPR area:
1485 FPOffset -= PPRStackSize;
1486 // - From the SP we only need to move up to the ZPR area:
1487 SPOffset -= PPRStackSize;
1488 // Note: `SPOffset = SVEStackSize + ...`, so `-= PPRStackSize` results in
1489 // `SPOffset = ZPRStackSize + ...`.
1490 }
1491
1492 if (FPAfterSVECalleeSaves) {
1493 FPOffset += StackOffset::getScalable(Scalable: AFI->getSVECalleeSavedStackSize());
1494 if (-ObjectOffset <= (int64_t)AFI->getSVECalleeSavedStackSize()) {
1495 FPOffset += StackOffset::getFixed(Fixed: AFI->getCalleeSavedStackSize());
1496 SPOffset += StackOffset::getFixed(Fixed: AFI->getCalleeSavedStackSize());
1497 }
1498 }
1499
1500 // Always use the FP for SVE spills if available and beneficial.
1501 if (hasFP(MF) && (SPOffset.getFixed() ||
1502 FPOffset.getScalable() < SPOffset.getScalable() ||
1503 RegInfo->hasStackRealignment(MF))) {
1504 FrameReg = RegInfo->getFrameRegister(MF);
1505 return FPOffset;
1506 }
1507 FrameReg = RegInfo->hasBasePointer(MF) ? RegInfo->getBaseRegister()
1508 : MCRegister(AArch64::SP);
1509
1510 return SPOffset;
1511 }
1512
1513 StackOffset SVEAreaOffset = {};
1514 if (FPAfterSVECalleeSaves) {
1515 // In this stack layout, the FP is in between the callee saves and other
1516 // SVE allocations.
1517 StackOffset SVECalleeSavedStack =
1518 StackOffset::getScalable(Scalable: AFI->getSVECalleeSavedStackSize());
1519 if (UseFP) {
1520 if (isFixed)
1521 SVEAreaOffset = SVECalleeSavedStack;
1522 else if (!isCSR)
1523 SVEAreaOffset = SVECalleeSavedStack - SVEStackSize;
1524 } else {
1525 if (isFixed)
1526 SVEAreaOffset = SVEStackSize;
1527 else if (isCSR)
1528 SVEAreaOffset = SVEStackSize - SVECalleeSavedStack;
1529 }
1530 } else {
1531 if (UseFP && !(isFixed || isCSR))
1532 SVEAreaOffset = -SVEStackSize;
1533 if (!UseFP && (isFixed || isCSR))
1534 SVEAreaOffset = SVEStackSize;
1535 }
1536
1537 if (UseFP) {
1538 FrameReg = RegInfo->getFrameRegister(MF);
1539 return StackOffset::getFixed(Fixed: FPOffset) + SVEAreaOffset;
1540 }
1541
1542 // Use the base pointer if we have one.
1543 if (RegInfo->hasBasePointer(MF))
1544 FrameReg = RegInfo->getBaseRegister();
1545 else {
1546 assert(!MFI.hasVarSizedObjects() &&
1547 "Can't use SP when we have var sized objects.");
1548 FrameReg = AArch64::SP;
1549 // If we're using the red zone for this function, the SP won't actually
1550 // be adjusted, so the offsets will be negative. They're also all
1551 // within range of the signed 9-bit immediate instructions.
1552 if (canUseRedZone(MF))
1553 Offset -= AFI->getLocalStackSize();
1554 }
1555
1556 return StackOffset::getFixed(Fixed: Offset) + SVEAreaOffset;
1557}
1558
1559static RegState getPrologueDeath(MachineFunction &MF, unsigned Reg) {
1560 // Do not set a kill flag on values that are also marked as live-in. This
1561 // happens with the @llvm-returnaddress intrinsic and with arguments passed in
1562 // callee saved registers.
1563 // Omitting the kill flags is conservatively correct even if the live-in
1564 // is not used after all.
1565 bool IsLiveIn = MF.getRegInfo().isLiveIn(Reg);
1566 return getKillRegState(B: !IsLiveIn);
1567}
1568
1569static bool produceCompactUnwindFrame(const AArch64FrameLowering &AFL,
1570 MachineFunction &MF) {
1571 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1572 AttributeList Attrs = MF.getFunction().getAttributes();
1573 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1574 return Subtarget.isTargetMachO() &&
1575 !(Subtarget.getTargetLowering()->supportSwiftError() &&
1576 Attrs.hasAttrSomewhere(Kind: Attribute::SwiftError)) &&
1577 MF.getFunction().getCallingConv() != CallingConv::SwiftTail &&
1578 !AFL.requiresSaveVG(MF) && !AFI->isSVECC();
1579}
1580
1581static bool invalidateWindowsRegisterPairing(bool SpillExtendedVolatile,
1582 unsigned SpillCount, unsigned Reg1,
1583 unsigned Reg2, bool NeedsWinCFI,
1584 const TargetRegisterInfo *TRI) {
1585 // If we are generating register pairs for a Windows function that requires
1586 // EH support, then pair consecutive registers only. There are no unwind
1587 // opcodes for saves/restores of non-consecutive register pairs.
1588 // The unwind opcodes are save_regp, save_regp_x, save_fregp, save_frepg_x,
1589 // save_lrpair.
1590 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
1591
1592 if (Reg2 == AArch64::FP)
1593 return true;
1594 if (!NeedsWinCFI)
1595 return false;
1596
1597 // ARM64EC introduced `save_any_regp`, which expects 16-byte alignment.
1598 // This is handled by only allowing paired spills for registers spilled at
1599 // even positions (which should be 16-byte aligned, as other GPRs/FPRs are
1600 // 8-bytes). We carve out an exception for {FP,LR}, which does not require
1601 // 16-byte alignment in the uop representation.
1602 if (TRI->getEncodingValue(Reg: Reg2) == TRI->getEncodingValue(Reg: Reg1) + 1)
1603 return SpillExtendedVolatile
1604 ? !((Reg1 == AArch64::FP && Reg2 == AArch64::LR) ||
1605 (SpillCount % 2) == 0)
1606 : false;
1607
1608 // If pairing a GPR with LR, the pair can be described by the save_lrpair
1609 // opcode. The save_lrpair opcode requires the first register to be odd.
1610 if (Reg1 >= AArch64::X19 && Reg1 <= AArch64::X27 &&
1611 (Reg1 - AArch64::X19) % 2 == 0 && Reg2 == AArch64::LR)
1612 return false;
1613 return true;
1614}
1615
1616/// Returns true if Reg1 and Reg2 cannot be paired using a ldp/stp instruction.
1617/// WindowsCFI requires that only consecutive registers can be paired.
1618/// LR and FP need to be allocated together when the frame needs to save
1619/// the frame-record. This means any other register pairing with LR is invalid.
1620static bool invalidateRegisterPairing(bool SpillExtendedVolatile,
1621 unsigned SpillCount, unsigned Reg1,
1622 unsigned Reg2, bool UsesWinAAPCS,
1623 bool NeedsWinCFI, bool NeedsFrameRecord,
1624 const TargetRegisterInfo *TRI) {
1625 if (UsesWinAAPCS)
1626 return invalidateWindowsRegisterPairing(SpillExtendedVolatile, SpillCount,
1627 Reg1, Reg2, NeedsWinCFI, TRI);
1628
1629 // If we need to store the frame record, don't pair any register
1630 // with LR other than FP.
1631 if (NeedsFrameRecord)
1632 return Reg2 == AArch64::LR;
1633
1634 return false;
1635}
1636
1637namespace {
1638
1639struct RegPairInfo {
1640 Register Reg1;
1641 Register Reg2;
1642 int FrameIdx;
1643 int Offset;
1644 enum RegType { GPR, FPR64, FPR128, PPR, ZPR, VG } Type;
1645 const TargetRegisterClass *RC;
1646
1647 RegPairInfo() = default;
1648
1649 bool isPaired() const { return Reg2.isValid(); }
1650
1651 bool isScalable() const { return Type == PPR || Type == ZPR; }
1652};
1653
1654} // end anonymous namespace
1655
1656MCRegister findFreePredicateReg(BitVector &SavedRegs) {
1657 for (unsigned PReg = AArch64::P8; PReg <= AArch64::P15; ++PReg) {
1658 if (SavedRegs.test(Idx: PReg)) {
1659 unsigned PNReg = PReg - AArch64::P0 + AArch64::PN0;
1660 return MCRegister(PNReg);
1661 }
1662 }
1663 return MCRegister();
1664}
1665
1666// The multivector LD/ST are available only for SME or SVE2p1 targets
1667bool enableMultiVectorSpillFill(const AArch64Subtarget &Subtarget,
1668 MachineFunction &MF) {
1669 if (DisableMultiVectorSpillFill)
1670 return false;
1671
1672 SMEAttrs FuncAttrs = MF.getInfo<AArch64FunctionInfo>()->getSMEFnAttrs();
1673 bool IsLocallyStreaming =
1674 FuncAttrs.hasStreamingBody() && !FuncAttrs.hasStreamingInterface();
1675
1676 // Only when in streaming mode SME2 instructions can be safely used.
1677 // It is not safe to use SME2 instructions when in streaming compatible or
1678 // locally streaming mode.
1679 return Subtarget.hasSVE2p1() ||
1680 (Subtarget.hasSME2() &&
1681 (!IsLocallyStreaming && Subtarget.isStreaming()));
1682}
1683
1684void computeCalleeSaveRegisterPairs(const AArch64FrameLowering &AFL,
1685 MachineFunction &MF,
1686 ArrayRef<CalleeSavedInfo> CSI,
1687 const TargetRegisterInfo *TRI,
1688 SmallVectorImpl<RegPairInfo> &RegPairs,
1689 bool NeedsFrameRecord) {
1690
1691 if (CSI.empty())
1692 return;
1693
1694 bool IsWindows = isTargetWindows(MF);
1695 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1696 unsigned StackHazardSize = getStackHazardSize(MF);
1697 MachineFrameInfo &MFI = MF.getFrameInfo();
1698 CallingConv::ID CC = MF.getFunction().getCallingConv();
1699 unsigned Count = CSI.size();
1700 (void)CC;
1701 // MachO's compact unwind format relies on all registers being stored in
1702 // pairs.
1703 assert((!produceCompactUnwindFrame(AFL, MF) ||
1704 CC == CallingConv::PreserveMost || CC == CallingConv::PreserveAll ||
1705 CC == CallingConv::CXX_FAST_TLS || CC == CallingConv::Win64 ||
1706 (Count & 1) == 0) &&
1707 "Odd number of callee-saved regs to spill!");
1708 int ByteOffset = AFI->getCalleeSavedStackSize();
1709 int StackFillDir = -1;
1710 int RegInc = 1;
1711 unsigned FirstReg = 0;
1712 if (IsWindows) {
1713 // For WinCFI, fill the stack from the bottom up.
1714 ByteOffset = 0;
1715 StackFillDir = 1;
1716 // As the CSI array is reversed to match PrologEpilogInserter, iterate
1717 // backwards, to pair up registers starting from lower numbered registers.
1718 RegInc = -1;
1719 FirstReg = Count - 1;
1720 }
1721
1722 bool FPAfterSVECalleeSaves = AFL.hasSVECalleeSavesAboveFrameRecord(MF);
1723 // Windows AAPCS has x9-x15 as volatile registers, x16-x17 as intra-procedural
1724 // scratch, x18 as platform reserved. However, clang has extended calling
1725 // convensions such as preserve_most and preserve_all which treat these as
1726 // CSR. As such, the ARM64 unwind uOPs bias registers by 19. We use ARM64EC
1727 // uOPs which have separate restrictions. We need to check for that.
1728 //
1729 // NOTE: we currently do not account for the D registers as LLVM does not
1730 // support non-ABI compliant D register spills.
1731 bool SpillExtendedVolatile =
1732 IsWindows && llvm::any_of(Range&: CSI, P: [](const CalleeSavedInfo &CSI) {
1733 const auto &Reg = CSI.getReg();
1734 return Reg >= AArch64::X0 && Reg <= AArch64::X18;
1735 });
1736
1737 int ZPRByteOffset = 0;
1738 int PPRByteOffset = 0;
1739 bool SplitPPRs = AFI->hasSplitSVEObjects();
1740 if (SplitPPRs) {
1741 ZPRByteOffset = AFI->getZPRCalleeSavedStackSize();
1742 PPRByteOffset = AFI->getPPRCalleeSavedStackSize();
1743 } else if (!FPAfterSVECalleeSaves) {
1744 ZPRByteOffset =
1745 AFI->getZPRCalleeSavedStackSize() + AFI->getPPRCalleeSavedStackSize();
1746 // Unused: Everything goes in ZPR space.
1747 PPRByteOffset = 0;
1748 }
1749
1750 bool NeedGapToAlignStack = AFI->hasCalleeSaveStackFreeSpace();
1751 Register LastReg = 0;
1752 bool HasCSHazardPadding = AFI->hasStackHazardSlotIndex() && !SplitPPRs;
1753
1754 auto AlignOffset = [StackFillDir](int Offset, int Align) {
1755 if (StackFillDir < 0)
1756 return alignDown(Value: Offset, Align);
1757 return alignTo(Value: Offset, Align);
1758 };
1759
1760 // When iterating backwards, the loop condition relies on unsigned wraparound.
1761 for (unsigned i = FirstReg; i < Count; i += RegInc) {
1762 RegPairInfo RPI;
1763 RPI.Reg1 = CSI[i].getReg();
1764
1765 if (AArch64::GPR64RegClass.contains(Reg: RPI.Reg1)) {
1766 RPI.Type = RegPairInfo::GPR;
1767 RPI.RC = &AArch64::GPR64RegClass;
1768 } else if (AArch64::FPR64RegClass.contains(Reg: RPI.Reg1)) {
1769 RPI.Type = RegPairInfo::FPR64;
1770 RPI.RC = &AArch64::FPR64RegClass;
1771 } else if (AArch64::FPR128RegClass.contains(Reg: RPI.Reg1)) {
1772 RPI.Type = RegPairInfo::FPR128;
1773 RPI.RC = &AArch64::FPR128RegClass;
1774 } else if (AArch64::ZPRRegClass.contains(Reg: RPI.Reg1)) {
1775 RPI.Type = RegPairInfo::ZPR;
1776 RPI.RC = &AArch64::ZPRRegClass;
1777 } else if (AArch64::PPRRegClass.contains(Reg: RPI.Reg1)) {
1778 RPI.Type = RegPairInfo::PPR;
1779 RPI.RC = &AArch64::PPRRegClass;
1780 } else if (RPI.Reg1 == AArch64::VG) {
1781 RPI.Type = RegPairInfo::VG;
1782 RPI.RC = &AArch64::FIXED_REGSRegClass;
1783 } else {
1784 llvm_unreachable("Unsupported register class.");
1785 }
1786
1787 int &ScalableByteOffset = RPI.Type == RegPairInfo::PPR && SplitPPRs
1788 ? PPRByteOffset
1789 : ZPRByteOffset;
1790
1791 // Add the stack hazard size as we transition from GPR->FPR CSRs.
1792 if (HasCSHazardPadding &&
1793 (!LastReg || !AArch64InstrInfo::isFpOrNEON(Reg: LastReg)) &&
1794 AArch64InstrInfo::isFpOrNEON(Reg: RPI.Reg1))
1795 ByteOffset += StackFillDir * StackHazardSize;
1796 LastReg = RPI.Reg1;
1797
1798 bool NeedsWinCFI = AFL.needsWinCFI(MF);
1799 int Scale = TRI->getSpillSize(RC: *RPI.RC);
1800 // Add the next reg to the pair if it is in the same register class.
1801 if (unsigned(i + RegInc) < Count && !HasCSHazardPadding) {
1802 MCRegister NextReg = CSI[i + RegInc].getReg();
1803 unsigned SpillCount = NeedsWinCFI ? FirstReg - i : i;
1804 int Aligned = AlignOffset(ByteOffset, Scale);
1805 int PairOffset = IsWindows ? Aligned : Aligned + StackFillDir * 2 * Scale;
1806 bool PairFitsImmRange =
1807 PairOffset / Scale >= -64 && PairOffset / Scale <= 63;
1808 switch (RPI.Type) {
1809 case RegPairInfo::GPR:
1810 if (AArch64::GPR64RegClass.contains(Reg: NextReg) && PairFitsImmRange &&
1811 !invalidateRegisterPairing(SpillExtendedVolatile, SpillCount,
1812 Reg1: RPI.Reg1, Reg2: NextReg, UsesWinAAPCS: IsWindows,
1813 NeedsWinCFI, NeedsFrameRecord, TRI))
1814 RPI.Reg2 = NextReg;
1815 break;
1816 case RegPairInfo::FPR64:
1817 if (AArch64::FPR64RegClass.contains(Reg: NextReg) && PairFitsImmRange &&
1818 !invalidateRegisterPairing(SpillExtendedVolatile, SpillCount,
1819 Reg1: RPI.Reg1, Reg2: NextReg, UsesWinAAPCS: IsWindows,
1820 NeedsWinCFI, NeedsFrameRecord, TRI))
1821 RPI.Reg2 = NextReg;
1822 break;
1823 case RegPairInfo::FPR128:
1824 if (AArch64::FPR128RegClass.contains(Reg: NextReg) && PairFitsImmRange)
1825 RPI.Reg2 = NextReg;
1826 break;
1827 case RegPairInfo::PPR:
1828 break;
1829 case RegPairInfo::ZPR:
1830 if (!NeedsWinCFI && AFI->getPredicateRegForFillSpill() != 0 &&
1831 ((RPI.Reg1 - AArch64::Z0) & 1) == 0 && (NextReg == RPI.Reg1 + 1)) {
1832 // Calculate offset of register pair to see if pair instruction can be
1833 // used.
1834 int Offset = (ScalableByteOffset + StackFillDir * 2 * Scale) / Scale;
1835 if ((-16 <= Offset && Offset <= 14) && (Offset % 2 == 0))
1836 RPI.Reg2 = NextReg;
1837 }
1838 break;
1839 case RegPairInfo::VG:
1840 break;
1841 }
1842 }
1843
1844 // GPRs and FPRs are saved in pairs of 64-bit regs. We expect the CSI
1845 // list to come in sorted by frame index so that we can issue the store
1846 // pair instructions directly. Assert if we see anything otherwise.
1847 //
1848 // The order of the registers in the list is controlled by
1849 // getCalleeSavedRegs(), so they will always be in-order, as well.
1850 assert((!RPI.isPaired() ||
1851 (CSI[i].getFrameIdx() + RegInc == CSI[i + RegInc].getFrameIdx())) &&
1852 "Out of order callee saved regs!");
1853
1854 assert((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg2 != AArch64::FP ||
1855 RPI.Reg1 == AArch64::LR) &&
1856 "FrameRecord must be allocated together with LR");
1857
1858 // Windows AAPCS has FP and LR reversed.
1859 assert((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg1 != AArch64::FP ||
1860 RPI.Reg2 == AArch64::LR) &&
1861 "FrameRecord must be allocated together with LR");
1862
1863 // MachO's compact unwind format relies on all registers being stored in
1864 // adjacent register pairs.
1865 assert((!produceCompactUnwindFrame(AFL, MF) ||
1866 CC == CallingConv::PreserveMost || CC == CallingConv::PreserveAll ||
1867 CC == CallingConv::CXX_FAST_TLS || CC == CallingConv::Win64 ||
1868 (RPI.isPaired() &&
1869 ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) ||
1870 RPI.Reg1 + 1 == RPI.Reg2))) &&
1871 "Callee-save registers not saved as adjacent register pair!");
1872
1873 RPI.FrameIdx = CSI[i].getFrameIdx();
1874 if (IsWindows &&
1875 RPI.isPaired()) // RPI.FrameIdx must be the lower index of the pair
1876 RPI.FrameIdx = CSI[i + RegInc].getFrameIdx();
1877
1878 // Realign the scalable offset if necessary. This is relevant when spilling
1879 // predicates on Windows.
1880 if (RPI.isScalable() && ScalableByteOffset % Scale != 0)
1881 ScalableByteOffset = AlignOffset(ScalableByteOffset, Scale);
1882
1883 // Realign the fixed offset if necessary. This is relevant when spilling Q
1884 // registers after spilling an odd amount of X registers.
1885 if (!RPI.isScalable() && ByteOffset % Scale != 0)
1886 ByteOffset = AlignOffset(ByteOffset, Scale);
1887
1888 int OffsetPre = RPI.isScalable() ? ScalableByteOffset : ByteOffset;
1889 assert(OffsetPre % Scale == 0);
1890
1891 if (RPI.isScalable())
1892 ScalableByteOffset += StackFillDir * (RPI.isPaired() ? 2 * Scale : Scale);
1893 else
1894 ByteOffset += StackFillDir * (RPI.isPaired() ? 2 * Scale : Scale);
1895
1896 // Swift's async context is directly before FP, so allocate an extra
1897 // 8 bytes for it.
1898 if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
1899 ((!IsWindows && RPI.Reg2 == AArch64::FP) ||
1900 (IsWindows && RPI.Reg2 == AArch64::LR)))
1901 ByteOffset += StackFillDir * 8;
1902
1903 // Round up size of non-pair to pair size if we need to pad the
1904 // callee-save area to ensure 16-byte alignment.
1905 if (NeedGapToAlignStack && !IsWindows && !RPI.isScalable() &&
1906 RPI.Type != RegPairInfo::FPR128 && !RPI.isPaired() &&
1907 ByteOffset % 16 != 0) {
1908 ByteOffset += 8 * StackFillDir;
1909 assert(MFI.getObjectAlign(RPI.FrameIdx) <= Align(16));
1910 // A stack frame with a gap looks like this, bottom up:
1911 // d9, d8. x21, gap, x20, x19.
1912 // Set extra alignment on the x21 object to create the gap above it.
1913 MFI.setObjectAlignment(ObjectIdx: RPI.FrameIdx, Alignment: Align(16));
1914 NeedGapToAlignStack = false;
1915 }
1916
1917 int OffsetPost = RPI.isScalable() ? ScalableByteOffset : ByteOffset;
1918 assert(OffsetPost % Scale == 0);
1919 // If filling top down (default), we want the offset after incrementing it.
1920 // If filling bottom up (WinCFI) we need the original offset.
1921 int Offset = IsWindows ? OffsetPre : OffsetPost;
1922
1923 // The FP, LR pair goes 8 bytes into our expanded 24-byte slot so that the
1924 // Swift context can directly precede FP.
1925 if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
1926 ((!IsWindows && RPI.Reg2 == AArch64::FP) ||
1927 (IsWindows && RPI.Reg2 == AArch64::LR)))
1928 Offset += 8;
1929 RPI.Offset = Offset / Scale;
1930
1931 assert((!RPI.isPaired() ||
1932 (!RPI.isScalable() && RPI.Offset >= -64 && RPI.Offset <= 63) ||
1933 (RPI.isScalable() && RPI.Offset >= -256 && RPI.Offset <= 255)) &&
1934 "Offset out of bounds for LDP/STP immediate");
1935
1936 auto isFrameRecord = [&] {
1937 if (RPI.isPaired())
1938 return IsWindows ? RPI.Reg1 == AArch64::FP && RPI.Reg2 == AArch64::LR
1939 : RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP;
1940 // Otherwise, look for the frame record as two unpaired registers. This is
1941 // needed for -aarch64-stack-hazard-size=<val>, which disables register
1942 // pairing (as the padding may be too large for the LDP/STP offset). Note:
1943 // On Windows, this check works out as current reg == FP, next reg == LR,
1944 // and on other platforms current reg == FP, previous reg == LR. This
1945 // works out as the correct pre-increment or post-increment offsets
1946 // respectively.
1947 return i > 0 && RPI.Reg1 == AArch64::FP &&
1948 CSI[i - 1].getReg() == AArch64::LR;
1949 };
1950
1951 // Save the offset to frame record so that the FP register can point to the
1952 // innermost frame record (spilled FP and LR registers).
1953 if (NeedsFrameRecord && isFrameRecord())
1954 AFI->setCalleeSaveBaseToFrameRecordOffset(Offset);
1955
1956 RegPairs.push_back(Elt: RPI);
1957 if (RPI.isPaired())
1958 i += RegInc;
1959 }
1960 if (IsWindows) {
1961 // If we need an alignment gap in the stack, align the topmost stack
1962 // object. A stack frame with a gap looks like this, bottom up:
1963 // x19, d8. d9, gap.
1964 // Set extra alignment on the topmost stack object (the first element in
1965 // CSI, which goes top down), to create the gap above it.
1966 if (AFI->hasCalleeSaveStackFreeSpace())
1967 MFI.setObjectAlignment(ObjectIdx: CSI[0].getFrameIdx(), Alignment: Align(16));
1968 // We iterated bottom up over the registers; flip RegPairs back to top
1969 // down order.
1970 std::reverse(first: RegPairs.begin(), last: RegPairs.end());
1971 }
1972}
1973
1974bool AArch64FrameLowering::spillCalleeSavedRegisters(
1975 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
1976 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
1977 MachineFunction &MF = *MBB.getParent();
1978 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
1979 auto &TLI = *Subtarget.getTargetLowering();
1980 const AArch64InstrInfo &TII = *Subtarget.getInstrInfo();
1981 bool NeedsWinCFI = needsWinCFI(MF);
1982 DebugLoc DL;
1983 SmallVector<RegPairInfo, 8> RegPairs;
1984
1985 computeCalleeSaveRegisterPairs(AFL: *this, MF, CSI, TRI, RegPairs, NeedsFrameRecord: hasFP(MF));
1986
1987 MachineRegisterInfo &MRI = MF.getRegInfo();
1988 // Refresh the reserved regs in case there are any potential changes since the
1989 // last freeze.
1990 MRI.freezeReservedRegs();
1991
1992 if (homogeneousPrologEpilog(MF)) {
1993 auto MIB = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AArch64::HOM_Prolog))
1994 .setMIFlag(MachineInstr::FrameSetup);
1995
1996 for (auto &RPI : RegPairs) {
1997 MIB.addReg(RegNo: RPI.Reg1);
1998 MIB.addReg(RegNo: RPI.Reg2);
1999
2000 // Update register live in.
2001 if (!MRI.isReserved(PhysReg: RPI.Reg1))
2002 MBB.addLiveIn(PhysReg: RPI.Reg1);
2003 if (RPI.isPaired() && !MRI.isReserved(PhysReg: RPI.Reg2))
2004 MBB.addLiveIn(PhysReg: RPI.Reg2);
2005 }
2006 return true;
2007 }
2008 bool PTrueCreated = false;
2009 for (const RegPairInfo &RPI : llvm::reverse(C&: RegPairs)) {
2010 Register Reg1 = RPI.Reg1;
2011 Register Reg2 = RPI.Reg2;
2012 unsigned StrOpc;
2013
2014 // Issue sequence of spills for cs regs. The first spill may be converted
2015 // to a pre-decrement store later by emitPrologue if the callee-save stack
2016 // area allocation can't be combined with the local stack area allocation.
2017 // For example:
2018 // stp x22, x21, [sp, #0] // addImm(+0)
2019 // stp x20, x19, [sp, #16] // addImm(+2)
2020 // stp fp, lr, [sp, #32] // addImm(+4)
2021 // Rationale: This sequence saves uop updates compared to a sequence of
2022 // pre-increment spills like stp xi,xj,[sp,#-16]!
2023 // Note: Similar rationale and sequence for restores in epilog.
2024 unsigned Size = TRI->getSpillSize(RC: *RPI.RC);
2025 Align Alignment = TRI->getSpillAlign(RC: *RPI.RC);
2026 switch (RPI.Type) {
2027 case RegPairInfo::GPR:
2028 StrOpc = RPI.isPaired() ? AArch64::STPXi : AArch64::STRXui;
2029 break;
2030 case RegPairInfo::FPR64:
2031 StrOpc = RPI.isPaired() ? AArch64::STPDi : AArch64::STRDui;
2032 break;
2033 case RegPairInfo::FPR128:
2034 StrOpc = RPI.isPaired() ? AArch64::STPQi : AArch64::STRQui;
2035 break;
2036 case RegPairInfo::ZPR:
2037 StrOpc = RPI.isPaired() ? AArch64::ST1B_2Z_IMM : AArch64::STR_ZXI;
2038 break;
2039 case RegPairInfo::PPR:
2040 StrOpc = AArch64::STR_PXI;
2041 break;
2042 case RegPairInfo::VG:
2043 StrOpc = AArch64::STRXui;
2044 break;
2045 }
2046
2047 Register X0Scratch;
2048 llvm::scope_exit RestoreX0([&] {
2049 if (X0Scratch.isValid())
2050 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: AArch64::X0)
2051 .addReg(RegNo: X0Scratch)
2052 .setMIFlag(MachineInstr::FrameSetup);
2053 });
2054
2055 if (Reg1 == AArch64::VG) {
2056 // Find an available register to store value of VG to.
2057 Reg1 = findScratchNonCalleeSaveRegister(MBB: &MBB, HasCall: true);
2058 assert(Reg1.isValid());
2059 if (MF.getSubtarget<AArch64Subtarget>().hasSVE()) {
2060 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AArch64::CNTD_XPiI), DestReg: Reg1)
2061 .addImm(Val: 31)
2062 .addImm(Val: 1)
2063 .setMIFlag(MachineInstr::FrameSetup);
2064 } else {
2065 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
2066 if (any_of(Range: MBB.liveins(),
2067 P: [&STI](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
2068 return STI.getRegisterInfo()->isSuperOrSubRegisterEq(
2069 RegA: AArch64::X0, RegB: LiveIn.PhysReg);
2070 })) {
2071 X0Scratch = Reg1;
2072 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: X0Scratch)
2073 .addReg(RegNo: AArch64::X0)
2074 .setMIFlag(MachineInstr::FrameSetup);
2075 }
2076
2077 RTLIB::Libcall LC = RTLIB::SMEABI_GET_CURRENT_VG;
2078 const uint32_t *RegMask =
2079 TRI->getCallPreservedMask(MF, TLI.getLibcallCallingConv(Call: LC));
2080 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AArch64::BL))
2081 .addExternalSymbol(FnName: TLI.getLibcallName(Call: LC))
2082 .addRegMask(Mask: RegMask)
2083 .addReg(RegNo: AArch64::X0, Flags: RegState::ImplicitDefine)
2084 .setMIFlag(MachineInstr::FrameSetup);
2085 Reg1 = AArch64::X0;
2086 }
2087 }
2088
2089 LLVM_DEBUG({
2090 dbgs() << "CSR spill: (" << printReg(Reg1, TRI);
2091 if (RPI.isPaired())
2092 dbgs() << ", " << printReg(Reg2, TRI);
2093 dbgs() << ") -> fi#(" << RPI.FrameIdx;
2094 if (RPI.isPaired())
2095 dbgs() << ", " << RPI.FrameIdx + 1;
2096 dbgs() << ")\n";
2097 });
2098
2099 assert((!isTargetWindows(MF) ||
2100 !(Reg1 == AArch64::LR && Reg2 == AArch64::FP)) &&
2101 "Windows unwdinding requires a consecutive (FP,LR) pair");
2102 // Windows unwind codes require consecutive registers if registers are
2103 // paired. Make the switch here, so that the code below will save (x,x+1)
2104 // and not (x+1,x).
2105 unsigned FrameIdxReg1 = RPI.FrameIdx;
2106 unsigned FrameIdxReg2 = RPI.FrameIdx + 1;
2107 if (isTargetWindows(MF) && RPI.isPaired()) {
2108 std::swap(a&: Reg1, b&: Reg2);
2109 std::swap(a&: FrameIdxReg1, b&: FrameIdxReg2);
2110 }
2111
2112 if (RPI.isPaired() && RPI.isScalable()) {
2113 [[maybe_unused]] const AArch64Subtarget &Subtarget =
2114 MF.getSubtarget<AArch64Subtarget>();
2115 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2116 unsigned PnReg = AFI->getPredicateRegForFillSpill();
2117 assert((PnReg != 0 && enableMultiVectorSpillFill(Subtarget, MF)) &&
2118 "Expects SVE2.1 or SME2 target and a predicate register");
2119#ifdef EXPENSIVE_CHECKS
2120 auto IsPPR = [](const RegPairInfo &c) {
2121 return c.Reg1 == RegPairInfo::PPR;
2122 };
2123 auto PPRBegin = std::find_if(RegPairs.begin(), RegPairs.end(), IsPPR);
2124 auto IsZPR = [](const RegPairInfo &c) {
2125 return c.Type == RegPairInfo::ZPR;
2126 };
2127 auto ZPRBegin = std::find_if(RegPairs.begin(), RegPairs.end(), IsZPR);
2128 assert(!(PPRBegin < ZPRBegin) &&
2129 "Expected callee save predicate to be handled first");
2130#endif
2131 if (!PTrueCreated) {
2132 PTrueCreated = true;
2133 BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: AArch64::PTRUE_C_B), DestReg: PnReg)
2134 .setMIFlags(MachineInstr::FrameSetup);
2135 }
2136 MachineInstrBuilder MIB = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: StrOpc));
2137 if (!MRI.isReserved(PhysReg: Reg1))
2138 MBB.addLiveIn(PhysReg: Reg1);
2139 if (!MRI.isReserved(PhysReg: Reg2))
2140 MBB.addLiveIn(PhysReg: Reg2);
2141 MIB.addReg(/*PairRegs*/ RegNo: AArch64::Z0_Z1 + (RPI.Reg1 - AArch64::Z0));
2142 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2143 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg2),
2144 F: MachineMemOperand::MOStore, Size, BaseAlignment: Alignment));
2145 MIB.addReg(RegNo: PnReg);
2146 MIB.addReg(RegNo: AArch64::SP)
2147 .addImm(Val: RPI.Offset / 2) // [sp, #imm*2*vscale],
2148 // where 2*vscale is implicit
2149 .setMIFlag(MachineInstr::FrameSetup);
2150 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2151 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg1),
2152 F: MachineMemOperand::MOStore, Size, BaseAlignment: Alignment));
2153 if (NeedsWinCFI)
2154 insertSEH(MBBI: MIB, TII, Flag: MachineInstr::FrameSetup);
2155 } else { // The code when the pair of ZReg is not present
2156 MachineInstrBuilder MIB = BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: StrOpc));
2157 if (!MRI.isReserved(PhysReg: Reg1))
2158 MBB.addLiveIn(PhysReg: Reg1);
2159 if (RPI.isPaired()) {
2160 if (!MRI.isReserved(PhysReg: Reg2))
2161 MBB.addLiveIn(PhysReg: Reg2);
2162 MIB.addReg(RegNo: Reg2, Flags: getPrologueDeath(MF, Reg: Reg2));
2163 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2164 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg2),
2165 F: MachineMemOperand::MOStore, Size, BaseAlignment: Alignment));
2166 }
2167 MIB.addReg(RegNo: Reg1, Flags: getPrologueDeath(MF, Reg: Reg1))
2168 .addReg(RegNo: AArch64::SP)
2169 .addImm(Val: RPI.Offset) // [sp, #offset*vscale],
2170 // where factor*vscale is implicit
2171 .setMIFlag(MachineInstr::FrameSetup);
2172 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2173 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg1),
2174 F: MachineMemOperand::MOStore, Size, BaseAlignment: Alignment));
2175 if (NeedsWinCFI)
2176 insertSEH(MBBI: MIB, TII, Flag: MachineInstr::FrameSetup);
2177 }
2178 // Update the StackIDs of the SVE stack slots.
2179 MachineFrameInfo &MFI = MF.getFrameInfo();
2180 if (RPI.Type == RegPairInfo::ZPR) {
2181 MFI.setStackID(ObjectIdx: FrameIdxReg1, ID: TargetStackID::ScalableVector);
2182 if (RPI.isPaired())
2183 MFI.setStackID(ObjectIdx: FrameIdxReg2, ID: TargetStackID::ScalableVector);
2184 } else if (RPI.Type == RegPairInfo::PPR) {
2185 MFI.setStackID(ObjectIdx: FrameIdxReg1, ID: TargetStackID::ScalablePredicateVector);
2186 if (RPI.isPaired())
2187 MFI.setStackID(ObjectIdx: FrameIdxReg2, ID: TargetStackID::ScalablePredicateVector);
2188 }
2189 }
2190 return true;
2191}
2192
2193bool AArch64FrameLowering::restoreCalleeSavedRegisters(
2194 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
2195 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
2196 MachineFunction &MF = *MBB.getParent();
2197 const AArch64InstrInfo &TII =
2198 *MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
2199 DebugLoc DL;
2200 SmallVector<RegPairInfo, 8> RegPairs;
2201 bool NeedsWinCFI = needsWinCFI(MF);
2202
2203 if (MBBI != MBB.end())
2204 DL = MBBI->getDebugLoc();
2205
2206 computeCalleeSaveRegisterPairs(AFL: *this, MF, CSI, TRI, RegPairs, NeedsFrameRecord: hasFP(MF));
2207 if (homogeneousPrologEpilog(MF, Exit: &MBB)) {
2208 auto MIB = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AArch64::HOM_Epilog))
2209 .setMIFlag(MachineInstr::FrameDestroy);
2210 for (auto &RPI : RegPairs) {
2211 MIB.addReg(RegNo: RPI.Reg1, Flags: RegState::Define);
2212 MIB.addReg(RegNo: RPI.Reg2, Flags: RegState::Define);
2213 }
2214 return true;
2215 }
2216
2217 // For performance reasons restore SVE register in increasing order
2218 auto IsPPR = [](const RegPairInfo &c) { return c.Type == RegPairInfo::PPR; };
2219 auto PPRBegin = llvm::find_if(Range&: RegPairs, P: IsPPR);
2220 auto PPREnd = std::find_if_not(first: PPRBegin, last: RegPairs.end(), pred: IsPPR);
2221 std::reverse(first: PPRBegin, last: PPREnd);
2222 auto IsZPR = [](const RegPairInfo &c) { return c.Type == RegPairInfo::ZPR; };
2223 auto ZPRBegin = llvm::find_if(Range&: RegPairs, P: IsZPR);
2224 auto ZPREnd = std::find_if_not(first: ZPRBegin, last: RegPairs.end(), pred: IsZPR);
2225 std::reverse(first: ZPRBegin, last: ZPREnd);
2226
2227 bool PTrueCreated = false;
2228 for (const RegPairInfo &RPI : RegPairs) {
2229 Register Reg1 = RPI.Reg1;
2230 Register Reg2 = RPI.Reg2;
2231
2232 // Issue sequence of restores for cs regs. The last restore may be converted
2233 // to a post-increment load later by emitEpilogue if the callee-save stack
2234 // area allocation can't be combined with the local stack area allocation.
2235 // For example:
2236 // ldp fp, lr, [sp, #32] // addImm(+4)
2237 // ldp x20, x19, [sp, #16] // addImm(+2)
2238 // ldp x22, x21, [sp, #0] // addImm(+0)
2239 // Note: see comment in spillCalleeSavedRegisters()
2240 unsigned LdrOpc;
2241 unsigned Size = TRI->getSpillSize(RC: *RPI.RC);
2242 Align Alignment = TRI->getSpillAlign(RC: *RPI.RC);
2243 switch (RPI.Type) {
2244 case RegPairInfo::GPR:
2245 LdrOpc = RPI.isPaired() ? AArch64::LDPXi : AArch64::LDRXui;
2246 break;
2247 case RegPairInfo::FPR64:
2248 LdrOpc = RPI.isPaired() ? AArch64::LDPDi : AArch64::LDRDui;
2249 break;
2250 case RegPairInfo::FPR128:
2251 LdrOpc = RPI.isPaired() ? AArch64::LDPQi : AArch64::LDRQui;
2252 break;
2253 case RegPairInfo::ZPR:
2254 LdrOpc = RPI.isPaired() ? AArch64::LD1B_2Z_IMM : AArch64::LDR_ZXI;
2255 break;
2256 case RegPairInfo::PPR:
2257 LdrOpc = AArch64::LDR_PXI;
2258 break;
2259 case RegPairInfo::VG:
2260 continue;
2261 }
2262 LLVM_DEBUG({
2263 dbgs() << "CSR restore: (" << printReg(Reg1, TRI);
2264 if (RPI.isPaired())
2265 dbgs() << ", " << printReg(Reg2, TRI);
2266 dbgs() << ") -> fi#(" << RPI.FrameIdx;
2267 if (RPI.isPaired())
2268 dbgs() << ", " << RPI.FrameIdx + 1;
2269 dbgs() << ")\n";
2270 });
2271
2272 // Windows unwind codes require consecutive registers if registers are
2273 // paired. Make the switch here, so that the code below will save (x,x+1)
2274 // and not (x+1,x).
2275 unsigned FrameIdxReg1 = RPI.FrameIdx;
2276 unsigned FrameIdxReg2 = RPI.FrameIdx + 1;
2277 if (isTargetWindows(MF) && RPI.isPaired()) {
2278 std::swap(a&: Reg1, b&: Reg2);
2279 std::swap(a&: FrameIdxReg1, b&: FrameIdxReg2);
2280 }
2281
2282 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2283 if (RPI.isPaired() && RPI.isScalable()) {
2284 [[maybe_unused]] const AArch64Subtarget &Subtarget =
2285 MF.getSubtarget<AArch64Subtarget>();
2286 unsigned PnReg = AFI->getPredicateRegForFillSpill();
2287 assert((PnReg != 0 && enableMultiVectorSpillFill(Subtarget, MF)) &&
2288 "Expects SVE2.1 or SME2 target and a predicate register");
2289#ifdef EXPENSIVE_CHECKS
2290 assert(!(PPRBegin < ZPRBegin) &&
2291 "Expected callee save predicate to be handled first");
2292#endif
2293 if (!PTrueCreated) {
2294 PTrueCreated = true;
2295 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AArch64::PTRUE_C_B), DestReg: PnReg)
2296 .setMIFlags(MachineInstr::FrameDestroy);
2297 }
2298 MachineInstrBuilder MIB = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: LdrOpc));
2299 MIB.addReg(/*PairRegs*/ RegNo: AArch64::Z0_Z1 + (RPI.Reg1 - AArch64::Z0),
2300 Flags: getDefRegState(B: true));
2301 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2302 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg2),
2303 F: MachineMemOperand::MOLoad, Size, BaseAlignment: Alignment));
2304 MIB.addReg(RegNo: PnReg);
2305 MIB.addReg(RegNo: AArch64::SP)
2306 .addImm(Val: RPI.Offset / 2) // [sp, #imm*2*vscale]
2307 // where 2*vscale is implicit
2308 .setMIFlag(MachineInstr::FrameDestroy);
2309 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2310 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg1),
2311 F: MachineMemOperand::MOLoad, Size, BaseAlignment: Alignment));
2312 if (NeedsWinCFI)
2313 insertSEH(MBBI: MIB, TII, Flag: MachineInstr::FrameDestroy);
2314 } else {
2315 MachineInstrBuilder MIB = BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: LdrOpc));
2316 if (RPI.isPaired()) {
2317 MIB.addReg(RegNo: Reg2, Flags: getDefRegState(B: true));
2318 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2319 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg2),
2320 F: MachineMemOperand::MOLoad, Size, BaseAlignment: Alignment));
2321 }
2322 MIB.addReg(RegNo: Reg1, Flags: getDefRegState(B: true));
2323 MIB.addReg(RegNo: AArch64::SP)
2324 .addImm(Val: RPI.Offset) // [sp, #offset*vscale]
2325 // where factor*vscale is implicit
2326 .setMIFlag(MachineInstr::FrameDestroy);
2327 MIB.addMemOperand(MMO: MF.getMachineMemOperand(
2328 PtrInfo: MachinePointerInfo::getFixedStack(MF, FI: FrameIdxReg1),
2329 F: MachineMemOperand::MOLoad, Size, BaseAlignment: Alignment));
2330 if (NeedsWinCFI)
2331 insertSEH(MBBI: MIB, TII, Flag: MachineInstr::FrameDestroy);
2332 }
2333 }
2334 return true;
2335}
2336
2337// Return the FrameID for a MMO.
2338static std::optional<int> getMMOFrameID(MachineMemOperand *MMO,
2339 const MachineFrameInfo &MFI) {
2340 auto *PSV =
2341 dyn_cast_or_null<FixedStackPseudoSourceValue>(Val: MMO->getPseudoValue());
2342 if (PSV)
2343 return std::optional<int>(PSV->getFrameIndex());
2344
2345 if (MMO->getValue()) {
2346 if (auto *Al = dyn_cast<AllocaInst>(Val: getUnderlyingObject(V: MMO->getValue()))) {
2347 for (int FI = MFI.getObjectIndexBegin(); FI < MFI.getObjectIndexEnd();
2348 FI++)
2349 if (MFI.getObjectAllocation(ObjectIdx: FI) == Al)
2350 return FI;
2351 }
2352 }
2353
2354 return std::nullopt;
2355}
2356
2357// Return the FrameID for a Load/Store instruction by looking at the first MMO.
2358static std::optional<int> getLdStFrameID(const MachineInstr &MI,
2359 const MachineFrameInfo &MFI) {
2360 if (!MI.mayLoadOrStore() || MI.getNumMemOperands() < 1)
2361 return std::nullopt;
2362
2363 return getMMOFrameID(MMO: *MI.memoperands_begin(), MFI);
2364}
2365
2366// Returns true if the LDST MachineInstr \p MI is a PPR access.
2367static bool isPPRAccess(const MachineInstr &MI) {
2368 return AArch64::PPRRegClass.contains(Reg: MI.getOperand(i: 0).getReg());
2369}
2370
2371// Check if a Hazard slot is needed for the current function, and if so create
2372// one for it. The index is stored in AArch64FunctionInfo->StackHazardSlotIndex,
2373// which can be used to determine if any hazard padding is needed.
2374void AArch64FrameLowering::determineStackHazardSlot(
2375 MachineFunction &MF, BitVector &SavedRegs) const {
2376 unsigned StackHazardSize = getStackHazardSize(MF);
2377 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
2378 if (StackHazardSize == 0 || StackHazardSize % 16 != 0 ||
2379 AFI->hasStackHazardSlotIndex())
2380 return;
2381
2382 // Stack hazards are only needed in streaming functions.
2383 SMEAttrs Attrs = AFI->getSMEFnAttrs();
2384 if (!StackHazardInNonStreaming && Attrs.hasNonStreamingInterfaceAndBody())
2385 return;
2386
2387 MachineFrameInfo &MFI = MF.getFrameInfo();
2388
2389 // Add a hazard slot if there are any CSR FPR registers, or are any fp-only
2390 // stack objects.
2391 bool HasFPRCSRs = any_of(Range: SavedRegs.set_bits(), P: [](unsigned Reg) {
2392 return AArch64::FPR64RegClass.contains(Reg) ||
2393 AArch64::FPR128RegClass.contains(Reg) ||
2394 AArch64::ZPRRegClass.contains(Reg);
2395 });
2396 bool HasPPRCSRs = any_of(Range: SavedRegs.set_bits(), P: [](unsigned Reg) {
2397 return AArch64::PPRRegClass.contains(Reg);
2398 });
2399 bool HasFPRStackObjects = false;
2400 bool HasPPRStackObjects = false;
2401 if (!HasFPRCSRs || SplitSVEObjects) {
2402 enum SlotType : uint8_t {
2403 Unknown = 0,
2404 ZPRorFPR = 1 << 0,
2405 PPR = 1 << 1,
2406 GPR = 1 << 2,
2407 LLVM_MARK_AS_BITMASK_ENUM(GPR)
2408 };
2409
2410 // Find stack slots solely used for one kind of register (ZPR, PPR, etc.),
2411 // based on the kinds of accesses used in the function.
2412 SmallVector<SlotType> SlotTypes(MFI.getObjectIndexEnd(), SlotType::Unknown);
2413 for (auto &MBB : MF) {
2414 for (auto &MI : MBB) {
2415 std::optional<int> FI = getLdStFrameID(MI, MFI);
2416 if (!FI || FI < 0 || FI > int(SlotTypes.size()))
2417 continue;
2418 if (MFI.hasScalableStackID(ObjectIdx: *FI)) {
2419 SlotTypes[*FI] |=
2420 isPPRAccess(MI) ? SlotType::PPR : SlotType::ZPRorFPR;
2421 } else {
2422 SlotTypes[*FI] |= AArch64InstrInfo::isFpOrNEON(MI)
2423 ? SlotType::ZPRorFPR
2424 : SlotType::GPR;
2425 }
2426 }
2427 }
2428
2429 for (int FI = 0; FI < int(SlotTypes.size()); ++FI) {
2430 HasFPRStackObjects |= SlotTypes[FI] == SlotType::ZPRorFPR;
2431 // For SplitSVEObjects remember that this stack slot is a predicate, this
2432 // will be needed later when determining the frame layout.
2433 if (SlotTypes[FI] == SlotType::PPR) {
2434 MFI.setStackID(ObjectIdx: FI, ID: TargetStackID::ScalablePredicateVector);
2435 HasPPRStackObjects = true;
2436 }
2437 }
2438 }
2439
2440 if (HasFPRCSRs || HasFPRStackObjects) {
2441 int ID = MFI.CreateStackObject(Size: StackHazardSize, Alignment: Align(16), isSpillSlot: false);
2442 LLVM_DEBUG(dbgs() << "Created Hazard slot at " << ID << " size "
2443 << StackHazardSize << "\n");
2444 AFI->setStackHazardSlotIndex(ID);
2445 }
2446
2447 if (!AFI->hasStackHazardSlotIndex())
2448 return;
2449
2450 if (SplitSVEObjects) {
2451 CallingConv::ID CC = MF.getFunction().getCallingConv();
2452 if (AFI->isSVECC() || CC == CallingConv::AArch64_SVE_VectorCall) {
2453 AFI->setSplitSVEObjects(true);
2454 LLVM_DEBUG(dbgs() << "Using SplitSVEObjects for SVE CC function\n");
2455 return;
2456 }
2457
2458 // We only use SplitSVEObjects in non-SVE CC functions if there's a
2459 // possibility of a stack hazard between PPRs and ZPRs/FPRs.
2460 LLVM_DEBUG(dbgs() << "Determining if SplitSVEObjects should be used in "
2461 "non-SVE CC function...\n");
2462
2463 // If another calling convention is explicitly set FPRs can't be promoted to
2464 // ZPR callee-saves.
2465 if (!is_contained(Set: {CallingConv::C, CallingConv::Fast}, Element: CC)) {
2466 LLVM_DEBUG(
2467 dbgs()
2468 << "Calling convention is not supported with SplitSVEObjects\n");
2469 return;
2470 }
2471
2472 if (!HasPPRCSRs && !HasPPRStackObjects) {
2473 LLVM_DEBUG(
2474 dbgs() << "Not using SplitSVEObjects as no PPRs are on the stack\n");
2475 return;
2476 }
2477
2478 if (!HasFPRCSRs && !HasFPRStackObjects) {
2479 LLVM_DEBUG(
2480 dbgs()
2481 << "Not using SplitSVEObjects as no FPRs or ZPRs are on the stack\n");
2482 return;
2483 }
2484
2485 [[maybe_unused]] const AArch64Subtarget &Subtarget =
2486 MF.getSubtarget<AArch64Subtarget>();
2487 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
2488 "Expected SVE to be available for PPRs");
2489
2490 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2491 // With SplitSVEObjects the CS hazard padding is placed between the
2492 // PPRs and ZPRs. If there are any FPR CS there would be a hazard between
2493 // them and the CS GRPs. Avoid this by promoting all FPR CS to ZPRs.
2494 BitVector FPRZRegs(SavedRegs.size());
2495 for (size_t Reg = 0, E = SavedRegs.size(); HasFPRCSRs && Reg < E; ++Reg) {
2496 BitVector::reference RegBit = SavedRegs[Reg];
2497 if (!RegBit)
2498 continue;
2499 unsigned SubRegIdx = 0;
2500 if (AArch64::FPR64RegClass.contains(Reg))
2501 SubRegIdx = AArch64::dsub;
2502 else if (AArch64::FPR128RegClass.contains(Reg))
2503 SubRegIdx = AArch64::zsub;
2504 else
2505 continue;
2506 // Clear the bit for the FPR save.
2507 RegBit = false;
2508 // Mark that we should save the corresponding ZPR.
2509 Register ZReg =
2510 TRI->getMatchingSuperReg(Reg, SubIdx: SubRegIdx, RC: &AArch64::ZPRRegClass);
2511 FPRZRegs.set(ZReg);
2512 }
2513 SavedRegs |= FPRZRegs;
2514
2515 AFI->setSplitSVEObjects(true);
2516 LLVM_DEBUG(dbgs() << "SplitSVEObjects enabled!\n");
2517 }
2518}
2519
2520void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
2521 BitVector &SavedRegs,
2522 RegScavenger *RS) const {
2523 // All calls are tail calls in GHC calling conv, and functions have no
2524 // prologue/epilogue.
2525 if (MF.getFunction().getCallingConv() == CallingConv::GHC)
2526 return;
2527
2528 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
2529
2530 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
2531 const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
2532 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2533 Register UnspilledCSGPR;
2534 Register UnspilledCSGPRPaired;
2535
2536 MachineFrameInfo &MFI = MF.getFrameInfo();
2537 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
2538
2539 MCRegister BasePointerReg =
2540 RegInfo->hasBasePointer(MF) ? RegInfo->getBaseRegister() : MCRegister();
2541
2542 Register ExtraCSSpill;
2543 bool HasUnpairedGPR64 = false;
2544 bool HasPairZReg = false;
2545 BitVector UserReservedRegs = RegInfo->getUserReservedRegs(MF);
2546 BitVector ReservedRegs = RegInfo->getReservedRegs(MF);
2547
2548 // Figure out which callee-saved registers to save/restore.
2549 for (unsigned i = 0; CSRegs[i]; ++i) {
2550 const MCRegister Reg = CSRegs[i];
2551
2552 // Add the base pointer register to SavedRegs if it is callee-save.
2553 if (Reg == BasePointerReg)
2554 SavedRegs.set(Reg);
2555
2556 // Don't save manually reserved registers set through +reserve-x#i,
2557 // even for callee-saved registers, as per GCC's behavior.
2558 if (UserReservedRegs[Reg]) {
2559 SavedRegs.reset(Idx: Reg);
2560 continue;
2561 }
2562
2563 bool RegUsed = SavedRegs.test(Idx: Reg);
2564 MCRegister PairedReg;
2565 const bool RegIsGPR64 = AArch64::GPR64RegClass.contains(Reg);
2566 if (RegIsGPR64 || AArch64::FPR64RegClass.contains(Reg) ||
2567 AArch64::FPR128RegClass.contains(Reg)) {
2568 // Compensate for odd numbers of GP CSRs.
2569 // For now, all the known cases of odd number of CSRs are of GPRs.
2570 if (HasUnpairedGPR64)
2571 PairedReg = CSRegs[i % 2 == 0 ? i - 1 : i + 1];
2572 else
2573 PairedReg = CSRegs[i ^ 1];
2574 }
2575
2576 // If the function requires all the GP registers to save (SavedRegs),
2577 // and there are an odd number of GP CSRs at the same time (CSRegs),
2578 // PairedReg could be in a different register class from Reg, which would
2579 // lead to a FPR (usually D8) accidentally being marked saved.
2580 if (RegIsGPR64 && !AArch64::GPR64RegClass.contains(Reg: PairedReg)) {
2581 PairedReg = Register();
2582 HasUnpairedGPR64 = true;
2583 }
2584 assert(!PairedReg.isValid() ||
2585 AArch64::GPR64RegClass.contains(Reg, PairedReg) ||
2586 AArch64::FPR64RegClass.contains(Reg, PairedReg) ||
2587 AArch64::FPR128RegClass.contains(Reg, PairedReg));
2588
2589 if (!RegUsed) {
2590 if (AArch64::GPR64RegClass.contains(Reg) && !ReservedRegs[Reg]) {
2591 UnspilledCSGPR = Reg;
2592 UnspilledCSGPRPaired = PairedReg;
2593 }
2594 continue;
2595 }
2596
2597 // MachO's compact unwind format relies on all registers being stored in
2598 // pairs.
2599 // FIXME: the usual format is actually better if unwinding isn't needed.
2600 if (producePairRegisters(MF) && PairedReg.isValid() &&
2601 !SavedRegs.test(Idx: PairedReg)) {
2602 SavedRegs.set(PairedReg);
2603 if (AArch64::GPR64RegClass.contains(Reg: PairedReg) &&
2604 !ReservedRegs[PairedReg])
2605 ExtraCSSpill = PairedReg;
2606 }
2607 // Check if there is a pair of ZRegs, so it can select PReg for spill/fill
2608 HasPairZReg |= (AArch64::ZPRRegClass.contains(Reg1: Reg, Reg2: CSRegs[i ^ 1]) &&
2609 SavedRegs.test(Idx: CSRegs[i ^ 1]));
2610 }
2611
2612 if (HasPairZReg && enableMultiVectorSpillFill(Subtarget, MF)) {
2613 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2614 // Find a suitable predicate register for the multi-vector spill/fill
2615 // instructions.
2616 MCRegister PnReg = findFreePredicateReg(SavedRegs);
2617 if (PnReg.isValid())
2618 AFI->setPredicateRegForFillSpill(PnReg);
2619 // If no free callee-save has been found assign one.
2620 if (!AFI->getPredicateRegForFillSpill() &&
2621 MF.getFunction().getCallingConv() ==
2622 CallingConv::AArch64_SVE_VectorCall) {
2623 SavedRegs.set(AArch64::P8);
2624 AFI->setPredicateRegForFillSpill(AArch64::PN8);
2625 }
2626
2627 assert(!ReservedRegs[AFI->getPredicateRegForFillSpill()] &&
2628 "Predicate cannot be a reserved register");
2629 }
2630
2631 if (MF.getFunction().getCallingConv() == CallingConv::Win64 &&
2632 !Subtarget.isTargetWindows()) {
2633 // For Windows calling convention on a non-windows OS, where X18 is treated
2634 // as reserved, back up X18 when entering non-windows code (marked with the
2635 // Windows calling convention) and restore when returning regardless of
2636 // whether the individual function uses it - it might call other functions
2637 // that clobber it.
2638 SavedRegs.set(AArch64::X18);
2639 }
2640
2641 // Determine if a Hazard slot should be used and where it should go.
2642 // If SplitSVEObjects is used, the hazard padding is placed between the PPRs
2643 // and ZPRs. Otherwise, it goes in the callee save area.
2644 determineStackHazardSlot(MF, SavedRegs);
2645
2646 // Calculates the callee saved stack size.
2647 unsigned CSStackSize = 0;
2648 unsigned ZPRCSStackSize = 0;
2649 unsigned PPRCSStackSize = 0;
2650 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2651 for (unsigned Reg : SavedRegs.set_bits()) {
2652 auto *RC = TRI->getMinimalPhysRegClass(Reg: MCRegister(Reg));
2653 assert(RC && "expected register class!");
2654 auto SpillSize = TRI->getSpillSize(RC: *RC);
2655 bool IsZPR = AArch64::ZPRRegClass.contains(Reg);
2656 bool IsPPR = !IsZPR && AArch64::PPRRegClass.contains(Reg);
2657 if (IsZPR)
2658 ZPRCSStackSize += SpillSize;
2659 else if (IsPPR)
2660 PPRCSStackSize += SpillSize;
2661 else {
2662 // A register and its super-register can both appear in SavedRegs.
2663 // Only the widest register is actually spilled, so skip such
2664 // sub-registers here to avoid double-counting the overlap.
2665 bool SavedSuper = any_of(Range: TRI->superregs(Reg), P: [&](MCPhysReg SuperReg) {
2666 return SavedRegs.test(Idx: SuperReg);
2667 });
2668 if (!SavedSuper)
2669 CSStackSize += SpillSize;
2670 }
2671 }
2672
2673 // Save number of saved regs, so we can easily update CSStackSize later to
2674 // account for any additional 64-bit GPR saves. Note: After this point
2675 // only 64-bit GPRs can be added to SavedRegs.
2676 unsigned NumSavedRegs = SavedRegs.count();
2677
2678 // If we have hazard padding in the CS area add that to the size.
2679 if (AFI->isStackHazardIncludedInCalleeSaveArea())
2680 CSStackSize += getStackHazardSize(MF);
2681
2682 // Increase the callee-saved stack size if the function has streaming mode
2683 // changes, as we will need to spill the value of the VG register.
2684 if (requiresSaveVG(MF))
2685 CSStackSize += 8;
2686
2687 // If we must call __arm_get_current_vg in the prologue preserve the LR.
2688 if (requiresSaveVG(MF) && !Subtarget.hasSVE())
2689 SavedRegs.set(AArch64::LR);
2690
2691 // The frame record needs to be created by saving the appropriate registers
2692 uint64_t EstimatedStackSize = MFI.estimateStackSize(MF);
2693 if (hasFP(MF) ||
2694 windowsRequiresStackProbe(MF, StackSizeInBytes: EstimatedStackSize + CSStackSize + 16)) {
2695 SavedRegs.set(AArch64::FP);
2696 SavedRegs.set(AArch64::LR);
2697 }
2698
2699 LLVM_DEBUG({
2700 dbgs() << "*** determineCalleeSaves\nSaved CSRs:";
2701 for (unsigned Reg : SavedRegs.set_bits())
2702 dbgs() << ' ' << printReg(MCRegister(Reg), RegInfo);
2703 dbgs() << "\n";
2704 });
2705
2706 // If any callee-saved registers are used, the frame cannot be eliminated.
2707 auto [ZPRLocalStackSize, PPRLocalStackSize] =
2708 determineSVEStackSizes(MF, AssignOffsets: AssignObjectOffsets::No);
2709 uint64_t SVELocals = ZPRLocalStackSize + PPRLocalStackSize;
2710 uint64_t SVEStackSize =
2711 alignTo(Value: ZPRCSStackSize + PPRCSStackSize + SVELocals, Align: 16);
2712 bool CanEliminateFrame = (SavedRegs.count() == 0) && !SVEStackSize;
2713
2714 // The CSR spill slots have not been allocated yet, so estimateStackSize
2715 // won't include them.
2716 unsigned EstimatedStackSizeLimit = estimateRSStackSizeLimit(MF);
2717
2718 // We may address some of the stack above the canonical frame address, either
2719 // for our own arguments or during a call. Include that in calculating whether
2720 // we have complicated addressing concerns.
2721 int64_t CalleeStackUsed = 0;
2722 for (int I = MFI.getObjectIndexBegin(); I != 0; ++I) {
2723 int64_t FixedOff = MFI.getObjectOffset(ObjectIdx: I);
2724 if (FixedOff > CalleeStackUsed)
2725 CalleeStackUsed = FixedOff;
2726 }
2727
2728 // Conservatively always assume BigStack when there are SVE spills.
2729 bool BigStack = SVEStackSize || (EstimatedStackSize + CSStackSize +
2730 CalleeStackUsed) > EstimatedStackSizeLimit;
2731 if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF))
2732 AFI->setHasStackFrame(true);
2733
2734 // Estimate if we might need to scavenge a register at some point in order
2735 // to materialize a stack offset. If so, either spill one additional
2736 // callee-saved register or reserve a special spill slot to facilitate
2737 // register scavenging. If we already spilled an extra callee-saved register
2738 // above to keep the number of spills even, we don't need to do anything else
2739 // here.
2740 if (BigStack) {
2741 if (!ExtraCSSpill.isValid() && UnspilledCSGPR.isValid()) {
2742 LLVM_DEBUG(dbgs() << "Spilling " << printReg(UnspilledCSGPR, RegInfo)
2743 << " to get a scratch register.\n");
2744 SavedRegs.set(UnspilledCSGPR);
2745 ExtraCSSpill = UnspilledCSGPR;
2746
2747 // MachO's compact unwind format relies on all registers being stored in
2748 // pairs, so if we need to spill one extra for BigStack, then we need to
2749 // store the pair.
2750 if (producePairRegisters(MF)) {
2751 if (!UnspilledCSGPRPaired.isValid()) {
2752 // Failed to make a pair for compact unwind format, revert spilling.
2753 if (produceCompactUnwindFrame(AFL: *this, MF)) {
2754 SavedRegs.reset(Idx: UnspilledCSGPR);
2755 ExtraCSSpill = Register();
2756 }
2757 } else
2758 SavedRegs.set(UnspilledCSGPRPaired);
2759 }
2760 }
2761
2762 // If we didn't find an extra callee-saved register to spill, create
2763 // an emergency spill slot.
2764 if (!ExtraCSSpill.isValid() ||
2765 MF.getRegInfo().isPhysRegUsed(PhysReg: ExtraCSSpill)) {
2766 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2767 const TargetRegisterClass &RC = AArch64::GPR64RegClass;
2768 unsigned Size = TRI->getSpillSize(RC);
2769 Align Alignment = TRI->getSpillAlign(RC);
2770 int FI = MFI.CreateSpillStackObject(Size, Alignment);
2771 RS->addScavengingFrameIndex(FI);
2772 LLVM_DEBUG(dbgs() << "No available CS registers, allocated fi#" << FI
2773 << " as the emergency spill slot.\n");
2774 }
2775 }
2776
2777 // Adding the size of additional 64bit GPR saves.
2778 CSStackSize += 8 * (SavedRegs.count() - NumSavedRegs);
2779
2780 // A Swift asynchronous context extends the frame record with a pointer
2781 // directly before FP.
2782 if (hasFP(MF) && AFI->hasSwiftAsyncContext())
2783 CSStackSize += 8;
2784
2785 uint64_t AlignedCSStackSize = alignTo(Value: CSStackSize, Align: 16);
2786 LLVM_DEBUG(dbgs() << "Estimated stack frame size: "
2787 << EstimatedStackSize + AlignedCSStackSize << " bytes.\n");
2788
2789 assert((!MFI.isCalleeSavedInfoValid() ||
2790 AFI->getCalleeSavedStackSize() == AlignedCSStackSize) &&
2791 "Should not invalidate callee saved info");
2792
2793 // Round up to register pair alignment to avoid additional SP adjustment
2794 // instructions.
2795 AFI->setCalleeSavedStackSize(AlignedCSStackSize);
2796 AFI->setCalleeSaveStackHasFreeSpace(AlignedCSStackSize != CSStackSize);
2797 AFI->setSVECalleeSavedStackSize(ZPR: ZPRCSStackSize, PPR: alignTo(Value: PPRCSStackSize, Align: 16));
2798}
2799
2800static void orderZPRCalleeSavesForPairs(MachineFunction &MF,
2801 const TargetRegisterInfo *RegInfo,
2802 std::vector<CalleeSavedInfo> &CSI) {
2803 // Reorder callee-saved ZPRs to maximize pairing which requires
2804 // consecutive even/odd registers at even scaled stack offsets.
2805 // Additional requirements are checked when the register pairs are formed.
2806 assert(!isTargetWindows(MF) &&
2807 "ZPR callee-save reordering not supported on Windows");
2808
2809 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
2810 if (!AFI->getPredicateRegForFillSpill())
2811 return;
2812
2813 SmallVector<CalleeSavedInfo> ZPRSaves;
2814 SmallVector<size_t> ZPRPositions;
2815
2816 for (auto [Index, CS] : llvm::enumerate(First&: CSI)) {
2817 if (AArch64::ZPRRegClass.contains(Reg: CS.getReg())) {
2818 ZPRSaves.push_back(Elt: CS);
2819 ZPRPositions.push_back(Elt: Index);
2820 }
2821 }
2822
2823 if (ZPRSaves.size() < 2)
2824 return;
2825
2826 llvm::sort(C&: ZPRSaves, Comp: [](const auto &A, const auto &B) {
2827 return A.getReg() < B.getReg();
2828 });
2829
2830 SmallVector<std::pair<CalleeSavedInfo, CalleeSavedInfo>> Pairs;
2831 SmallVector<CalleeSavedInfo> Singles;
2832 for (size_t i = 0; i < ZPRSaves.size();) {
2833 if (i + 1 < ZPRSaves.size() &&
2834 (ZPRSaves[i].getReg() + 1 == ZPRSaves[i + 1].getReg()) &&
2835 (ZPRSaves[i].getReg() - AArch64::Z0) % 2 == 0) {
2836 Pairs.emplace_back(Args&: ZPRSaves[i], Args&: ZPRSaves[i + 1]);
2837 i += 2;
2838 } else {
2839 Singles.push_back(Elt: ZPRSaves[i++]);
2840 }
2841 }
2842
2843 // If the lowest offset is odd, select one register to spill here
2844 // so subsequent pairs begin at an even offset.
2845 int ZPRByteOffset = AFI->getZPRCalleeSavedStackSize();
2846 if (!AFI->hasSplitSVEObjects())
2847 ZPRByteOffset += AFI->getPPRCalleeSavedStackSize();
2848
2849 const int Scale = RegInfo->getSpillSize(RC: AArch64::ZPRRegClass);
2850 const int LowestOffset =
2851 (ZPRByteOffset / Scale) - static_cast<int>(ZPRSaves.size());
2852
2853 // Prefer the highest single otherwise split the highest pair.
2854 std::optional<CalleeSavedInfo> AlignmentSingle;
2855 if (LowestOffset % 2 != 0) {
2856 if (!Singles.empty()) {
2857 AlignmentSingle = Singles.pop_back_val();
2858 } else {
2859 assert(!Pairs.empty() && "Expected a ZPR pair to split");
2860 auto [Even, Odd] = Pairs.pop_back_val();
2861 AlignmentSingle = Odd;
2862 Singles.push_back(Elt: Even);
2863 }
2864 }
2865
2866 if (Pairs.empty())
2867 return;
2868
2869 // Build ZPRs so reverse spill emission processes the leading single first,
2870 // followed by the candidate even/odd pairs and remaining singles.
2871 SmallVector<CalleeSavedInfo> ZPRSavesInCSIOrder;
2872 llvm::append_range(C&: ZPRSavesInCSIOrder, R&: Singles);
2873
2874 for (const auto &[Even, Odd] : Pairs) {
2875 ZPRSavesInCSIOrder.push_back(Elt: Even);
2876 ZPRSavesInCSIOrder.push_back(Elt: Odd);
2877 }
2878
2879 if (AlignmentSingle)
2880 ZPRSavesInCSIOrder.push_back(Elt: *AlignmentSingle);
2881
2882 assert(ZPRSavesInCSIOrder.size() == ZPRPositions.size() &&
2883 "Reordering should not change the number of ZPR spills");
2884 for (auto [Position, CS] : llvm::zip(t&: ZPRPositions, u&: ZPRSavesInCSIOrder))
2885 CSI[Position] = CS;
2886}
2887
2888bool AArch64FrameLowering::assignCalleeSavedSpillSlots(
2889 MachineFunction &MF, const TargetRegisterInfo *RegInfo,
2890 std::vector<CalleeSavedInfo> &CSI) const {
2891 bool IsWindows = isTargetWindows(MF);
2892 unsigned StackHazardSize = getStackHazardSize(MF);
2893 // To match the canonical windows frame layout, reverse the list of
2894 // callee saved registers to get them laid out by PrologEpilogInserter
2895 // in the right order. (PrologEpilogInserter allocates stack objects top
2896 // down. Windows canonical prologs store higher numbered registers at
2897 // the top, thus have the CSI array start from the highest registers.)
2898 if (IsWindows)
2899 std::reverse(first: CSI.begin(), last: CSI.end());
2900
2901 if (CSI.empty())
2902 return true; // Early exit if no callee saved registers are modified!
2903
2904 // Now that we know which registers need to be saved and restored, allocate
2905 // stack slots for them.
2906 MachineFrameInfo &MFI = MF.getFrameInfo();
2907 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
2908
2909 // Insert VG into the list of CSRs, immediately before LR if saved.
2910 if (requiresSaveVG(MF)) {
2911 CalleeSavedInfo VGInfo(AArch64::VG);
2912 auto It =
2913 find_if(Range&: CSI, P: [](auto &Info) { return Info.getReg() == AArch64::LR; });
2914 if (It != CSI.end())
2915 CSI.insert(position: It, x: VGInfo);
2916 else
2917 CSI.push_back(x: VGInfo);
2918 }
2919
2920 const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
2921 if (!IsWindows && enableMultiVectorSpillFill(Subtarget, MF))
2922 // The Windows stack layout is not supported by this reordering function
2923 // yet.
2924 orderZPRCalleeSavesForPairs(MF, RegInfo, CSI);
2925
2926 Register LastReg = 0;
2927 int HazardSlotIndex = std::numeric_limits<int>::max();
2928 for (auto &CS : CSI) {
2929 MCRegister Reg = CS.getReg();
2930 const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);
2931
2932 // Create a hazard slot as we switch between GPR and FPR CSRs.
2933 if (AFI->isStackHazardIncludedInCalleeSaveArea() &&
2934 (!LastReg || !AArch64InstrInfo::isFpOrNEON(Reg: LastReg)) &&
2935 AArch64InstrInfo::isFpOrNEON(Reg)) {
2936 assert(HazardSlotIndex == std::numeric_limits<int>::max() &&
2937 "Unexpected register order for hazard slot");
2938 HazardSlotIndex = MFI.CreateStackObject(Size: StackHazardSize, Alignment: Align(8), isSpillSlot: true);
2939 LLVM_DEBUG(dbgs() << "Created CSR Hazard at slot " << HazardSlotIndex
2940 << "\n");
2941 AFI->setStackHazardCSRSlotIndex(HazardSlotIndex);
2942 MFI.setIsCalleeSavedObjectIndex(ObjectIdx: HazardSlotIndex, IsCalleeSaved: true);
2943 }
2944
2945 unsigned Size = RegInfo->getSpillSize(RC: *RC);
2946 Align Alignment(RegInfo->getSpillAlign(RC: *RC));
2947 int FrameIdx = MFI.CreateStackObject(Size, Alignment, isSpillSlot: true);
2948 CS.setFrameIdx(FrameIdx);
2949 MFI.setIsCalleeSavedObjectIndex(ObjectIdx: FrameIdx, IsCalleeSaved: true);
2950
2951 // Grab 8 bytes below FP for the extended asynchronous frame info.
2952 if (hasFP(MF) && AFI->hasSwiftAsyncContext() && Reg == AArch64::FP) {
2953 FrameIdx = MFI.CreateStackObject(Size: 8, Alignment, isSpillSlot: true);
2954 AFI->setSwiftAsyncContextFrameIdx(FrameIdx);
2955 MFI.setIsCalleeSavedObjectIndex(ObjectIdx: FrameIdx, IsCalleeSaved: true);
2956 }
2957 LastReg = Reg;
2958 }
2959
2960 // Add hazard slot in the case where no FPR CSRs are present.
2961 if (AFI->isStackHazardIncludedInCalleeSaveArea() &&
2962 HazardSlotIndex == std::numeric_limits<int>::max()) {
2963 HazardSlotIndex = MFI.CreateStackObject(Size: StackHazardSize, Alignment: Align(8), isSpillSlot: true);
2964 LLVM_DEBUG(dbgs() << "Created CSR Hazard at slot " << HazardSlotIndex
2965 << "\n");
2966 AFI->setStackHazardCSRSlotIndex(HazardSlotIndex);
2967 MFI.setIsCalleeSavedObjectIndex(ObjectIdx: HazardSlotIndex, IsCalleeSaved: true);
2968 }
2969
2970 return true;
2971}
2972
2973bool AArch64FrameLowering::enableStackSlotScavenging(
2974 const MachineFunction &MF) const {
2975 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
2976 // If the function has streaming-mode changes, don't scavenge a
2977 // spillslot in the callee-save area, as that might require an
2978 // 'addvl' in the streaming-mode-changing call-sequence when the
2979 // function doesn't use a FP.
2980 if (AFI->hasStreamingModeChanges() && !hasFP(MF))
2981 return false;
2982 // Don't allow register salvaging with hazard slots, in case it moves objects
2983 // into the wrong place.
2984 if (AFI->hasStackHazardSlotIndex())
2985 return false;
2986 return AFI->hasCalleeSaveStackFreeSpace();
2987}
2988
2989/// returns true if there are any SVE callee saves.
2990static bool getSVECalleeSaveSlotRange(const MachineFrameInfo &MFI,
2991 int &Min, int &Max) {
2992 Min = std::numeric_limits<int>::max();
2993 Max = std::numeric_limits<int>::min();
2994
2995 if (!MFI.isCalleeSavedInfoValid())
2996 return false;
2997
2998 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2999 for (auto &CS : CSI) {
3000 if (AArch64::ZPRRegClass.contains(Reg: CS.getReg()) ||
3001 AArch64::PPRRegClass.contains(Reg: CS.getReg())) {
3002 assert((Max == std::numeric_limits<int>::min() ||
3003 Max + 1 == CS.getFrameIdx()) &&
3004 "SVE CalleeSaves are not consecutive");
3005 Min = std::min(a: Min, b: CS.getFrameIdx());
3006 Max = std::max(a: Max, b: CS.getFrameIdx());
3007 }
3008 }
3009 return Min != std::numeric_limits<int>::max();
3010}
3011
3012static SVEStackSizes determineSVEStackSizes(MachineFunction &MF,
3013 AssignObjectOffsets AssignOffsets) {
3014 MachineFrameInfo &MFI = MF.getFrameInfo();
3015 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
3016
3017 SVEStackSizes SVEStack{};
3018
3019 // With SplitSVEObjects we maintain separate stack offsets for predicates
3020 // (PPRs) and SVE vectors (ZPRs). When SplitSVEObjects is disabled predicates
3021 // are included in the SVE vector area.
3022 uint64_t &ZPRStackTop = SVEStack.ZPRStackSize;
3023 uint64_t &PPRStackTop =
3024 AFI->hasSplitSVEObjects() ? SVEStack.PPRStackSize : SVEStack.ZPRStackSize;
3025
3026#ifndef NDEBUG
3027 // First process all fixed stack objects.
3028 for (int I = MFI.getObjectIndexBegin(); I != 0; ++I)
3029 assert(!MFI.hasScalableStackID(I) &&
3030 "SVE vectors should never be passed on the stack by value, only by "
3031 "reference.");
3032#endif
3033
3034 auto AllocateObject = [&](int FI) {
3035 uint64_t &StackTop = MFI.getStackID(ObjectIdx: FI) == TargetStackID::ScalableVector
3036 ? ZPRStackTop
3037 : PPRStackTop;
3038
3039 // FIXME: Given that the length of SVE vectors is not necessarily a power of
3040 // two, we'd need to align every object dynamically at runtime if the
3041 // alignment is larger than 16. This is not yet supported.
3042 Align Alignment = MFI.getObjectAlign(ObjectIdx: FI);
3043 if (Alignment > Align(16))
3044 report_fatal_error(
3045 reason: "Alignment of scalable vectors > 16 bytes is not yet supported");
3046
3047 StackTop += MFI.getObjectSize(ObjectIdx: FI);
3048 StackTop = alignTo(Size: StackTop, A: Alignment);
3049
3050 assert(StackTop < (uint64_t)std::numeric_limits<int64_t>::max() &&
3051 "SVE StackTop far too large?!");
3052
3053 int64_t Offset = -int64_t(StackTop);
3054 if (AssignOffsets == AssignObjectOffsets::Yes)
3055 MFI.setObjectOffset(ObjectIdx: FI, SPOffset: Offset);
3056
3057 LLVM_DEBUG(dbgs() << "alloc FI(" << FI << ") at SP[" << Offset << "]\n");
3058 };
3059
3060 // Then process all callee saved slots.
3061 int MinCSFrameIndex, MaxCSFrameIndex;
3062 if (getSVECalleeSaveSlotRange(MFI, Min&: MinCSFrameIndex, Max&: MaxCSFrameIndex)) {
3063 for (int FI = MinCSFrameIndex; FI <= MaxCSFrameIndex; ++FI)
3064 AllocateObject(FI);
3065 }
3066
3067 // Ensure the CS area is 16-byte aligned.
3068 PPRStackTop = alignTo(Size: PPRStackTop, A: Align(16U));
3069 ZPRStackTop = alignTo(Size: ZPRStackTop, A: Align(16U));
3070
3071 // Create a buffer of SVE objects to allocate and sort it.
3072 SmallVector<int, 8> ObjectsToAllocate;
3073 // If we have a stack protector, and we've previously decided that we have SVE
3074 // objects on the stack and thus need it to go in the SVE stack area, then it
3075 // needs to go first.
3076 int StackProtectorFI = -1;
3077 if (MFI.hasStackProtectorIndex()) {
3078 StackProtectorFI = MFI.getStackProtectorIndex();
3079 if (MFI.getStackID(ObjectIdx: StackProtectorFI) == TargetStackID::ScalableVector)
3080 ObjectsToAllocate.push_back(Elt: StackProtectorFI);
3081 }
3082
3083 for (int FI = 0, E = MFI.getObjectIndexEnd(); FI != E; ++FI) {
3084 if (FI == StackProtectorFI || MFI.isDeadObjectIndex(ObjectIdx: FI) ||
3085 MFI.isCalleeSavedObjectIndex(ObjectIdx: FI))
3086 continue;
3087
3088 if (MFI.getStackID(ObjectIdx: FI) != TargetStackID::ScalableVector &&
3089 MFI.getStackID(ObjectIdx: FI) != TargetStackID::ScalablePredicateVector)
3090 continue;
3091
3092 ObjectsToAllocate.push_back(Elt: FI);
3093 }
3094
3095 // Allocate all SVE locals and spills
3096 for (unsigned FI : ObjectsToAllocate)
3097 AllocateObject(FI);
3098
3099 PPRStackTop = alignTo(Size: PPRStackTop, A: Align(16U));
3100 ZPRStackTop = alignTo(Size: ZPRStackTop, A: Align(16U));
3101
3102 if (AssignOffsets == AssignObjectOffsets::Yes)
3103 AFI->setStackSizeSVE(ZPR: SVEStack.ZPRStackSize, PPR: SVEStack.PPRStackSize);
3104
3105 return SVEStack;
3106}
3107
3108void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
3109 MachineFunction &MF, RegScavenger *RS) const {
3110 assert(getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown &&
3111 "Upwards growing stack unsupported");
3112
3113 (void)determineSVEStackSizes(MF, AssignOffsets: AssignObjectOffsets::Yes);
3114
3115 // If this function isn't doing Win64-style C++ EH, we don't need to do
3116 // anything.
3117 if (!MF.hasEHFunclets())
3118 return;
3119
3120 MachineFrameInfo &MFI = MF.getFrameInfo();
3121 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
3122
3123 // Win64 C++ EH needs to allocate space for the catch objects in the fixed
3124 // object area right next to the UnwindHelp object.
3125 WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo();
3126 int64_t CurrentOffset =
3127 AFI->getVarArgsGPRSize() + AFI->getTailCallReservedStack();
3128 for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
3129 for (WinEHHandlerType &H : TBME.HandlerArray) {
3130 int FrameIndex = H.CatchObj.FrameIndex;
3131 if ((FrameIndex != INT_MAX) && MFI.getObjectOffset(ObjectIdx: FrameIndex) == 0) {
3132 CurrentOffset =
3133 alignTo(Value: CurrentOffset, Align: MFI.getObjectAlign(ObjectIdx: FrameIndex).value());
3134 CurrentOffset += MFI.getObjectSize(ObjectIdx: FrameIndex);
3135 MFI.setObjectOffset(ObjectIdx: FrameIndex, SPOffset: -CurrentOffset);
3136 }
3137 }
3138 }
3139
3140 // Create an UnwindHelp object.
3141 // The UnwindHelp object is allocated at the start of the fixed object area
3142 int64_t UnwindHelpOffset = alignTo(Size: CurrentOffset + 8, A: Align(16));
3143 assert(UnwindHelpOffset == getFixedObjectSize(MF, AFI, /*IsWin64*/ true,
3144 /*IsFunclet*/ false) &&
3145 "UnwindHelpOffset must be at the start of the fixed object area");
3146 int UnwindHelpFI = MFI.CreateFixedObject(/*Size*/ 8, SPOffset: -UnwindHelpOffset,
3147 /*IsImmutable=*/false);
3148 EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
3149
3150 MachineBasicBlock &MBB = MF.front();
3151 auto MBBI = MBB.begin();
3152 while (MBBI != MBB.end() && MBBI->getFlag(Flag: MachineInstr::FrameSetup))
3153 ++MBBI;
3154
3155 // We need to store -2 into the UnwindHelp object at the start of the
3156 // function.
3157 DebugLoc DL;
3158 RS->enterBasicBlockEnd(MBB);
3159 RS->backward(I: MBBI);
3160 Register DstReg = RS->FindUnusedReg(RC: &AArch64::GPR64commonRegClass);
3161 assert(DstReg && "There must be a free register after frame setup");
3162 const AArch64InstrInfo &TII =
3163 *MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
3164 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AArch64::MOVi64imm), DestReg: DstReg).addImm(Val: -2);
3165 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: TII.get(Opcode: AArch64::STURXi))
3166 .addReg(RegNo: DstReg, Flags: getKillRegState(B: true))
3167 .addFrameIndex(Idx: UnwindHelpFI)
3168 .addImm(Val: 0);
3169}
3170
3171namespace {
3172struct TagStoreInstr {
3173 MachineInstr *MI;
3174 int64_t Offset, Size;
3175 explicit TagStoreInstr(MachineInstr *MI, int64_t Offset, int64_t Size)
3176 : MI(MI), Offset(Offset), Size(Size) {}
3177};
3178
3179class TagStoreEdit {
3180 MachineFunction *MF;
3181 MachineBasicBlock *MBB;
3182 MachineRegisterInfo *MRI;
3183 // Tag store instructions that are being replaced.
3184 SmallVector<TagStoreInstr, 8> TagStores;
3185 // Combined memref arguments of the above instructions.
3186 SmallVector<MachineMemOperand *, 8> CombinedMemRefs;
3187
3188 // Replace allocation tags in [FrameReg + FrameRegOffset, FrameReg +
3189 // FrameRegOffset + Size) with the address tag of SP.
3190 Register FrameReg;
3191 StackOffset FrameRegOffset;
3192 int64_t Size;
3193 // If not std::nullopt, move FrameReg to (FrameReg + FrameRegUpdate) at the
3194 // end.
3195 std::optional<int64_t> FrameRegUpdate;
3196 // MIFlags for any FrameReg updating instructions.
3197 unsigned FrameRegUpdateFlags;
3198
3199 // Use zeroing instruction variants.
3200 bool ZeroData;
3201 DebugLoc DL;
3202
3203 void emitUnrolled(MachineBasicBlock::iterator InsertI);
3204 void emitLoop(MachineBasicBlock::iterator InsertI);
3205
3206public:
3207 TagStoreEdit(MachineBasicBlock *MBB, bool ZeroData)
3208 : MBB(MBB), ZeroData(ZeroData) {
3209 MF = MBB->getParent();
3210 MRI = &MF->getRegInfo();
3211 }
3212 // Add an instruction to be replaced. Instructions must be added in the
3213 // ascending order of Offset, and have to be adjacent.
3214 void addInstruction(TagStoreInstr I) {
3215 assert((TagStores.empty() ||
3216 TagStores.back().Offset + TagStores.back().Size == I.Offset) &&
3217 "Non-adjacent tag store instructions.");
3218 TagStores.push_back(Elt: I);
3219 }
3220 void clear() { TagStores.clear(); }
3221 // Emit equivalent code at the given location, and erase the current set of
3222 // instructions. May skip if the replacement is not profitable. May invalidate
3223 // the input iterator and replace it with a valid one.
3224 void emitCode(MachineBasicBlock::iterator &InsertI,
3225 const AArch64FrameLowering *TFI, bool TryMergeSPUpdate);
3226};
3227
3228void TagStoreEdit::emitUnrolled(MachineBasicBlock::iterator InsertI) {
3229 const AArch64InstrInfo *TII =
3230 MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
3231
3232 const int64_t kMinOffset = -256 * 16;
3233 const int64_t kMaxOffset = 255 * 16;
3234
3235 Register BaseReg = FrameReg;
3236 int64_t BaseRegOffsetBytes = FrameRegOffset.getFixed();
3237 if (BaseRegOffsetBytes < kMinOffset ||
3238 BaseRegOffsetBytes + (Size - Size % 32) > kMaxOffset ||
3239 // BaseReg can be FP, which is not necessarily aligned to 16-bytes. In
3240 // that case, BaseRegOffsetBytes will not be aligned to 16 bytes, which
3241 // is required for the offset of ST2G.
3242 BaseRegOffsetBytes % 16 != 0) {
3243 Register ScratchReg = MRI->createVirtualRegister(RegClass: &AArch64::GPR64RegClass);
3244 emitFrameOffset(MBB&: *MBB, MBBI: InsertI, DL, DestReg: ScratchReg, SrcReg: BaseReg,
3245 Offset: StackOffset::getFixed(Fixed: BaseRegOffsetBytes), TII);
3246 BaseReg = ScratchReg;
3247 BaseRegOffsetBytes = 0;
3248 }
3249
3250 MachineInstr *LastI = nullptr;
3251 while (Size) {
3252 int64_t InstrSize = (Size > 16) ? 32 : 16;
3253 unsigned Opcode =
3254 InstrSize == 16
3255 ? (ZeroData ? AArch64::STZGi : AArch64::STGi)
3256 : (ZeroData ? AArch64::STZ2Gi : AArch64::ST2Gi);
3257 assert(BaseRegOffsetBytes % 16 == 0);
3258 MachineInstr *I = BuildMI(BB&: *MBB, I: InsertI, MIMD: DL, MCID: TII->get(Opcode))
3259 .addReg(RegNo: AArch64::SP)
3260 .addReg(RegNo: BaseReg)
3261 .addImm(Val: BaseRegOffsetBytes / 16)
3262 .setMemRefs(CombinedMemRefs);
3263 // A store to [BaseReg, #0] should go last for an opportunity to fold the
3264 // final SP adjustment in the epilogue.
3265 if (BaseRegOffsetBytes == 0)
3266 LastI = I;
3267 BaseRegOffsetBytes += InstrSize;
3268 Size -= InstrSize;
3269 }
3270
3271 if (LastI)
3272 MBB->splice(Where: InsertI, Other: MBB, From: LastI);
3273}
3274
3275void TagStoreEdit::emitLoop(MachineBasicBlock::iterator InsertI) {
3276 const AArch64InstrInfo *TII =
3277 MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
3278
3279 Register BaseReg = FrameRegUpdate
3280 ? FrameReg
3281 : MRI->createVirtualRegister(RegClass: &AArch64::GPR64RegClass);
3282 Register SizeReg = MRI->createVirtualRegister(RegClass: &AArch64::GPR64RegClass);
3283
3284 emitFrameOffset(MBB&: *MBB, MBBI: InsertI, DL, DestReg: BaseReg, SrcReg: FrameReg, Offset: FrameRegOffset, TII);
3285
3286 int64_t LoopSize = Size;
3287 // If the loop size is not a multiple of 32, split off one 16-byte store at
3288 // the end to fold BaseReg update into.
3289 if (FrameRegUpdate && *FrameRegUpdate)
3290 LoopSize -= LoopSize % 32;
3291 MachineInstr *LoopI = BuildMI(BB&: *MBB, I: InsertI, MIMD: DL,
3292 MCID: TII->get(Opcode: ZeroData ? AArch64::STZGloop_wback
3293 : AArch64::STGloop_wback))
3294 .addDef(RegNo: SizeReg)
3295 .addDef(RegNo: BaseReg)
3296 .addImm(Val: LoopSize)
3297 .addReg(RegNo: BaseReg)
3298 .setMemRefs(CombinedMemRefs);
3299 if (FrameRegUpdate)
3300 LoopI->setFlags(FrameRegUpdateFlags);
3301
3302 int64_t ExtraBaseRegUpdate =
3303 FrameRegUpdate ? (*FrameRegUpdate - FrameRegOffset.getFixed() - Size) : 0;
3304 LLVM_DEBUG(dbgs() << "TagStoreEdit::emitLoop: LoopSize=" << LoopSize
3305 << ", Size=" << Size
3306 << ", ExtraBaseRegUpdate=" << ExtraBaseRegUpdate
3307 << ", FrameRegUpdate=" << FrameRegUpdate
3308 << ", FrameRegOffset.getFixed()="
3309 << FrameRegOffset.getFixed() << "\n");
3310 if (LoopSize < Size) {
3311 assert(FrameRegUpdate);
3312 assert(Size - LoopSize == 16);
3313 // Tag 16 more bytes at BaseReg and update BaseReg.
3314 int64_t STGOffset = ExtraBaseRegUpdate + 16;
3315 assert(STGOffset % 16 == 0 && STGOffset >= -4096 && STGOffset <= 4080 &&
3316 "STG immediate out of range");
3317 BuildMI(BB&: *MBB, I: InsertI, MIMD: DL,
3318 MCID: TII->get(Opcode: ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex))
3319 .addDef(RegNo: BaseReg)
3320 .addReg(RegNo: BaseReg)
3321 .addReg(RegNo: BaseReg)
3322 .addImm(Val: STGOffset / 16)
3323 .setMemRefs(CombinedMemRefs)
3324 .setMIFlags(FrameRegUpdateFlags);
3325 } else if (ExtraBaseRegUpdate) {
3326 // Update BaseReg.
3327 int64_t AddSubOffset = std::abs(i: ExtraBaseRegUpdate);
3328 assert(AddSubOffset <= 4095 && "ADD/SUB immediate out of range");
3329 BuildMI(
3330 BB&: *MBB, I: InsertI, MIMD: DL,
3331 MCID: TII->get(Opcode: ExtraBaseRegUpdate > 0 ? AArch64::ADDXri : AArch64::SUBXri))
3332 .addDef(RegNo: BaseReg)
3333 .addReg(RegNo: BaseReg)
3334 .addImm(Val: AddSubOffset)
3335 .addImm(Val: 0)
3336 .setMIFlags(FrameRegUpdateFlags);
3337 }
3338}
3339
3340// Check if *II is a register update that can be merged into STGloop that ends
3341// at (Reg + Size). RemainingOffset is the required adjustment to Reg after the
3342// end of the loop.
3343bool canMergeRegUpdate(MachineBasicBlock::iterator II, unsigned Reg,
3344 int64_t Size, int64_t *TotalOffset) {
3345 MachineInstr &MI = *II;
3346 if ((MI.getOpcode() == AArch64::ADDXri ||
3347 MI.getOpcode() == AArch64::SUBXri) &&
3348 MI.getOperand(i: 0).getReg() == Reg && MI.getOperand(i: 1).getReg() == Reg) {
3349 unsigned Shift = AArch64_AM::getShiftValue(Imm: MI.getOperand(i: 3).getImm());
3350 int64_t Offset = MI.getOperand(i: 2).getImm() << Shift;
3351 if (MI.getOpcode() == AArch64::SUBXri)
3352 Offset = -Offset;
3353 int64_t PostOffset = Offset - Size;
3354 // TagStoreEdit::emitLoop might emit either an ADD/SUB after the loop, or
3355 // an STGPostIndex which does the last 16 bytes of tag write. Which one is
3356 // chosen depends on the alignment of the loop size, but the difference
3357 // between the valid ranges for the two instructions is small, so we
3358 // conservatively assume that it could be either case here.
3359 //
3360 // Max offset of STGPostIndex, minus the 16 byte tag write folded into that
3361 // instruction.
3362 const int64_t kMaxOffset = 4080 - 16;
3363 // Max offset of SUBXri.
3364 const int64_t kMinOffset = -4095;
3365 if (PostOffset <= kMaxOffset && PostOffset >= kMinOffset &&
3366 PostOffset % 16 == 0) {
3367 *TotalOffset = Offset;
3368 return true;
3369 }
3370 }
3371 return false;
3372}
3373
3374void mergeMemRefs(const SmallVectorImpl<TagStoreInstr> &TSE,
3375 SmallVectorImpl<MachineMemOperand *> &MemRefs) {
3376 MemRefs.clear();
3377 for (auto &TS : TSE) {
3378 MachineInstr *MI = TS.MI;
3379 // An instruction without memory operands may access anything. Be
3380 // conservative and return an empty list.
3381 if (MI->memoperands_empty()) {
3382 MemRefs.clear();
3383 return;
3384 }
3385 MemRefs.append(in_start: MI->memoperands_begin(), in_end: MI->memoperands_end());
3386 }
3387}
3388
3389void TagStoreEdit::emitCode(MachineBasicBlock::iterator &InsertI,
3390 const AArch64FrameLowering *TFI,
3391 bool TryMergeSPUpdate) {
3392 if (TagStores.empty())
3393 return;
3394 TagStoreInstr &FirstTagStore = TagStores[0];
3395 TagStoreInstr &LastTagStore = TagStores[TagStores.size() - 1];
3396 Size = LastTagStore.Offset - FirstTagStore.Offset + LastTagStore.Size;
3397 DL = TagStores[0].MI->getDebugLoc();
3398
3399 Register Reg;
3400 FrameRegOffset = TFI->resolveFrameOffsetReference(
3401 MF: *MF, ObjectOffset: FirstTagStore.Offset, isFixed: false /*isFixed*/,
3402 StackID: TargetStackID::Default /*StackID*/, FrameReg&: Reg,
3403 /*PreferFP=*/false, /*ForSimm=*/true);
3404 FrameReg = Reg;
3405 FrameRegUpdate = std::nullopt;
3406
3407 mergeMemRefs(TSE: TagStores, MemRefs&: CombinedMemRefs);
3408
3409 LLVM_DEBUG({
3410 dbgs() << "Replacing adjacent STG instructions:\n";
3411 for (const auto &Instr : TagStores) {
3412 dbgs() << " " << *Instr.MI;
3413 }
3414 });
3415
3416 // Size threshold where a loop becomes shorter than a linear sequence of
3417 // tagging instructions.
3418 const int kSetTagLoopThreshold = 176;
3419 if (Size < kSetTagLoopThreshold) {
3420 if (TagStores.size() < 2)
3421 return;
3422 emitUnrolled(InsertI);
3423 } else {
3424 MachineInstr *UpdateInstr = nullptr;
3425 int64_t TotalOffset = 0;
3426 if (TryMergeSPUpdate) {
3427 // See if we can merge base register update into the STGloop.
3428 // This is done in AArch64LoadStoreOptimizer for "normal" stores,
3429 // but STGloop is way too unusual for that, and also it only
3430 // realistically happens in function epilogue. Also, STGloop is expanded
3431 // before that pass.
3432 if (InsertI != MBB->end() &&
3433 canMergeRegUpdate(II: InsertI, Reg: FrameReg, Size: FrameRegOffset.getFixed() + Size,
3434 TotalOffset: &TotalOffset)) {
3435 UpdateInstr = &*InsertI++;
3436 LLVM_DEBUG(dbgs() << "Folding SP update into loop:\n "
3437 << *UpdateInstr);
3438 }
3439 }
3440
3441 if (!UpdateInstr && TagStores.size() < 2)
3442 return;
3443
3444 if (UpdateInstr) {
3445 FrameRegUpdate = TotalOffset;
3446 FrameRegUpdateFlags = UpdateInstr->getFlags();
3447 }
3448 emitLoop(InsertI);
3449 if (UpdateInstr)
3450 UpdateInstr->eraseFromParent();
3451 }
3452
3453 for (auto &TS : TagStores)
3454 TS.MI->eraseFromParent();
3455}
3456
3457bool isMergeableStackTaggingInstruction(MachineInstr &MI, int64_t &Offset,
3458 int64_t &Size, bool &ZeroData) {
3459 MachineFunction &MF = *MI.getParent()->getParent();
3460 const MachineFrameInfo &MFI = MF.getFrameInfo();
3461
3462 unsigned Opcode = MI.getOpcode();
3463 ZeroData = (Opcode == AArch64::STZGloop || Opcode == AArch64::STZGi ||
3464 Opcode == AArch64::STZ2Gi);
3465
3466 if (Opcode == AArch64::STGloop || Opcode == AArch64::STZGloop) {
3467 if (!MI.getOperand(i: 0).isDead() || !MI.getOperand(i: 1).isDead())
3468 return false;
3469 if (!MI.getOperand(i: 2).isImm() || !MI.getOperand(i: 3).isFI())
3470 return false;
3471 Offset = MFI.getObjectOffset(ObjectIdx: MI.getOperand(i: 3).getIndex());
3472 Size = MI.getOperand(i: 2).getImm();
3473 return true;
3474 }
3475
3476 if (Opcode == AArch64::STGi || Opcode == AArch64::STZGi)
3477 Size = 16;
3478 else if (Opcode == AArch64::ST2Gi || Opcode == AArch64::STZ2Gi)
3479 Size = 32;
3480 else
3481 return false;
3482
3483 if (MI.getOperand(i: 0).getReg() != AArch64::SP || !MI.getOperand(i: 1).isFI())
3484 return false;
3485
3486 Offset = MFI.getObjectOffset(ObjectIdx: MI.getOperand(i: 1).getIndex()) +
3487 16 * MI.getOperand(i: 2).getImm();
3488 return true;
3489}
3490
3491static size_t countAvailableScavengerSlots(LivePhysRegs &LiveRegs,
3492 MachineRegisterInfo &MRI,
3493 RegScavenger *RS) {
3494 auto FreeGPRs =
3495 llvm::count_if(Range: AArch64::GPR64RegClass, P: [&LiveRegs, &MRI](auto Reg) {
3496 return LiveRegs.available(MRI, Reg);
3497 });
3498
3499 size_t NumEmergencySlots = 0;
3500 if (RS)
3501 NumEmergencySlots = RS->getNumScavengingFrameIndices();
3502
3503 return FreeGPRs + NumEmergencySlots;
3504}
3505
3506// Detect a run of memory tagging instructions for adjacent stack frame slots,
3507// and replace them with a shorter instruction sequence:
3508// * replace STG + STG with ST2G
3509// * replace STGloop + STGloop with STGloop
3510// This code needs to run when stack slot offsets are already known, but before
3511// FrameIndex operands in STG instructions are eliminated.
3512MachineBasicBlock::iterator tryMergeAdjacentSTG(MachineBasicBlock::iterator II,
3513 const AArch64FrameLowering *TFI,
3514 RegScavenger *RS) {
3515 bool FirstZeroData;
3516 int64_t Size, Offset;
3517 MachineInstr &MI = *II;
3518 MachineBasicBlock *MBB = MI.getParent();
3519 MachineBasicBlock::iterator NextI = ++II;
3520 if (&MI == &MBB->instr_back())
3521 return II;
3522 if (!isMergeableStackTaggingInstruction(MI, Offset, Size, ZeroData&: FirstZeroData))
3523 return II;
3524
3525 SmallVector<TagStoreInstr, 4> Instrs;
3526 Instrs.emplace_back(Args: &MI, Args&: Offset, Args&: Size);
3527
3528 constexpr int kScanLimit = 10;
3529 int Count = 0;
3530 for (MachineBasicBlock::iterator E = MBB->end();
3531 NextI != E && Count < kScanLimit; ++NextI) {
3532 MachineInstr &MI = *NextI;
3533 bool ZeroData;
3534 int64_t Size, Offset;
3535 // Collect instructions that update memory tags with a FrameIndex operand
3536 // and (when applicable) constant size, and whose output registers are dead
3537 // (the latter is almost always the case in practice). Since these
3538 // instructions effectively have no inputs or outputs, we are free to skip
3539 // any non-aliasing instructions in between without tracking used registers.
3540 if (isMergeableStackTaggingInstruction(MI, Offset, Size, ZeroData)) {
3541 if (ZeroData != FirstZeroData)
3542 break;
3543 Instrs.emplace_back(Args: &MI, Args&: Offset, Args&: Size);
3544 continue;
3545 }
3546
3547 // Only count non-transient, non-tagging instructions toward the scan
3548 // limit.
3549 if (!MI.isTransient())
3550 ++Count;
3551
3552 // Just in case, stop before the epilogue code starts.
3553 if (MI.getFlag(Flag: MachineInstr::FrameSetup) ||
3554 MI.getFlag(Flag: MachineInstr::FrameDestroy))
3555 break;
3556
3557 // Reject anything that may alias the collected instructions.
3558 if (MI.mayLoadOrStore() || MI.hasUnmodeledSideEffects() || MI.isCall())
3559 break;
3560 }
3561
3562 // New code will be inserted after the last tagging instruction we've found.
3563 MachineBasicBlock::iterator InsertI = Instrs.back().MI;
3564
3565 // All the gathered stack tag instructions are merged and placed after
3566 // last tag store in the list. The check should be made if the nzcv
3567 // flag is live at the point where we are trying to insert. Otherwise
3568 // the nzcv flag might get clobbered if any stg loops are present.
3569
3570 // FIXME : This approach of bailing out from merge is conservative in
3571 // some ways like even if stg loops are not present after merge the
3572 // insert list, this liveness check is done (which is not needed).
3573 LivePhysRegs LiveRegs(*(MBB->getParent()->getSubtarget().getRegisterInfo()));
3574 LiveRegs.addLiveOuts(MBB: *MBB);
3575 for (auto I = MBB->rbegin();; ++I) {
3576 MachineInstr &MI = *I;
3577 if (MI == InsertI)
3578 break;
3579 LiveRegs.stepBackward(MI: *I);
3580 }
3581 InsertI++;
3582 if (LiveRegs.contains(Reg: AArch64::NZCV))
3583 return InsertI;
3584
3585 // Emitting an MTE loop requires two physical registers (BaseReg and
3586 // SizeReg). If the function is under register pressure, the register
3587 // scavenger will crash trying to allocate them. If we don't have at least
3588 // two free slots (free registers + emergency slots), bail out and fall back
3589 // to the unrolled sequence.
3590 if (countAvailableScavengerSlots(LiveRegs, MRI&: MBB->getParent()->getRegInfo(),
3591 RS) < 2) {
3592 LLVM_DEBUG(
3593 dbgs() << "Failed to merge MTE stack tagging instructions into loop "
3594 << "due to high register pressure.\n");
3595 return InsertI;
3596 }
3597
3598 llvm::stable_sort(Range&: Instrs,
3599 C: [](const TagStoreInstr &Left, const TagStoreInstr &Right) {
3600 return Left.Offset < Right.Offset;
3601 });
3602
3603 // Make sure that we don't have any overlapping stores.
3604 int64_t CurOffset = Instrs[0].Offset;
3605 for (auto &Instr : Instrs) {
3606 if (CurOffset > Instr.Offset)
3607 return NextI;
3608 CurOffset = Instr.Offset + Instr.Size;
3609 }
3610
3611 // Find contiguous runs of tagged memory and emit shorter instruction
3612 // sequences for them when possible.
3613 TagStoreEdit TSE(MBB, FirstZeroData);
3614 std::optional<int64_t> EndOffset;
3615 for (auto &Instr : Instrs) {
3616 if (EndOffset && *EndOffset != Instr.Offset) {
3617 // Found a gap.
3618 TSE.emitCode(InsertI, TFI, /*TryMergeSPUpdate = */ false);
3619 TSE.clear();
3620 }
3621
3622 TSE.addInstruction(I: Instr);
3623 EndOffset = Instr.Offset + Instr.Size;
3624 }
3625
3626 const MachineFunction *MF = MBB->getParent();
3627 // Multiple FP/SP updates in a loop cannot be described by CFI instructions.
3628 TSE.emitCode(
3629 InsertI, TFI, /*TryMergeSPUpdate = */
3630 !MF->getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF: *MF));
3631
3632 return InsertI;
3633}
3634} // namespace
3635
3636void AArch64FrameLowering::processFunctionBeforeFrameIndicesReplaced(
3637 MachineFunction &MF, RegScavenger *RS = nullptr) const {
3638 for (auto &BB : MF)
3639 for (MachineBasicBlock::iterator II = BB.begin(); II != BB.end();) {
3640 if (StackTaggingMergeSetTag)
3641 II = tryMergeAdjacentSTG(II, TFI: this, RS);
3642 }
3643
3644 // By the time this method is called, most of the prologue/epilogue code is
3645 // already emitted, whether its location was affected by the shrink-wrapping
3646 // optimization or not.
3647 if (!MF.getFunction().hasFnAttribute(Kind: Attribute::Naked) &&
3648 shouldSignReturnAddressEverywhere(MF))
3649 emitPacRetPlusLeafHardening(MF);
3650}
3651
3652/// For Win64 AArch64 EH, the offset to the Unwind object is from the SP
3653/// before the update. This is easily retrieved as it is exactly the offset
3654/// that is set in processFunctionBeforeFrameFinalized.
3655StackOffset AArch64FrameLowering::getFrameIndexReferencePreferSP(
3656 const MachineFunction &MF, int FI, Register &FrameReg,
3657 bool IgnoreSPUpdates) const {
3658 const MachineFrameInfo &MFI = MF.getFrameInfo();
3659 if (IgnoreSPUpdates) {
3660 LLVM_DEBUG(dbgs() << "Offset from the SP for " << FI << " is "
3661 << MFI.getObjectOffset(FI) << "\n");
3662 FrameReg = AArch64::SP;
3663 return StackOffset::getFixed(Fixed: MFI.getObjectOffset(ObjectIdx: FI));
3664 }
3665
3666 // Go to common code if we cannot provide sp + offset.
3667 if (MFI.hasVarSizedObjects() ||
3668 MF.getInfo<AArch64FunctionInfo>()->hasSVEStackSize() ||
3669 MF.getSubtarget().getRegisterInfo()->hasStackRealignment(MF))
3670 return getFrameIndexReference(MF, FI, FrameReg);
3671
3672 FrameReg = AArch64::SP;
3673 return getStackOffset(MF, ObjectOffset: MFI.getObjectOffset(ObjectIdx: FI));
3674}
3675
3676/// The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
3677/// the parent's frame pointer
3678unsigned AArch64FrameLowering::getWinEHParentFrameOffset(
3679 const MachineFunction &MF) const {
3680 return 0;
3681}
3682
3683/// Funclets only need to account for space for the callee saved registers,
3684/// as the locals are accounted for in the parent's stack frame.
3685unsigned AArch64FrameLowering::getWinEHFuncletFrameSize(
3686 const MachineFunction &MF) const {
3687 // This is the size of the pushed CSRs.
3688 unsigned CSSize =
3689 MF.getInfo<AArch64FunctionInfo>()->getCalleeSavedStackSize();
3690 // This is the amount of stack a funclet needs to allocate.
3691 return alignTo(Size: CSSize + MF.getFrameInfo().getMaxCallFrameSize(),
3692 A: getStackAlign());
3693}
3694
3695namespace {
3696struct FrameObject {
3697 bool IsValid = false;
3698 // Index of the object in MFI.
3699 int ObjectIndex = 0;
3700 // Group ID this object belongs to.
3701 int GroupIndex = -1;
3702 // This object should be placed first (closest to SP).
3703 bool ObjectFirst = false;
3704 // This object's group (which always contains the object with
3705 // ObjectFirst==true) should be placed first.
3706 bool GroupFirst = false;
3707
3708 // Used to distinguish between FP and GPR accesses. The values are decided so
3709 // that they sort FPR < Hazard < GPR and they can be or'd together.
3710 unsigned Accesses = 0;
3711 enum { AccessFPR = 1, AccessHazard = 2, AccessGPR = 4 };
3712};
3713
3714class GroupBuilder {
3715 SmallVector<int, 8> CurrentMembers;
3716 int NextGroupIndex = 0;
3717 std::vector<FrameObject> &Objects;
3718
3719public:
3720 GroupBuilder(std::vector<FrameObject> &Objects) : Objects(Objects) {}
3721 void AddMember(int Index) { CurrentMembers.push_back(Elt: Index); }
3722 void EndCurrentGroup() {
3723 if (CurrentMembers.size() > 1) {
3724 // Create a new group with the current member list. This might remove them
3725 // from their pre-existing groups. That's OK, dealing with overlapping
3726 // groups is too hard and unlikely to make a difference.
3727 LLVM_DEBUG(dbgs() << "group:");
3728 for (int Index : CurrentMembers) {
3729 Objects[Index].GroupIndex = NextGroupIndex;
3730 LLVM_DEBUG(dbgs() << " " << Index);
3731 }
3732 LLVM_DEBUG(dbgs() << "\n");
3733 NextGroupIndex++;
3734 }
3735 CurrentMembers.clear();
3736 }
3737};
3738
3739bool FrameObjectCompare(const FrameObject &A, const FrameObject &B) {
3740 // Objects at a lower index are closer to FP; objects at a higher index are
3741 // closer to SP.
3742 //
3743 // For consistency in our comparison, all invalid objects are placed
3744 // at the end. This also allows us to stop walking when we hit the
3745 // first invalid item after it's all sorted.
3746 //
3747 // If we want to include a stack hazard region, order FPR accesses < the
3748 // hazard object < GPRs accesses in order to create a separation between the
3749 // two. For the Accesses field 1 = FPR, 2 = Hazard Object, 4 = GPR.
3750 //
3751 // Otherwise the "first" object goes first (closest to SP), followed by the
3752 // members of the "first" group.
3753 //
3754 // The rest are sorted by the group index to keep the groups together.
3755 // Higher numbered groups are more likely to be around longer (i.e. untagged
3756 // in the function epilogue and not at some earlier point). Place them closer
3757 // to SP.
3758 //
3759 // If all else equal, sort by the object index to keep the objects in the
3760 // original order.
3761 return std::make_tuple(args: !A.IsValid, args: A.Accesses, args: A.ObjectFirst, args: A.GroupFirst,
3762 args: A.GroupIndex, args: A.ObjectIndex) <
3763 std::make_tuple(args: !B.IsValid, args: B.Accesses, args: B.ObjectFirst, args: B.GroupFirst,
3764 args: B.GroupIndex, args: B.ObjectIndex);
3765}
3766} // namespace
3767
3768void AArch64FrameLowering::orderFrameObjects(
3769 const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {
3770 const AArch64FunctionInfo &AFI = *MF.getInfo<AArch64FunctionInfo>();
3771
3772 if ((!OrderFrameObjects && !AFI.hasSplitSVEObjects()) ||
3773 ObjectsToAllocate.empty())
3774 return;
3775
3776 const MachineFrameInfo &MFI = MF.getFrameInfo();
3777 std::vector<FrameObject> FrameObjects(MFI.getObjectIndexEnd());
3778 for (auto &Obj : ObjectsToAllocate) {
3779 FrameObjects[Obj].IsValid = true;
3780 FrameObjects[Obj].ObjectIndex = Obj;
3781 }
3782
3783 // Identify FPR vs GPR slots for hazards, and stack slots that are tagged at
3784 // the same time.
3785 GroupBuilder GB(FrameObjects);
3786 for (auto &MBB : MF) {
3787 for (auto &MI : MBB) {
3788 if (MI.isDebugInstr())
3789 continue;
3790
3791 if (AFI.hasStackHazardSlotIndex()) {
3792 std::optional<int> FI = getLdStFrameID(MI, MFI);
3793 if (FI && *FI >= 0 && *FI < (int)FrameObjects.size()) {
3794 if (MFI.getStackID(ObjectIdx: *FI) == TargetStackID::ScalableVector ||
3795 AArch64InstrInfo::isFpOrNEON(MI))
3796 FrameObjects[*FI].Accesses |= FrameObject::AccessFPR;
3797 else
3798 FrameObjects[*FI].Accesses |= FrameObject::AccessGPR;
3799 }
3800 }
3801
3802 int OpIndex;
3803 switch (MI.getOpcode()) {
3804 case AArch64::STGloop:
3805 case AArch64::STZGloop:
3806 OpIndex = 3;
3807 break;
3808 case AArch64::STGi:
3809 case AArch64::STZGi:
3810 case AArch64::ST2Gi:
3811 case AArch64::STZ2Gi:
3812 OpIndex = 1;
3813 break;
3814 default:
3815 OpIndex = -1;
3816 }
3817
3818 int TaggedFI = -1;
3819 if (OpIndex >= 0) {
3820 const MachineOperand &MO = MI.getOperand(i: OpIndex);
3821 if (MO.isFI()) {
3822 int FI = MO.getIndex();
3823 if (FI >= 0 && FI < MFI.getObjectIndexEnd() &&
3824 FrameObjects[FI].IsValid)
3825 TaggedFI = FI;
3826 }
3827 }
3828
3829 // If this is a stack tagging instruction for a slot that is not part of a
3830 // group yet, either start a new group or add it to the current one.
3831 if (TaggedFI >= 0)
3832 GB.AddMember(Index: TaggedFI);
3833 else
3834 GB.EndCurrentGroup();
3835 }
3836 // Groups should never span multiple basic blocks.
3837 GB.EndCurrentGroup();
3838 }
3839
3840 if (AFI.hasStackHazardSlotIndex()) {
3841 FrameObjects[AFI.getStackHazardSlotIndex()].Accesses =
3842 FrameObject::AccessHazard;
3843 // If a stack object is unknown or both GPR and FPR, sort it into GPR.
3844 for (auto &Obj : FrameObjects)
3845 if (!Obj.Accesses ||
3846 Obj.Accesses == (FrameObject::AccessGPR | FrameObject::AccessFPR))
3847 Obj.Accesses = FrameObject::AccessGPR;
3848 }
3849
3850 // If the function's tagged base pointer is pinned to a stack slot, we want to
3851 // put that slot first when possible. This will likely place it at SP + 0,
3852 // and save one instruction when generating the base pointer because IRG does
3853 // not allow an immediate offset.
3854 std::optional<int> TBPI = AFI.getTaggedBasePointerIndex();
3855 if (TBPI) {
3856 FrameObjects[*TBPI].ObjectFirst = true;
3857 FrameObjects[*TBPI].GroupFirst = true;
3858 int FirstGroupIndex = FrameObjects[*TBPI].GroupIndex;
3859 if (FirstGroupIndex >= 0)
3860 for (FrameObject &Object : FrameObjects)
3861 if (Object.GroupIndex == FirstGroupIndex)
3862 Object.GroupFirst = true;
3863 }
3864
3865 llvm::stable_sort(Range&: FrameObjects, C: FrameObjectCompare);
3866
3867 int i = 0;
3868 for (auto &Obj : FrameObjects) {
3869 // All invalid items are sorted at the end, so it's safe to stop.
3870 if (!Obj.IsValid)
3871 break;
3872 ObjectsToAllocate[i++] = Obj.ObjectIndex;
3873 }
3874
3875 LLVM_DEBUG({
3876 dbgs() << "Final frame order:\n";
3877 for (auto &Obj : FrameObjects) {
3878 if (!Obj.IsValid)
3879 break;
3880 dbgs() << " " << Obj.ObjectIndex << ": group " << Obj.GroupIndex;
3881 if (Obj.ObjectFirst)
3882 dbgs() << ", first";
3883 if (Obj.GroupFirst)
3884 dbgs() << ", group-first";
3885 dbgs() << "\n";
3886 }
3887 });
3888}
3889
3890/// Emit a loop to decrement SP until it is equal to TargetReg, with probes at
3891/// least every ProbeSize bytes. Returns an iterator of the first instruction
3892/// after the loop. The difference between SP and TargetReg must be an exact
3893/// multiple of ProbeSize.
3894MachineBasicBlock::iterator
3895AArch64FrameLowering::inlineStackProbeLoopExactMultiple(
3896 MachineBasicBlock::iterator MBBI, int64_t ProbeSize,
3897 Register TargetReg) const {
3898 MachineBasicBlock &MBB = *MBBI->getParent();
3899 MachineFunction &MF = *MBB.getParent();
3900 const AArch64InstrInfo *TII =
3901 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
3902 DebugLoc DL = MBB.findDebugLoc(MBBI);
3903
3904 MachineFunction::iterator MBBInsertPoint = std::next(x: MBB.getIterator());
3905 MachineBasicBlock *LoopMBB = MF.CreateMachineBasicBlock(BB: MBB.getBasicBlock());
3906 MF.insert(MBBI: MBBInsertPoint, MBB: LoopMBB);
3907 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(BB: MBB.getBasicBlock());
3908 MF.insert(MBBI: MBBInsertPoint, MBB: ExitMBB);
3909
3910 // SUB SP, SP, #ProbeSize (or equivalent if ProbeSize is not encodable
3911 // in SUB).
3912 emitFrameOffset(MBB&: *LoopMBB, MBBI: LoopMBB->end(), DL, DestReg: AArch64::SP, SrcReg: AArch64::SP,
3913 Offset: StackOffset::getFixed(Fixed: -ProbeSize), TII,
3914 MachineInstr::FrameSetup);
3915 // LDR XZR, [SP]
3916 BuildMI(BB&: *LoopMBB, I: LoopMBB->end(), MIMD: DL, MCID: TII->get(Opcode: AArch64::LDRXui))
3917 .addDef(RegNo: AArch64::XZR)
3918 .addReg(RegNo: AArch64::SP)
3919 .addImm(Val: 0)
3920 .addMemOperand(MMO: MF.getMachineMemOperand(
3921 PtrInfo: MachinePointerInfo::getUnknownStack(MF),
3922 F: MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, Size: 8,
3923 BaseAlignment: Align(8)))
3924 .setMIFlags(MachineInstr::FrameSetup);
3925 // CMP SP, TargetReg
3926 BuildMI(BB&: *LoopMBB, I: LoopMBB->end(), MIMD: DL, MCID: TII->get(Opcode: AArch64::SUBSXrx64),
3927 DestReg: AArch64::XZR)
3928 .addReg(RegNo: AArch64::SP)
3929 .addReg(RegNo: TargetReg)
3930 .addImm(Val: AArch64_AM::getArithExtendImm(ET: AArch64_AM::UXTX, Imm: 0))
3931 .setMIFlags(MachineInstr::FrameSetup);
3932 // B.CC Loop
3933 BuildMI(BB&: *LoopMBB, I: LoopMBB->end(), MIMD: DL, MCID: TII->get(Opcode: AArch64::Bcc))
3934 .addImm(Val: AArch64CC::NE)
3935 .addMBB(MBB: LoopMBB)
3936 .setMIFlags(MachineInstr::FrameSetup);
3937
3938 LoopMBB->addSuccessor(Succ: ExitMBB);
3939 LoopMBB->addSuccessor(Succ: LoopMBB);
3940 // Synthesize the exit MBB.
3941 ExitMBB->splice(Where: ExitMBB->end(), Other: &MBB, From: MBBI, To: MBB.end());
3942 ExitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &MBB);
3943 MBB.addSuccessor(Succ: LoopMBB);
3944 // Update liveins.
3945 fullyRecomputeLiveIns(MBBs: {ExitMBB, LoopMBB});
3946
3947 return ExitMBB->begin();
3948}
3949
3950void AArch64FrameLowering::inlineStackProbeFixed(
3951 MachineBasicBlock::iterator MBBI, Register ScratchReg, int64_t FrameSize,
3952 StackOffset CFAOffset) const {
3953 MachineBasicBlock *MBB = MBBI->getParent();
3954 MachineFunction &MF = *MBB->getParent();
3955 const AArch64InstrInfo *TII =
3956 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
3957 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
3958 bool EmitAsyncCFI = AFI->needsAsyncDwarfUnwindInfo(MF);
3959 bool HasFP = hasFP(MF);
3960
3961 DebugLoc DL;
3962 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
3963 int64_t NumBlocks = FrameSize / ProbeSize;
3964 int64_t ResidualSize = FrameSize % ProbeSize;
3965
3966 LLVM_DEBUG(dbgs() << "Stack probing: total " << FrameSize << " bytes, "
3967 << NumBlocks << " blocks of " << ProbeSize
3968 << " bytes, plus " << ResidualSize << " bytes\n");
3969
3970 // Decrement SP by NumBlock * ProbeSize bytes, with either unrolled or
3971 // ordinary loop.
3972 if (NumBlocks <= AArch64::StackProbeMaxLoopUnroll) {
3973 for (int i = 0; i < NumBlocks; ++i) {
3974 // SUB SP, SP, #ProbeSize (or equivalent if ProbeSize is not
3975 // encodable in a SUB).
3976 emitFrameOffset(MBB&: *MBB, MBBI, DL, DestReg: AArch64::SP, SrcReg: AArch64::SP,
3977 Offset: StackOffset::getFixed(Fixed: -ProbeSize), TII,
3978 MachineInstr::FrameSetup, SetNZCV: false, NeedsWinCFI: false, HasWinCFI: nullptr,
3979 EmitCFAOffset: EmitAsyncCFI && !HasFP, InitialOffset: CFAOffset);
3980 CFAOffset += StackOffset::getFixed(Fixed: ProbeSize);
3981 // LDR XZR, [SP]
3982 BuildMI(BB&: *MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: AArch64::LDRXui))
3983 .addDef(RegNo: AArch64::XZR)
3984 .addReg(RegNo: AArch64::SP)
3985 .addImm(Val: 0)
3986 .addMemOperand(MMO: MF.getMachineMemOperand(
3987 PtrInfo: MachinePointerInfo::getUnknownStack(MF),
3988 F: MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, Size: 8,
3989 BaseAlignment: Align(8)))
3990 .setMIFlags(MachineInstr::FrameSetup);
3991 }
3992 } else if (NumBlocks != 0) {
3993 // SUB ScratchReg, SP, #FrameSize (or equivalent if FrameSize is not
3994 // encodable in ADD). ScrathReg may temporarily become the CFA register.
3995 emitFrameOffset(MBB&: *MBB, MBBI, DL, DestReg: ScratchReg, SrcReg: AArch64::SP,
3996 Offset: StackOffset::getFixed(Fixed: -ProbeSize * NumBlocks), TII,
3997 MachineInstr::FrameSetup, SetNZCV: false, NeedsWinCFI: false, HasWinCFI: nullptr,
3998 EmitCFAOffset: EmitAsyncCFI && !HasFP, InitialOffset: CFAOffset);
3999 CFAOffset += StackOffset::getFixed(Fixed: ProbeSize * NumBlocks);
4000 MBBI = inlineStackProbeLoopExactMultiple(MBBI, ProbeSize, TargetReg: ScratchReg);
4001 MBB = MBBI->getParent();
4002 if (EmitAsyncCFI && !HasFP) {
4003 // Set the CFA register back to SP.
4004 CFIInstBuilder(*MBB, MBBI, MachineInstr::FrameSetup)
4005 .buildDefCFARegister(Reg: AArch64::SP);
4006 }
4007 }
4008
4009 if (ResidualSize != 0) {
4010 // SUB SP, SP, #ResidualSize (or equivalent if ResidualSize is not encodable
4011 // in SUB).
4012 emitFrameOffset(MBB&: *MBB, MBBI, DL, DestReg: AArch64::SP, SrcReg: AArch64::SP,
4013 Offset: StackOffset::getFixed(Fixed: -ResidualSize), TII,
4014 MachineInstr::FrameSetup, SetNZCV: false, NeedsWinCFI: false, HasWinCFI: nullptr,
4015 EmitCFAOffset: EmitAsyncCFI && !HasFP, InitialOffset: CFAOffset);
4016 if (ResidualSize > AArch64::StackProbeMaxUnprobedStack) {
4017 // LDR XZR, [SP]
4018 BuildMI(BB&: *MBB, I: MBBI, MIMD: DL, MCID: TII->get(Opcode: AArch64::LDRXui))
4019 .addDef(RegNo: AArch64::XZR)
4020 .addReg(RegNo: AArch64::SP)
4021 .addImm(Val: 0)
4022 .addMemOperand(MMO: MF.getMachineMemOperand(
4023 PtrInfo: MachinePointerInfo::getUnknownStack(MF),
4024 F: MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, Size: 8,
4025 BaseAlignment: Align(8)))
4026 .setMIFlags(MachineInstr::FrameSetup);
4027 }
4028 }
4029}
4030
4031void AArch64FrameLowering::inlineStackProbe(MachineFunction &MF,
4032 MachineBasicBlock &MBB) const {
4033 // Get the instructions that need to be replaced. We emit at most two of
4034 // these. Remember them in order to avoid complications coming from the need
4035 // to traverse the block while potentially creating more blocks.
4036 SmallVector<MachineInstr *, 4> ToReplace;
4037 for (MachineInstr &MI : MBB)
4038 if (MI.getOpcode() == AArch64::PROBED_STACKALLOC ||
4039 MI.getOpcode() == AArch64::PROBED_STACKALLOC_VAR)
4040 ToReplace.push_back(Elt: &MI);
4041
4042 for (MachineInstr *MI : ToReplace) {
4043 if (MI->getOpcode() == AArch64::PROBED_STACKALLOC) {
4044 Register ScratchReg = MI->getOperand(i: 0).getReg();
4045 int64_t FrameSize = MI->getOperand(i: 1).getImm();
4046 StackOffset CFAOffset = StackOffset::get(Fixed: MI->getOperand(i: 2).getImm(),
4047 Scalable: MI->getOperand(i: 3).getImm());
4048 inlineStackProbeFixed(MBBI: MI->getIterator(), ScratchReg, FrameSize,
4049 CFAOffset);
4050 } else {
4051 assert(MI->getOpcode() == AArch64::PROBED_STACKALLOC_VAR &&
4052 "Stack probe pseudo-instruction expected");
4053 const AArch64InstrInfo *TII =
4054 MI->getMF()->getSubtarget<AArch64Subtarget>().getInstrInfo();
4055 Register TargetReg = MI->getOperand(i: 0).getReg();
4056 (void)TII->probedStackAlloc(MBBI: MI->getIterator(), TargetReg, FrameSetup: true);
4057 }
4058 MI->eraseFromParent();
4059 }
4060}
4061
4062struct StackAccess {
4063 enum AccessType {
4064 NotAccessed = 0, // Stack object not accessed by load/store instructions.
4065 GPR = 1 << 0, // A general purpose register.
4066 PPR = 1 << 1, // A predicate register.
4067 FPR = 1 << 2, // A floating point/Neon/SVE register.
4068 };
4069
4070 int Idx;
4071 StackOffset Offset;
4072 int64_t Size;
4073 unsigned AccessTypes;
4074
4075 StackAccess() : Idx(0), Offset(), Size(0), AccessTypes(NotAccessed) {}
4076
4077 bool operator<(const StackAccess &Rhs) const {
4078 return std::make_tuple(args: start(), args: Idx) <
4079 std::make_tuple(args: Rhs.start(), args: Rhs.Idx);
4080 }
4081
4082 bool isCPU() const {
4083 // Predicate register load and store instructions execute on the CPU.
4084 return AccessTypes & (AccessType::GPR | AccessType::PPR);
4085 }
4086 bool isSME() const { return AccessTypes & AccessType::FPR; }
4087 bool isMixed() const { return isCPU() && isSME(); }
4088
4089 int64_t start() const { return Offset.getFixed() + Offset.getScalable(); }
4090 int64_t end() const { return start() + Size; }
4091
4092 std::string getTypeString() const {
4093 switch (AccessTypes) {
4094 case AccessType::FPR:
4095 return "FPR";
4096 case AccessType::PPR:
4097 return "PPR";
4098 case AccessType::GPR:
4099 return "GPR";
4100 case AccessType::NotAccessed:
4101 return "NA";
4102 default:
4103 return "Mixed";
4104 }
4105 }
4106
4107 void print(raw_ostream &OS) const {
4108 OS << getTypeString() << " stack object at [SP"
4109 << (Offset.getFixed() < 0 ? "" : "+") << Offset.getFixed();
4110 if (Offset.getScalable())
4111 OS << (Offset.getScalable() < 0 ? "" : "+") << Offset.getScalable()
4112 << " * vscale";
4113 OS << "]";
4114 }
4115};
4116
4117static inline raw_ostream &operator<<(raw_ostream &OS, const StackAccess &SA) {
4118 SA.print(OS);
4119 return OS;
4120}
4121
4122void AArch64FrameLowering::emitRemarks(
4123 const MachineFunction &MF, MachineOptimizationRemarkEmitter *ORE) const {
4124
4125 auto *AFI = MF.getInfo<AArch64FunctionInfo>();
4126 if (AFI->getSMEFnAttrs().hasNonStreamingInterfaceAndBody())
4127 return;
4128
4129 unsigned StackHazardSize = getStackHazardSize(MF);
4130 const uint64_t HazardSize =
4131 (StackHazardSize) ? StackHazardSize : StackHazardRemarkSize;
4132
4133 if (HazardSize == 0)
4134 return;
4135
4136 const MachineFrameInfo &MFI = MF.getFrameInfo();
4137 // Bail if function has no stack objects.
4138 if (!MFI.hasStackObjects())
4139 return;
4140
4141 std::vector<StackAccess> StackAccesses(MFI.getNumObjects());
4142
4143 size_t NumFPLdSt = 0;
4144 size_t NumNonFPLdSt = 0;
4145
4146 // Collect stack accesses via Load/Store instructions.
4147 for (const MachineBasicBlock &MBB : MF) {
4148 for (const MachineInstr &MI : MBB) {
4149 if (!MI.mayLoadOrStore() || MI.getNumMemOperands() < 1)
4150 continue;
4151 for (MachineMemOperand *MMO : MI.memoperands()) {
4152 std::optional<int> FI = getMMOFrameID(MMO, MFI);
4153 if (FI && !MFI.isDeadObjectIndex(ObjectIdx: *FI)) {
4154 int FrameIdx = *FI;
4155
4156 size_t ArrIdx = FrameIdx + MFI.getNumFixedObjects();
4157 if (StackAccesses[ArrIdx].AccessTypes == StackAccess::NotAccessed) {
4158 StackAccesses[ArrIdx].Idx = FrameIdx;
4159 StackAccesses[ArrIdx].Offset =
4160 getFrameIndexReferenceFromSP(MF, FI: FrameIdx);
4161 StackAccesses[ArrIdx].Size = MFI.getObjectSize(ObjectIdx: FrameIdx);
4162 }
4163
4164 unsigned RegTy = StackAccess::AccessType::GPR;
4165 if (MFI.hasScalableStackID(ObjectIdx: FrameIdx))
4166 RegTy = isPPRAccess(MI) ? StackAccess::PPR : StackAccess::FPR;
4167 else if (AArch64InstrInfo::isFpOrNEON(MI))
4168 RegTy = StackAccess::FPR;
4169
4170 StackAccesses[ArrIdx].AccessTypes |= RegTy;
4171
4172 if (RegTy == StackAccess::FPR)
4173 ++NumFPLdSt;
4174 else
4175 ++NumNonFPLdSt;
4176 }
4177 }
4178 }
4179 }
4180
4181 if (NumFPLdSt == 0 || NumNonFPLdSt == 0)
4182 return;
4183
4184 llvm::sort(C&: StackAccesses);
4185 llvm::erase_if(C&: StackAccesses, P: [](const StackAccess &S) {
4186 return S.AccessTypes == StackAccess::NotAccessed;
4187 });
4188
4189 SmallVector<const StackAccess *> MixedObjects;
4190 SmallVector<std::pair<const StackAccess *, const StackAccess *>> HazardPairs;
4191
4192 if (StackAccesses.front().isMixed())
4193 MixedObjects.push_back(Elt: &StackAccesses.front());
4194
4195 for (auto It = StackAccesses.begin(), End = std::prev(x: StackAccesses.end());
4196 It != End; ++It) {
4197 const auto &First = *It;
4198 const auto &Second = *(It + 1);
4199
4200 if (Second.isMixed())
4201 MixedObjects.push_back(Elt: &Second);
4202
4203 if ((First.isSME() && Second.isCPU()) ||
4204 (First.isCPU() && Second.isSME())) {
4205 uint64_t Distance = static_cast<uint64_t>(Second.start() - First.end());
4206 if (Distance < HazardSize)
4207 HazardPairs.emplace_back(Args: &First, Args: &Second);
4208 }
4209 }
4210
4211 auto EmitRemark = [&](llvm::StringRef Str) {
4212 ORE->emit(RemarkBuilder: [&]() {
4213 auto R = MachineOptimizationRemarkAnalysis(
4214 "sme", "StackHazard", MF.getFunction().getSubprogram(), &MF.front());
4215 return R << formatv(Fmt: "stack hazard in '{0}': ", Vals: MF.getName()).str() << Str;
4216 });
4217 };
4218
4219 for (const auto &P : HazardPairs)
4220 EmitRemark(formatv(Fmt: "{0} is too close to {1}", Vals: *P.first, Vals: *P.second).str());
4221
4222 for (const auto *Obj : MixedObjects)
4223 EmitRemark(
4224 formatv(Fmt: "{0} accessed by both GP and FP instructions", Vals: *Obj).str());
4225}
4226