Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / X86 / win64-funclet-preisel-intrinsics.ll
blobc015a4e670d638ee3e9596291da5923675f54ed0
1 ; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
3 ; WinEH requires funclet tokens on nounwind intrinsics if they can lower to
4 ; regular function calls in the course of IR transformations.
6 ; Test that the code generator will emit the function call and not consider it
7 ; an "implausible instruciton". In the past this silently truncated code on
8 ; exception paths and caused crashes at runtime.
10 ; Reduced IR generated from ObjC++ source:
12 ;     @class Ety;
13 ;     void opaque(void);
14 ;     void test_catch_with_objc_intrinsic(void) {
15 ;       @try {
16 ;         opaque();
17 ;       } @catch (Ety *ex) {
18 ;         // Destroy ex when leaving catchpad. This would emit calls to two
19 ;         // intrinsic functions: llvm.objc.retain and llvm.objc.storeStrong
20 ;       }
21 ;     }
23 ; llvm.objc.retain and llvm.objc.storeStrong both lower into regular function
24 ; calls before ISel. We only need one of them to trigger funclet truncation
25 ; during codegen:
27 define void @test_catch_with_objc_intrinsic() personality ptr @__CxxFrameHandler3 {
28 entry:
29   %exn.slot = alloca ptr, align 8
30   %ex2 = alloca ptr, align 8
31   invoke void @opaque() to label %invoke.cont unwind label %catch.dispatch
33 catch.dispatch:                                   ; preds = %entry
34   %0 = catchswitch within none [label %catch] unwind to caller
36 invoke.cont:                                      ; preds = %entry
37   unreachable
39 catch:                                            ; preds = %catch.dispatch
40   %1 = catchpad within %0 [ptr null, i32 64, ptr %exn.slot]
41   %exn = load ptr, ptr %exn.slot, align 8
42   %2 = call ptr @llvm.objc.retain(ptr %exn) [ "funclet"(token %1) ]
43   store ptr %2, ptr %ex2, align 8
44   catchret from %1 to label %catchret.dest
46 catchret.dest:                                    ; preds = %catch
47   ret void
50 declare void @opaque()
51 declare ptr @llvm.objc.retain(ptr) #0
52 declare i32 @__CxxFrameHandler3(...)
54 attributes #0 = { nounwind }
56 ; EH catchpad with SEH prologue:
57 ;     CHECK-LABEL:  # %catch
58 ;     CHECK:          pushq   %rbp
59 ;     CHECK:          .seh_pushreg %rbp
60 ;                     ...
61 ;     CHECK:          .seh_endprologue
63 ; At this point the code used to be truncated (and sometimes terminated with an
64 ; int3 opcode):
65 ;     CHECK-NOT:      int3
67 ; Instead, the runtime call to retain should be emitted:
68 ;     CHECK:          movq    -8(%rbp), %rcx
69 ;     CHECK:          callq   objc_retain
70 ;                     ...
72 ; This is the end of the funclet:
73 ;     CHECK:          popq      %rbp
74 ;     CHECK:          retq                                    # CATCHRET
75 ;                     ...
76 ;     CHECK:          .seh_handlerdata
77 ;                     ...
78 ;     CHECK:          .seh_endproc