diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -353,6 +353,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 @@ -389,8 +398,15 @@ // (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(); + assert((!MF.getSubtarget().hasSVE() || + AFI->hasCalculatedStackSizeSVE()) && + "Expected SVE area to be calculated by this point"); + return TFI.hasFP(MF) && !needsStackRealignment(MF) && !AFI->getStackSizeSVE(); } bool AArch64RegisterInfo::requiresFrameIndexScavenging( diff --git a/llvm/test/CodeGen/AArch64/framelayout-scavengingslot.mir b/llvm/test/CodeGen/AArch64/framelayout-scavengingslot.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/framelayout-scavengingslot.mir @@ -0,0 +1,27 @@ +# 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 +... diff --git a/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir b/llvm/test/CodeGen/AArch64/framelayout-sve-basepointer.mir new file mode 100644 --- /dev/null +++ b/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 +... diff --git a/llvm/test/CodeGen/AArch64/framelayout-sve-scavengingslot.mir b/llvm/test/CodeGen/AArch64/framelayout-sve-scavengingslot.mir new file mode 100644 --- /dev/null +++ b/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 +... diff --git a/llvm/test/CodeGen/AArch64/framelayout-sve.mir b/llvm/test/CodeGen/AArch64/framelayout-sve.mir --- a/llvm/test/CodeGen/AArch64/framelayout-sve.mir +++ b/llvm/test/CodeGen/AArch64/framelayout-sve.mir @@ -1,4 +1,4 @@ -# 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 @@ -30,7 +30,7 @@ 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 } @@ -335,23 +335,23 @@ 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: