1; Tests lowerings of different versions of coro.await.suspend 2; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s 3 4%Awaiter = type {} 5 6; CHECK: define {{[^@]*}} @f.resume(ptr {{[^%]*}} %[[HDL:.+]]) 7; CHECK: %[[AWAITER:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 0 8define void @f() presplitcoroutine { 9entry: 10 %awaiter = alloca %Awaiter 11 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 12 %size = call i32 @llvm.coro.size.i32() 13 %alloc = call ptr @malloc(i32 %size) 14 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 15 %suspend.init = call i8 @llvm.coro.suspend(token none, i1 false) 16 switch i8 %suspend.init, label %ret [ 17 i8 0, label %step 18 i8 1, label %cleanup 19 ] 20 21; CHECK: call void @await_suspend_wrapper_void(ptr %[[AWAITER]], ptr %[[HDL]]) 22; CHECK-NEXT: br label %{{.*}} 23step: 24 %save = call token @llvm.coro.save(ptr null) 25 call void @llvm.coro.await.suspend.void(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_void) 26 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) 27 switch i8 %suspend, label %ret [ 28 i8 0, label %step1 29 i8 1, label %cleanup 30 ] 31 32; CHECK: %[[RESUME:.+]] = call i1 @await_suspend_wrapper_bool(ptr %[[AWAITER]], ptr %[[HDL]]) 33; CHECK-NEXT: br i1 %[[RESUME]], label %{{[^,]+}}, label %[[STEP2:.+]] 34step1: 35 %save1 = call token @llvm.coro.save(ptr null) 36 %resume.bool = call i1 @llvm.coro.await.suspend.bool(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_bool) 37 br i1 %resume.bool, label %suspend.cond, label %step2 38 39suspend.cond: 40 %suspend1 = call i8 @llvm.coro.suspend(token %save1, i1 false) 41 switch i8 %suspend1, label %ret [ 42 i8 0, label %step2 43 i8 1, label %cleanup 44 ] 45 46; CHECK: [[STEP2]]: 47; CHECK: %[[NEXT_HDL:.+]] = call ptr @await_suspend_wrapper_handle(ptr %[[AWAITER]], ptr %[[HDL]]) 48; CHECK-NEXT: %[[CONT:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0) 49; CHECK-NEXT: musttail call {{.*}} void %[[CONT]](ptr %[[NEXT_HDL]]) 50step2: 51 %save2 = call token @llvm.coro.save(ptr null) 52 call void @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) 53 %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) 54 switch i8 %suspend2, label %ret [ 55 i8 0, label %step3 56 i8 1, label %cleanup 57 ] 58 59step3: 60 br label %cleanup 61 62cleanup: 63 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 64 call void @free(ptr %mem) 65 br label %ret 66 67ret: 68 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 69 ret void 70} 71 72; check that we were haven't accidentally went out of @f.resume body 73; CHECK-LABEL: @f.destroy( 74; CHECK-LABEL: @f.cleanup( 75 76declare void @await_suspend_wrapper_void(ptr, ptr) 77declare i1 @await_suspend_wrapper_bool(ptr, ptr) 78declare ptr @await_suspend_wrapper_handle(ptr, ptr) 79 80declare ptr @llvm.coro.free(token, ptr) 81declare i32 @llvm.coro.size.i32() 82declare i8 @llvm.coro.suspend(token, i1) 83declare void @llvm.coro.resume(ptr) 84declare void @llvm.coro.destroy(ptr) 85 86declare token @llvm.coro.id(i32, ptr, ptr, ptr) 87declare i1 @llvm.coro.alloc(token) 88declare ptr @llvm.coro.begin(token, ptr) 89declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) 90declare i1 @llvm.coro.await.suspend.bool(ptr, ptr, ptr) 91declare void @llvm.coro.await.suspend.handle(ptr, ptr, ptr) 92declare i1 @llvm.coro.end(ptr, i1, token) 93 94declare noalias ptr @malloc(i32) 95declare void @free(ptr) 96