Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -579,6 +579,12 @@ !F.hasFnAttribute("no-stack-arg-probe"); } +static bool needsWinCFI(const MachineFunction &MF) { + const Function &F = MF.getFunction(); + return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && + F.needsUnwindTableEntry(); +} + bool AArch64FrameLowering::shouldCombineCSRLocalStackBump( MachineFunction &MF, uint64_t StackBumpBytes) const { AArch64FunctionInfo *AFI = MF.getInfo(); @@ -589,6 +595,12 @@ if (AFI->getLocalStackSize() == 0) return false; + // For WinCFI, prefer to not combine the stack bump (to force a stp with + // predecrement) to match the packed unwind format, provided that there + // actually are any callee saved registers to merge the decrement with. + if (needsWinCFI(MF) && AFI->getCalleeSavedStackSize() > 0) + return false; + // 512 is the maximum immediate for stp/ldp that will be used for // callee-save save/restores if (StackBumpBytes >= 512 || windowsRequiresStackProbe(MF, StackBumpBytes)) @@ -982,12 +994,6 @@ // } -static bool needsWinCFI(const MachineFunction &MF) { - const Function &F = MF.getFunction(); - return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && - F.needsUnwindTableEntry(); -} - static bool isTargetWindows(const MachineFunction &MF) { return MF.getSubtarget().isTargetWindows(); } Index: llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll =================================================================== --- llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll +++ llvm/test/CodeGen/AArch64/addr-of-ret-addr.ll @@ -41,11 +41,11 @@ ret i32 %add ; CHECK-LABEL: bar -; CHECK: sub sp, sp, #96 -; CHECK: stp x29, x30, [sp, #16] -; CHECK: add x29, sp, #16 +; CHECK: stp x29, x30, [sp, #-80]! +; CHECK: mov x29, sp +; CHECK: sub sp, sp, #16 ; CHECK: stp x1, x2, [x29, #24] ; CHECK: add x1, x29, #8 -; CHECK: ldp x29, x30, [sp, #16] -; CHECK: add sp, sp, #96 +; CHECK: add sp, sp, #16 +; CHECK: ldp x29, x30, [sp], #80 } Index: llvm/test/CodeGen/AArch64/seh-finally.ll =================================================================== --- llvm/test/CodeGen/AArch64/seh-finally.ll +++ llvm/test/CodeGen/AArch64/seh-finally.ll @@ -35,7 +35,8 @@ define void @simple_seh() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { entry: ; CHECK-LABEL: simple_seh -; CHECK: add x29, sp, #16 +; CHECK: mov x29, sp +; CHECK: sub sp, sp, #16 ; CHECK: mov x0, #-2 ; CHECK: stur x0, [x29, #16] ; CHECK: .set .Lsimple_seh$frame_escape_0, -8 @@ -140,7 +141,8 @@ define void @vla_present(i32 %n) #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { entry: ; CHECK-LABEL: vla_present -; CHECK: add x29, sp, #32 +; CHECK: mov x29, sp +; CHECK: sub sp, sp, #32 ; CHECK: mov x1, #-2 ; CHECK: stur x1, [x29, #16] ; CHECK: .set .Lvla_present$frame_escape_0, -4 Index: llvm/test/CodeGen/AArch64/sponentry.ll =================================================================== --- llvm/test/CodeGen/AArch64/sponentry.ll +++ llvm/test/CodeGen/AArch64/sponentry.ll @@ -37,12 +37,14 @@ } ; CHECK: foo: -; CHECK: sub sp, sp, #448 -; CHECK: add x29, sp, #424 +; CHECK: str x28, [sp, #-32]! +; CHECK: add x29, sp, #8 +; CHECK: sub sp, sp, #416 ; CHECK: add x1, x29, #24 ; CHECK: bl _setjmpex -; NOFP: sub sp, sp, #432 +; NOFP: stp x29, x30, [sp, #-16]! +; NOFP: sub sp, sp, #416 ; NOFP: add x1, sp, #432 define dso_local void @var_args(i8*, ...) { @@ -67,12 +69,14 @@ } ; CHECK: var_args: -; CHECK: sub sp, sp, #96 -; CHECK: add x29, sp, #16 +; CHECK: stp x29, x30, [sp, #-80]! +; CHECK: mov x29, sp +; CHECK: sub sp, sp, #16 ; CHECK: add x1, x29, #80 ; CHECK: bl _setjmpex -; NOFP: sub sp, sp, #96 +; NOFP: str x30, [sp, #-80]! +; NOFP: sub sp, sp, #16 ; NOFP: add x1, sp, #96 define dso_local void @manyargs(i64 %x1, i64 %x2, i64 %x3, i64 %x4, i64 %x5, i64 %x6, i64 %x7, i64 %x8, i64 %x9, i64 %x10) { Index: llvm/test/CodeGen/AArch64/win64_vararg.ll =================================================================== --- llvm/test/CodeGen/AArch64/win64_vararg.ll +++ llvm/test/CodeGen/AArch64/win64_vararg.ll @@ -211,9 +211,9 @@ declare void @llvm.stackrestore(i8*) ; CHECK-LABEL: snprintf -; CHECK-DAG: sub sp, sp, #96 -; CHECK-DAG: stp x19, x20, [sp, #16] -; CHECK-DAG: stp x21, x30, [sp, #32] +; CHECK-DAG: stp x19, x20, [sp, #-80]! +; CHECK-DAG: stp x21, x30, [sp, #16] +; CHECK-DAG: sub sp, sp, #16 ; CHECK-DAG: add x8, sp, #56 ; CHECK-DAG: mov x19, x2 ; CHECK-DAG: mov x20, x1 @@ -231,11 +231,11 @@ ; CHECK-DAG: mov x3, x19 ; CHECK-DAG: mov x4, xzr ; CHECK-DAG: bl __stdio_common_vsprintf -; CHECK-DAG: ldp x21, x30, [sp, #32] -; CHECK-DAG: ldp x19, x20, [sp, #16] ; CHECK-DAG: cmp w0, #0 ; CHECK-DAG: csinv w0, w0, wzr, ge -; CHECK-DAG: add sp, sp, #96 +; CHECK-DAG: add sp, sp, #16 +; CHECK-DAG: ldp x21, x30, [sp, #16] +; CHECK-DAG: ldp x19, x20, [sp], #80 ; CHECK-DAG: ret define i32 @snprintf(i8*, i64, i8*, ...) local_unnamed_addr #5 { %4 = alloca i8*, align 8 Index: llvm/test/CodeGen/AArch64/wineh-frame-predecrement.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/wineh-frame-predecrement.mir @@ -0,0 +1,65 @@ +# RUN: llc -o - %s -mtriple=aarch64-windows -start-before=prologepilog \ +# RUN: -stop-after=prologepilog | FileCheck %s + +# Check that the callee-saved registers are saved starting with a STP +# with predecrement, followed by a separate stack adjustment later. + +# CHECK: early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -2 +# CHECK-NEXT: frame-setup SEH_SaveRegP_X 19, 20, -16 +# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 +# CHECK-NEXT: frame-setup SEH_StackAlloc 16 +# CHECK-NEXT: frame-setup SEH_PrologEnd + +... +--- +name: func +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 4 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +callSites: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $x0, $x19, $x20 + + renamable $x8 = ADDXri %stack.0, 0, 0 + $x19 = ADDXrr $x0, $x8 + $x20 = ADDXrr $x19, $x0 + $x0 = ADDXrr $x0, killed $x20 + + RET_ReallyLR + +...