| ; 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 | |
| } |