llvm-project/llvm/test/CodeGen/X86/win64-funclet-savexmm.ll
Daniel Paoliello b3458fdec5
[llvm] Win x64 Unwind V2 1/n: Mark beginning and end of epilogs (#110024)
Windows x64 Unwind V2 adds epilog information to unwind data:
specifically, the length of the epilog and the offset of each epilog.

The first step to do this is to add markers to the beginning and end of
each epilog when generating Windows x64 code. I've modelled this after
how LLVM was marking ARM and AArch64 epilogs in Windows (and unified the
code between the three).
2025-01-30 13:51:30 -08:00

118 lines
3.8 KiB
LLVM

; RUN: llc -mtriple=x86_64-pc-windows-msvc -mattr=+avx < %s | FileCheck %s
; void bar(int a, int b, int c, int d, int e);
; void baz(int x);
;
; void foo(int a, int b, int c, int d, int e)
; {
; __asm("nop" ::: "bx", "cx", "xmm5", "xmm6", "ymm7");
; try {
; bar(a, b, c, d, e);
; }
; catch (...) {
; baz(a);
; if (a)
; __asm("nop" ::: "xmm8");
; }
; }
%rtti.TypeDescriptor2 = type { ptr, ptr, [3 x i8] }
$"??_R0H@8" = comdat any
@"??_7type_info@@6B@" = external constant ptr
@"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { ptr @"??_7type_info@@6B@", ptr null, [3 x i8] c".H\00" }, comdat
declare dso_local i32 @__CxxFrameHandler3(...)
declare dso_local void @"?bar@@YAXHHHHH@Z"(i32, i32, i32, i32, i32)
declare dso_local void @"?baz@@YAXH@Z"(i32)
define dso_local void @"?foo@@YAXHHHHH@Z"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) personality ptr @__CxxFrameHandler3 {
entry:
%e.addr = alloca i32, align 4
%d.addr = alloca i32, align 4
%c.addr = alloca i32, align 4
%b.addr = alloca i32, align 4
%a.addr = alloca i32, align 4
store i32 %e, ptr %e.addr, align 4
store i32 %d, ptr %d.addr, align 4
store i32 %c, ptr %c.addr, align 4
store i32 %b, ptr %b.addr, align 4
store i32 %a, ptr %a.addr, align 4
call void asm sideeffect "nop", "~{bx},~{cx},~{xmm5},~{xmm6},~{ymm7}"()
%0 = load i32, ptr %e.addr, align 4
%1 = load i32, ptr %d.addr, align 4
%2 = load i32, ptr %c.addr, align 4
%3 = load i32, ptr %b.addr, align 4
%4 = load i32, ptr %a.addr, align 4
invoke void @"?bar@@YAXHHHHH@Z"(i32 %4, i32 %3, i32 %2, i32 %1, i32 %0)
to label %invoke.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
%5 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
%6 = catchpad within %5 [ptr null, i32 64, ptr null]
%7 = load i32, ptr %a.addr, align 4
call void @"?baz@@YAXH@Z"(i32 %7) [ "funclet"(token %6) ]
%8 = load i32, ptr %a.addr, align 4
%tobool = icmp ne i32 %8, 0
br i1 %tobool, label %if.then, label %if.end
if.then: ; preds = %catch
call void asm sideeffect "nop", "~{xmm8}"() [ "funclet"(token %6) ]
br label %if.end
invoke.cont: ; preds = %entry
br label %try.cont
if.end: ; preds = %if.then, %catch
catchret from %6 to label %catchret.dest
catchret.dest: ; preds = %if.end
br label %try.cont
try.cont: ; preds = %catchret.dest, %invoke.cont
ret void
}
; CHECK: # %catch
; CHECK: movq %rdx, 16(%rsp)
; CHECK: pushq %rbp
; CHECK: .seh_pushreg %rbp
; CHECK: pushq %rbx
; CHECK: .seh_pushreg %rbx
; CHECK: subq $88, %rsp
; CHECK: .seh_stackalloc 88
; CHECK: leaq 112(%rdx), %rbp
; CHECK: vmovaps %xmm8, 32(%rsp)
; CHECK: .seh_savexmm %xmm8, 32
; CHECK: vmovaps %xmm7, 48(%rsp)
; CHECK: .seh_savexmm %xmm7, 48
; CHECK: vmovaps %xmm6, 64(%rsp)
; CHECK: .seh_savexmm %xmm6, 64
; CHECK: .seh_endprologue
; CHECK: movl -{{[0-9]+}}(%rbp), %ecx
; CHECK: vmovaps 64(%rsp), %xmm6
; CHECK: vmovaps 48(%rsp), %xmm7
; CHECK: vmovaps 32(%rsp), %xmm8
; CHECK: leaq .LBB0_1(%rip), %rax
; CHECK: .seh_startepilogue
; CHECK: addq $88, %rsp
; CHECK: popq %rbx
; CHECK: popq %rbp
; CHECK: .seh_endepilogue
; CHECK: retq # CATCHRET
; CHECK-LABEL: "$handlerMap$0$?foo@@YAXHHHHH@Z":
; CHECK-NEXT: .long 64 # Adjectives
; CHECK-NEXT: .long 0 # Type
; CHECK-NEXT: .long 0 # CatchObjOffset
; CHECK-NEXT: .long "?catch$2@?0??foo@@YAXHHHHH@Z@4HA"@IMGREL # Handler
; Sum of:
; 16 RDX store offset
; 16 two pushes
; 72 stack alloc
; CHECK-NEXT: .long 120 # ParentFrameOffset