blob: d92b031bc94ff30c55d2cd6c6c0b320af943b580 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefix=LINUX
; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -verify-machineinstrs | FileCheck %s --check-prefix=WIN64
; A 128-byte stack adjustment should be emitted as `add rsp, -128` in the
; prologue and `sub rsp, -128` in the epilogue: 128 misses the sign-extended
; 8-bit immediate form, but -128 fits it, saving three bytes each. Windows
; epilogues keep the canonical `add rsp, imm` because the Win64 v1 unwinder
; recognizes epilogues by disassembling for it; prologues are located by
; SizeOfProlog and never disassembled, so they may flip.
declare void @escape(ptr)
; One value lives across the call, forcing a single CSR push; the 120 bytes
; of locals then round up to a 128-byte adjustment on Linux.
define ptr @frame128(ptr %p) {
; LINUX-LABEL: frame128:
; LINUX: # %bb.0:
; LINUX-NEXT: pushq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: addq $-128, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 144
; LINUX-NEXT: .cfi_offset %rbx, -16
; LINUX-NEXT: movq %rdi, %rbx
; LINUX-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; LINUX-NEXT: callq escape@PLT
; LINUX-NEXT: movq %rbx, %rax
; LINUX-NEXT: subq $-128, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: popq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 8
; LINUX-NEXT: retq
;
; WIN64-LABEL: frame128:
; WIN64: # %bb.0:
; WIN64-NEXT: pushq %rsi
; WIN64-NEXT: .seh_pushreg %rsi
; WIN64-NEXT: subq $160, %rsp
; WIN64-NEXT: .seh_stackalloc 160
; WIN64-NEXT: .seh_endprologue
; WIN64-NEXT: movq %rcx, %rsi
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN64-NEXT: callq escape
; WIN64-NEXT: movq %rsi, %rax
; WIN64-NEXT: .seh_startepilogue
; WIN64-NEXT: addq $160, %rsp
; WIN64-NEXT: popq %rsi
; WIN64-NEXT: .seh_endepilogue
; WIN64-NEXT: retq
; WIN64-NEXT: .seh_endproc
%buf = alloca [120 x i8]
call void @escape(ptr %buf)
ret ptr %p
}
; The same shape with 96 bytes of locals reaches a 128-byte adjustment on
; Win64 (32-byte shadow area included): the prologue flips to `add rsp, -128`
; but the epilogue must keep `add rsp, 128`.
define ptr @frame128_win(ptr %p) {
; LINUX-LABEL: frame128_win:
; LINUX: # %bb.0:
; LINUX-NEXT: pushq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: subq $96, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 112
; LINUX-NEXT: .cfi_offset %rbx, -16
; LINUX-NEXT: movq %rdi, %rbx
; LINUX-NEXT: movq %rsp, %rdi
; LINUX-NEXT: callq escape@PLT
; LINUX-NEXT: movq %rbx, %rax
; LINUX-NEXT: addq $96, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: popq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 8
; LINUX-NEXT: retq
;
; WIN64-LABEL: frame128_win:
; WIN64: # %bb.0:
; WIN64-NEXT: pushq %rsi
; WIN64-NEXT: .seh_pushreg %rsi
; WIN64-NEXT: addq $-128, %rsp
; WIN64-NEXT: .seh_stackalloc 128
; WIN64-NEXT: .seh_endprologue
; WIN64-NEXT: movq %rcx, %rsi
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN64-NEXT: callq escape
; WIN64-NEXT: movq %rsi, %rax
; WIN64-NEXT: .seh_startepilogue
; WIN64-NEXT: addq $128, %rsp
; WIN64-NEXT: popq %rsi
; WIN64-NEXT: .seh_endepilogue
; WIN64-NEXT: retq
; WIN64-NEXT: .seh_endproc
%buf = alloca [96 x i8]
call void @escape(ptr %buf)
ret ptr %p
}
; An adjacent size keeps the plain 32-bit immediate.
define ptr @frame144(ptr %p) {
; LINUX-LABEL: frame144:
; LINUX: # %bb.0:
; LINUX-NEXT: pushq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: subq $144, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 160
; LINUX-NEXT: .cfi_offset %rbx, -16
; LINUX-NEXT: movq %rdi, %rbx
; LINUX-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; LINUX-NEXT: callq escape@PLT
; LINUX-NEXT: movq %rbx, %rax
; LINUX-NEXT: addq $144, %rsp
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: popq %rbx
; LINUX-NEXT: .cfi_def_cfa_offset 8
; LINUX-NEXT: retq
;
; WIN64-LABEL: frame144:
; WIN64: # %bb.0:
; WIN64-NEXT: pushq %rsi
; WIN64-NEXT: .seh_pushreg %rsi
; WIN64-NEXT: subq $176, %rsp
; WIN64-NEXT: .seh_stackalloc 176
; WIN64-NEXT: .seh_endprologue
; WIN64-NEXT: movq %rcx, %rsi
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN64-NEXT: callq escape
; WIN64-NEXT: movq %rsi, %rax
; WIN64-NEXT: .seh_startepilogue
; WIN64-NEXT: addq $176, %rsp
; WIN64-NEXT: popq %rsi
; WIN64-NEXT: .seh_endepilogue
; WIN64-NEXT: retq
; WIN64-NEXT: .seh_endproc
%buf = alloca [136 x i8]
call void @escape(ptr %buf)
ret ptr %p
}