if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) {
if (needsStackRealignment(MF))
return true;
+
+ if (MF.getSubtarget<AArch64Subtarget>().hasSVE()) {
+ const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
+ // 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
// (closer to SP).
//
// The beginning works most reliably if we have a frame pointer.
+ // In the presence of any non-constant space between FP and locals,
+ // (e.g. in case of stack realignment or a scalable SVE area), it is
+ // better to use SP or BP.
const AArch64FrameLowering &TFI = *getFrameLowering(MF);
- return TFI.hasFP(MF);
+ const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
+ assert((!MF.getSubtarget<AArch64Subtarget>().hasSVE() ||
+ AFI->hasCalculatedStackSizeSVE()) &&
+ "Expected SVE area to be calculated by this point");
+ return TFI.hasFP(MF) && !needsStackRealignment(MF) && !AFI->getStackSizeSVE();
}
bool AArch64RegisterInfo::requiresFrameIndexScavenging(
--- /dev/null
+# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
+---
+# This test verifies that the emergency scavenging slot is located near
+# the SP when the stack is realigned.
+name: LateScavengingSlotRealignment
+# CHECK-LABEL: name: LateScavengingSlotRealignment
+# CHECK: bb.0:
+# CHECK: STRXui killed $[[SCRATCH:x[0-9]+]], $sp, 3
+# CHECK-NEXT: $[[SCRATCH]] = ADDXri $sp, 40, 0
+# CHECK-NEXT: STRXui $x0, killed $[[SCRATCH]], 4095
+# CHECK-NEXT: $[[SCRATCH]] = LDRXui $sp, 3
+# CHECK: bb.1:
+tracksRegLiveness: true
+frameInfo:
+ isFrameAddressTaken: true
+stack:
+ - { id: 0, size: 16, alignment: 16 }
+ - { id: 1, size: 32768, alignment: 32 }
+body: |
+ bb.0:
+ liveins: $x0, $x8
+ STRXui $x0, %stack.0, 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
+...
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...
-# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
+# RUN: llc -mattr=+sve -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
#
# Test allocation and deallocation of SVE objects on the stack,
# as well as using a combination of scalable and non-scalable
define void @test_address_sve_fp() nounwind { entry: unreachable }
define void @test_stack_arg_sve() nounwind { entry: unreachable }
define void @test_address_sve_out_of_range() nounwind { entry: unreachable }
- define void @test_address_gpr_vla_nobp() nounwind { entry: unreachable }
+ define void @test_address_gpr_vla() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_pregs_sve() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_zregs_sve() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_sve() nounwind { entry: unreachable }
RET_ReallyLR
---
...
-# Test that non-SVE objects are accessed from FP when there is no BP,
-# but the SP cannot be used because of variable-length arrays.
+# Test that non-SVE objects are accessed from BP when there are
+# variable length arrays, because it will be more expensive to
+# access from the FP when there are also SVE objects on the stack.
#
# +----------+ <- FP
# | %fstack.0| // 16 scalable bytes
# +----------+ <- @FP - 16 scalable bytes
# | %stack.0 | // 16 bytes
-# +----------+ <- @FP - 16 scalable bytes - 16b
+# +----------+ <- @BP
# : %stack.1 : // variable length
# +----------+ <- SP
-# CHECK-LABEL: name: test_address_gpr_vla_nobp
-# CHECK: bb.0.entry:
-# CHECK: $[[TMP:x[0-9]+]] = ADDVL_XXI $fp, -1
-# CHECK-NEXT: STURXi $xzr, killed $[[TMP]], -16
-# CHECK: RET_ReallyLR
-name: test_address_gpr_vla_nobp
+# CHECK-LABEL: name: test_address_gpr_vla
+# CHECK: bb.0.entry:
+# CHECK: STRXui $xzr, $x19, 0
+# CHECK: RET_ReallyLR
+name: test_address_gpr_vla
frameInfo:
maxAlignment: 16
fixedStack: