1 ; Tests that we'll generate the store to the final suspend index if we see the unwind coro end.
2 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
4 define ptr @unwind_coro_end() presplitcoroutine personality i32 3 {
6 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
7 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
8 call void @print(i32 0)
12 %initial_suspend = call i8 @llvm.coro.suspend(token none, i1 false)
13 switch i8 %initial_suspend, label %init_suspend [i8 0, label %init_resume
14 i8 1, label %init_suspend]
20 invoke void @print(i32 1)
21 to label %final_suspend unwind label %lpad
24 %0 = call i8 @llvm.coro.suspend(token none, i1 true)
25 switch i8 %0, label %suspend [i8 0, label %resume
28 invoke void @print(i32 1) to label %suspend unwind label %lpad
31 call i1 @llvm.coro.end(ptr %hdl, i1 false, token none)
32 call void @print(i32 0)
36 %lpval = landingpad { ptr, i32 }
39 call void @print(i32 2)
40 %need.resume = call i1 @llvm.coro.end(ptr null, i1 true, token none)
41 br i1 %need.resume, label %eh.resume, label %cleanup.cont
44 call void @print(i32 3)
48 resume { ptr, i32 } %lpval
51 ; Tests that we need to store the final index if we see unwind coro end.
52 ; CHECK: define{{.*}}@unwind_coro_end.resume
53 ; CHECK: invoke{{.*}}print
54 ; CHECK-NEXT: to label %[[RESUME:.*]] unwind label %[[LPAD:.*]]
58 ; CHECK: store ptr null, ptr %hdl
60 ; CHECK: store i1 true, ptr %index.addr
64 ; CHECK: store ptr null, ptr %hdl
66 ; CHECK: store i1 true, ptr %index.addr
68 ; Tests the use of final index in the destroy function.
69 ; CHECK: define{{.*}}@unwind_coro_end.destroy
70 ; CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr
71 ; CHECK-NEXT: switch i1 %[[INDEX]],
73 define ptr @nounwind_coro_end(i1 %val) presplitcoroutine personality i32 3 {
75 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
76 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
77 call void @print(i32 0)
81 %initial_suspend = call i8 @llvm.coro.suspend(token none, i1 false)
82 switch i8 %initial_suspend, label %init_suspend [i8 0, label %init_resume
83 i8 1, label %init_suspend]
92 %0 = call i8 @llvm.coro.suspend(token none, i1 true)
93 switch i8 %0, label %suspend [i8 0, label %resume
96 call void @print(i32 1)
100 call i1 @llvm.coro.end(ptr %hdl, i1 false, token none)
101 call void @print(i32 0)
105 ; Tests that we can omit to store the final suspend index if we don't
106 ; see unwind coro end.
107 ; CHECK: define{{.*}}@nounwind_coro_end.resume
108 ; CHECK-NOT: store i1 true, ptr %index.addr
111 ; Tests that we judge the final suspend case by the nullness of resume function.
112 ; CHECK: define{{.*}}@nounwind_coro_end.destroy
113 ; CHECK: %[[RESUME_FN:.+]] = load ptr, ptr %hdl, align 8
114 ; CHECK: %{{.*}} = icmp eq ptr %[[RESUME_FN]], null
116 declare ptr @llvm.coro.free(token, ptr)
117 declare i32 @llvm.coro.size.i32()
118 declare i8 @llvm.coro.suspend(token, i1)
119 declare void @llvm.coro.resume(ptr)
120 declare void @llvm.coro.destroy(ptr)
122 declare token @llvm.coro.id(i32, ptr, ptr, ptr)
123 declare ptr @llvm.coro.alloc(token)
124 declare ptr @llvm.coro.begin(token, ptr)
125 declare i1 @llvm.coro.end(ptr, i1, token)
127 declare noalias ptr @malloc(i32)
128 declare void @print(i32)
129 declare void @free(ptr)