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