1 ; Tests that the coro.destroy and coro.resume are devirtualized where possible,
2 ; SCC pipeline restarts and inlines the direct calls.
3 ; RUN: opt < %s -S -inline -coro-elide -dce | FileCheck %s
5 declare void @print(i32) nounwind
7 ; resume part of the coroutine
8 define fastcc void @f.resume(i8*) {
9 tail call void @print(i32 0)
13 ; destroy part of the coroutine
14 define fastcc void @f.destroy(i8*) {
15 tail call void @print(i32 1)
19 @f.resumers = internal constant [2 x void (i8*)*] [void (i8*)* @f.resume,
20 void (i8*)* @f.destroy]
22 ; a coroutine start function
25 %id = call token @llvm.coro.id(i32 0, i8* null,
26 i8* bitcast (i8*()* @f to i8*),
27 i8* bitcast ([2 x void (i8*)*]* @f.resumers to i8*))
28 %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
32 ; CHECK-LABEL: @callResume(
33 define void @callResume() {
37 ; CHECK: call void @print(i32 0)
38 %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
39 %1 = bitcast i8* %0 to void (i8*)*
40 call fastcc void %1(i8* %hdl)
42 ; CHECK-NEXT: call void @print(i32 1)
43 %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
44 %3 = bitcast i8* %2 to void (i8*)*
45 call fastcc void %3(i8* %hdl)
47 ; CHECK-NEXT: ret void
52 define void @eh() personality i8* null {
56 ; CHECK: call void @print(i32 0)
57 %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
58 %1 = bitcast i8* %0 to void (i8*)*
59 invoke void %1(i8* %hdl)
60 to label %cont unwind label %ehcleanup
65 %tok = cleanuppad within none []
66 cleanupret from %tok unwind to caller
69 ; CHECK-LABEL: @no_devirt_info_null(
70 ; no devirtualization here, since coro.begin info parameter is null
71 define void @no_devirt_info_null() {
73 %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
74 %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
76 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
77 %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
78 %1 = bitcast i8* %0 to void (i8*)*
79 call fastcc void %1(i8* %hdl)
81 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
82 %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
83 %3 = bitcast i8* %2 to void (i8*)*
84 call fastcc void %3(i8* %hdl)
90 ; CHECK-LABEL: @no_devirt_no_begin(
91 ; no devirtualization here, since coro.begin is not visible
92 define void @no_devirt_no_begin(i8* %hdl) {
95 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
96 %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
97 %1 = bitcast i8* %0 to void (i8*)*
98 call fastcc void %1(i8* %hdl)
100 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
101 %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
102 %3 = bitcast i8* %2 to void (i8*)*
103 call fastcc void %3(i8* %hdl)
109 declare token @llvm.coro.id(i32, i8*, i8*, i8*)
110 declare i8* @llvm.coro.begin(token, i8*)
111 declare i8* @llvm.coro.frame()
112 declare i8* @llvm.coro.subfn.addr(i8*, i8)