Index: llvm/lib/Target/AArch64/AArch64FrameLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -99,11 +99,12 @@ } } + int64_t estimateSVEStackObjectOffsets(const MachineFrameInfo &MF) const; + private: bool shouldCombineCSRLocalStackBump(MachineFunction &MF, unsigned StackBumpBytes) const; - int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const; int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF, int &MinCSFrameIndex, int &MaxCSFrameIndex) const; Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -154,6 +154,7 @@ #include "llvm/Target/TargetOptions.h" #include #include +#include #include #include @@ -2519,10 +2520,11 @@ // Fills in the first and last callee-saved frame indices into // Min/MaxCSFrameIndex, respectively. // Returns the size of the stack. -static int64_t determineSVEStackObjectOffsets(MachineFrameInfo &MFI, - int &MinCSFrameIndex, - int &MaxCSFrameIndex, - bool AssignOffsets) { +static int64_t +determineSVEStackObjectOffsets(const MachineFrameInfo &MFI, + int &MinCSFrameIndex, int &MaxCSFrameIndex, + std::function Assign, + std::function Align) { // First process all fixed stack objects. int64_t Offset = 0; for (int I = MFI.getObjectIndexBegin(); I != 0; ++I) @@ -2532,22 +2534,16 @@ Offset = FixedOffset; } - auto Assign = [&MFI](int FI, int64_t Offset) { - LLVM_DEBUG(dbgs() << "alloc FI(" << FI << ") at SP[" << Offset << "]\n"); - MFI.setObjectOffset(FI, Offset); - }; - // Then process all callee saved slots. if (getSVECalleeSaveSlotRange(MFI, MinCSFrameIndex, MaxCSFrameIndex)) { // Make sure to align the last callee save slot. - MFI.setObjectAlignment(MaxCSFrameIndex, 16U); + Align(MaxCSFrameIndex, 16U); // Assign offsets to the callee save slots. for (int I = MinCSFrameIndex; I <= MaxCSFrameIndex; ++I) { Offset += MFI.getObjectSize(I); Offset = alignTo(Offset, MFI.getObjectAlignment(I)); - if (AssignOffsets) - Assign(I, -Offset); + Assign(I, -Offset); } } @@ -2576,23 +2572,32 @@ "Alignment of scalable vectors > 16 bytes is not yet supported"); Offset = alignTo(Offset + MFI.getObjectSize(FI), Align); - if (AssignOffsets) - Assign(FI, -Offset); + Assign(FI, -Offset); } return Offset; } int64_t AArch64FrameLowering::estimateSVEStackObjectOffsets( - MachineFrameInfo &MFI) const { + const MachineFrameInfo &MFI) const { int MinCSFrameIndex, MaxCSFrameIndex; - return determineSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex, false); + auto Assign = [](int FI, int64_t Offset) {}; + auto Align = [](int FI, unsigned Align) {}; + return determineSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex, + Assign, Align); } int64_t AArch64FrameLowering::assignSVEStackObjectOffsets( MachineFrameInfo &MFI, int &MinCSFrameIndex, int &MaxCSFrameIndex) const { + auto Assign = [&MFI](int FI, int64_t Offset) { + LLVM_DEBUG(dbgs() << "alloc FI(" << FI << ") at SP[" << Offset << "]\n"); + MFI.setObjectOffset(FI, Offset); + }; + auto Align = [&MFI](int FI, unsigned Align) { + MFI.setObjectAlignment(FI, Align); + }; return determineSVEStackObjectOffsets(MFI, MinCSFrameIndex, MaxCSFrameIndex, - true); + Assign, Align); } void AArch64FrameLowering::processFunctionBeforeFrameFinalized( Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -277,6 +277,15 @@ if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) { if (needsStackRealignment(MF)) return true; + + if (MF.getSubtarget().hasSVE()) { + const AArch64FunctionInfo *AFI = MF.getInfo(); + // Frames that have variable sized objects and scalable SVE objects, + // should always use a basepointer. + if (!AFI->hasCalculatedStackSizeSVE() || AFI->getStackSizeSVE()) + return true; + } + // Conservatively estimate whether the negative offset from the frame // pointer will be sufficient to reach. If a function has a smallish // frame, it's less likely to have lots of spills and callee saved @@ -313,8 +322,9 @@ // (closer to SP). // // The beginning works most reliably if we have a frame pointer. + // In the presence of SVE however, it is better to use SP or BP. const AArch64FrameLowering &TFI = *getFrameLowering(MF); - return TFI.hasFP(MF); + return TFI.hasFP(MF) && !TFI.estimateSVEStackObjectOffsets(MF.getFrameInfo()); } bool AArch64RegisterInfo::requiresFrameIndexScavenging( Index: llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir @@ -0,0 +1,23 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog -mattr=+sve %s -o - | FileCheck %s +--- +# This test verifies that the basepointer is available in presence of SVE stack objects. +name: hasBasepointer +# CHECK-LABEL: name: hasBasepointer +# CHECK: bb.0: +# CHECK: $sp = frame-setup ADDVL_XXI $sp, -1 +# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 +# CHECK-NEXT: $x19 = ADDXri $sp, 0, 0 +# CHECK: STRXui $x0, $x19, 0 +tracksRegLiveness: true +frameInfo: + isFrameAddressTaken: true +stack: + - { id: 0, type: variable-sized, alignment: 1 } + - { id: 1, name: '', size: 16, alignment: 8 } + - { id: 2, stack-id: sve-vec, size: 16, alignment: 16 } +body: | + bb.0: + liveins: $x0 + STRXui $x0, %stack.1, 0 + RET_ReallyLR +... Index: llvm/test/CodeGen/AArch64/framelayout-sve-scavengingslot.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/framelayout-sve-scavengingslot.mir @@ -0,0 +1,28 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog -mattr=+sve %s -o - | FileCheck %s +--- +# This test verifies that the emergency scavenging slot is located near the SP/BP. +name: LateScavengingSlot +# CHECK-LABEL: name: LateScavengingSlot +# CHECK: bb.0: +# CHECK: $sp = frame-setup ADDVL_XXI $sp, -1 +# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 8, 12 +# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 +# CHECK: STRXui killed $[[SCRATCH:x[0-9]+]], $sp, 1 +# CHECK-NEXT: $[[SCRATCH]] = ADDVL_XXI $fp, -1 +# CHECK-NEXT: STRXui $x0, killed $[[SCRATCH]], 0 +# CHECK: bb.1: +tracksRegLiveness: true +frameInfo: + isFrameAddressTaken: true +stack: + - { id: 0, name: '', size: 32761, alignment: 8 } + - { id: 1, stack-id: sve-vec, size: 16, alignment: 16 } +body: | + bb.0: + liveins: $x0, $x8 + STRXui $x0, %stack.1, 0 + B %bb.1 + bb.1: + liveins: $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $lr + RET_ReallyLR implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27, implicit $x28, implicit $lr +...