1; RUN: opt < %s -passes='cgscc(coro-split),early-cse,dce,simplifycfg' -S | FileCheck %s 2 3%"struct.std::__n4861::noop_coroutine_promise" = type { i8 } 4%struct.Promise = type { %"struct.std::__n4861::coroutine_handle" } 5%"struct.std::__n4861::coroutine_handle" = type { ptr } 6 7define ptr @foo() #1 { 8entry: 9 %__promise = alloca %struct.Promise, align 8 10 %0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr nonnull @foo, ptr null) 11 %1 = call i1 @llvm.coro.alloc(token %0) 12 br i1 %1, label %coro.alloc, label %init.suspend 13 14coro.alloc: ; preds = %entry 15 %2 = tail call i64 @llvm.coro.size.i64() 16 %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef %2) #11 17 br label %init.suspend 18 19init.suspend: ; preds = %entry, %coro.alloc 20 %3 = phi ptr [ null, %entry ], [ %call, %coro.alloc ] 21 %4 = call ptr @llvm.coro.begin(token %0, ptr %3) #12 22 call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %__promise) #3 23 store ptr null, ptr %__promise, align 8 24 %5 = call token @llvm.coro.save(ptr null) 25 %6 = call i8 @llvm.coro.suspend(token %5, i1 false) 26 switch i8 %6, label %coro.ret [ 27 i8 0, label %await.suspend 28 i8 1, label %cleanup1 29 ] 30 31await.suspend: ; preds = %init.suspend 32 %7 = call token @llvm.coro.save(ptr null) 33 %8 = call i8 @llvm.coro.suspend(token %7, i1 false) 34 switch i8 %8, label %coro.ret [ 35 i8 0, label %await2.suspend 36 i8 1, label %cleanup2 37 ] 38 39await2.suspend: ; preds = %await.suspend 40 %call27 = call ptr @_Z5Innerv() #3 41 %9 = call token @llvm.coro.save(ptr null) 42 %10 = getelementptr inbounds i8, ptr %__promise, i64 -16 43 store ptr %10, ptr %call27, align 8 44 %11 = getelementptr inbounds i8, ptr %call27, i64 -16 45 %12 = call ptr @llvm.coro.subfn.addr(ptr nonnull %11, i8 0) 46 call fastcc void %12(ptr nonnull %11) #3 47 %13 = call i8 @llvm.coro.suspend(token %9, i1 false) 48 switch i8 %13, label %coro.ret [ 49 i8 0, label %final.suspend 50 i8 1, label %cleanup3 51 ] 52 53final.suspend: ; preds = %await2.suspend 54 %14 = call ptr @llvm.coro.subfn.addr(ptr nonnull %11, i8 1) 55 call fastcc void %14(ptr nonnull %11) #3 56 %15 = call token @llvm.coro.save(ptr null) 57 %retval.sroa.0.0.copyload.i = load ptr, ptr %__promise, align 8 58 %16 = call ptr @llvm.coro.subfn.addr(ptr %retval.sroa.0.0.copyload.i, i8 0) 59 call fastcc void %16(ptr %retval.sroa.0.0.copyload.i) #3 60 %17 = call i8 @llvm.coro.suspend(token %15, i1 true) #12 61 switch i8 %17, label %coro.ret [ 62 i8 0, label %final.ready 63 i8 1, label %cleanup62 64 ] 65 66final.ready: ; preds = %final.suspend 67 call void @exit(i32 noundef 1) 68 unreachable 69 70cleanup1: 71 call void @dtor1() 72 br label %cleanup62 73 74cleanup2: 75 call void @dtor2() 76 br label %cleanup62 77 78cleanup3: 79 call void @dtor3() 80 br label %cleanup62 81 82cleanup62: ; preds = %await2.suspend, %await.suspend, %init.suspend, %final.suspend 83 call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %__promise) #3 84 %18 = call ptr @llvm.coro.free(token %0, ptr %4) 85 %.not = icmp eq ptr %18, null 86 br i1 %.not, label %coro.ret, label %coro.free 87 88coro.free: ; preds = %cleanup62 89 call void @_ZdlPv(ptr noundef nonnull %18) #3 90 br label %coro.ret 91 92coro.ret: ; preds = %coro.free, %cleanup62, %final.suspend, %await2.suspend, %await.suspend, %init.suspend 93 %19 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #12 94 ret ptr %__promise 95} 96 97declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #2 98declare i1 @llvm.coro.alloc(token) #3 99declare dso_local noundef nonnull ptr @_Znwm(i64 noundef) local_unnamed_addr #4 100declare i64 @llvm.coro.size.i64() #5 101declare ptr @llvm.coro.begin(token, ptr writeonly) #3 102declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #6 103declare token @llvm.coro.save(ptr) #7 104declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #6 105declare i8 @llvm.coro.suspend(token, i1) #3 106declare ptr @_Z5Innerv() local_unnamed_addr 107declare dso_local void @_ZdlPv(ptr noundef) local_unnamed_addr #8 108declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2 109declare i1 @llvm.coro.end(ptr, i1, token) #3 110declare void @exit(i32 noundef) 111declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #10 112declare void @dtor1() 113declare void @dtor2() 114declare void @dtor3() 115 116attributes #0 = { mustprogress nounwind uwtable } 117attributes #1 = { nounwind presplitcoroutine uwtable coro_only_destroy_when_complete } 118attributes #2 = { argmemonly nofree nounwind readonly } 119attributes #3 = { nounwind } 120attributes #4 = { nobuiltin allocsize(0) } 121attributes #5 = { nofree nosync nounwind readnone } 122attributes #6 = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } 123attributes #7 = { nomerge nounwind } 124attributes #8 = { nobuiltin nounwind } 125attributes #9 = { noreturn } 126attributes #10 = { argmemonly nounwind readonly } 127attributes #11 = { nounwind allocsize(0) } 128attributes #12 = { noduplicate } 129 130; CHECK: define{{.*}}@foo.destroy( 131; CHECK-NEXT: entry.destroy: 132; CHECK-NEXT: call void @_ZdlPv 133; CHECK-NEXT: ret void 134 135; CHECK: define{{.*}}@foo.cleanup( 136; CHECK-NEXT: entry.cleanup: 137; CHECK-NEXT: ret void 138