1 ; Tests that the coro.destroy and coro.resume are devirtualized where possible,
2 ; SCC pipeline restarts and inlines the direct calls.
4 ; RUN: -passes='cgscc(inline,function(coro-elide,dce),inline,function(coro-elide,dce))' \
7 declare void @print(i32) nounwind
9 ; resume part of the coroutine
10 define fastcc void @f.resume(ptr dereferenceable(1)) {
11 tail call void @print(i32 0)
15 ; destroy part of the coroutine
16 define fastcc void @f.destroy(ptr) {
17 tail call void @print(i32 1)
21 ; cleanup part of the coroutine
22 define fastcc void @f.cleanup(ptr) {
23 tail call void @print(i32 2)
27 @f.resumers = internal constant [3 x ptr] [ptr @f.resume,
31 ; a coroutine start function
34 %id = call token @llvm.coro.id(i32 0, ptr null,
37 %alloc = call i1 @llvm.coro.alloc(token %id)
38 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
42 ; CHECK-LABEL: @callResume(
43 define void @callResume() {
47 ; CHECK: call void @print(i32 0)
48 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
49 call fastcc void %0(ptr %hdl)
51 ; CHECK-NEXT: call void @print(i32 2)
52 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
53 call fastcc void %1(ptr %hdl)
55 ; CHECK-NEXT: ret void
59 ; CHECK-LABEL: @callResumeMultiRet(
60 define void @callResumeMultiRet(i1 %b) {
63 ; CHECK: %alloc.i = call i1 @llvm.coro.alloc
64 ; CHECK: call void @print(i32 0)
65 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
66 call fastcc void %0(ptr %hdl)
67 br i1 %b, label %destroy, label %ret
70 ; CHECK: call void @print(i32 1)
71 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
72 call fastcc void %1(ptr %hdl)
79 ; CHECK-LABEL: @callResumeMultiRetDommmed(
80 define void @callResumeMultiRetDommmed(i1 %b) {
83 ; CHECK-NOT: %alloc.i = call i1 @llvm.coro.alloc
84 ; CHECK: call void @print(i32 0)
85 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
86 call fastcc void %0(ptr %hdl)
87 ; CHECK: call void @print(i32 2)
88 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
89 call fastcc void %1(ptr %hdl)
90 br i1 %b, label %destroy, label %ret
100 define void @eh() personality ptr null {
104 ; CHECK: call void @print(i32 0)
105 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
106 invoke void %0(ptr %hdl)
107 to label %cont unwind label %ehcleanup
112 %tok = cleanuppad within none []
113 cleanupret from %tok unwind to caller
116 ; CHECK-LABEL: @no_devirt_info_null(
117 ; no devirtualization here, since coro.begin info parameter is null
118 define void @no_devirt_info_null() {
120 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
121 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
123 ; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
124 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
125 call fastcc void %0(ptr %hdl)
127 ; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
128 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
129 call fastcc void %1(ptr %hdl)
135 ; CHECK-LABEL: @no_devirt_no_begin(
136 ; no devirtualization here, since coro.begin is not visible
137 define void @no_devirt_no_begin(ptr %hdl) {
140 ; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
141 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
142 call fastcc void %0(ptr %hdl)
144 ; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
145 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)
146 call fastcc void %1(ptr %hdl)
152 declare token @llvm.coro.id(i32, ptr, ptr, ptr)
153 declare ptr @llvm.coro.begin(token, ptr)
154 declare ptr @llvm.coro.frame()
155 declare ptr @llvm.coro.subfn.addr(ptr, i8)
156 declare i1 @llvm.coro.alloc(token)