81 lines · plain
1; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s2 3%"struct.std::coroutine_handle" = type { ptr }4%"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }5%"struct.lean_future<int>::Awaiter" = type { i32, %"struct.std::coroutine_handle.0" }6 7declare ptr @malloc(i64)8 9%i8.array = type { [100 x i8] }10declare void @consume.i8.array(ptr)11 12; The lifetime of testval starts and ends before coro.suspend. Even though consume.i8.array13; might capture it, we can safely say it won't live across suspension.14define void @foo() presplitcoroutine {15entry:16 %testval = alloca %i8.array17 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)18 %alloc = call ptr @malloc(i64 16) #319 %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)20 21 call void @llvm.lifetime.start.p0(ptr %testval)22 call void @consume.i8.array(ptr %testval)23 call void @llvm.lifetime.end.p0(ptr %testval)24 25 %save = call token @llvm.coro.save(ptr null)26 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)27 switch i8 %suspend, label %exit [28 i8 0, label %await.ready29 i8 1, label %exit30 ]31await.ready:32 %StrayCoroSave = call token @llvm.coro.save(ptr null)33 br label %exit34exit:35 call void @llvm.coro.end(ptr null, i1 false, token none)36 ret void37}38 39; The lifetime of testval starts after coro.suspend. So it will never live across suspension40; points.41define void @bar() presplitcoroutine {42entry:43 %testval = alloca %i8.array44 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)45 %alloc = call ptr @malloc(i64 16) #346 %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)47 %save = call token @llvm.coro.save(ptr null)48 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)49 switch i8 %suspend, label %exit [50 i8 0, label %await.ready51 i8 1, label %exit52 ]53await.ready:54 %StrayCoroSave = call token @llvm.coro.save(ptr null)55 56 call void @llvm.lifetime.start.p0(ptr %testval)57 call void @consume.i8.array(ptr %testval)58 call void @llvm.lifetime.end.p0(ptr %testval)59 60 br label %exit61exit:62 call void @llvm.coro.end(ptr null, i1 false, token none)63 ret void64}65 66; Verify that for both foo and bar, testval isn't put on the frame.67; CHECK: %foo.Frame = type { ptr, ptr, i1 }68; CHECK: %bar.Frame = type { ptr, ptr, i1 }69 70declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)71declare i1 @llvm.coro.alloc(token) #372declare i64 @llvm.coro.size.i64() #573declare ptr @llvm.coro.begin(token, ptr writeonly) #374declare token @llvm.coro.save(ptr) #375declare ptr @llvm.coro.frame() #576declare i8 @llvm.coro.suspend(token, i1) #377declare ptr @llvm.coro.free(token, ptr nocapture readonly) #278declare void @llvm.coro.end(ptr, i1, token) #379declare void @llvm.lifetime.start.p0(ptr nocapture) #480declare void @llvm.lifetime.end.p0(ptr nocapture) #481