86 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s3 4@escape_hatch0 = external global i645@escape_hatch1 = external global i646 7define void @foo() presplitcoroutine {8; CHECK-LABEL: @foo(9; CHECK-NEXT: entry:10; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)11; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 40)12; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])13; CHECK-NEXT: store ptr @foo.resume, ptr [[VFRAME]], align 814; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 115; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 816; CHECK-NEXT: [[STACKVAR0_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 217; CHECK-NEXT: [[STACKVAR1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 318; CHECK-NEXT: [[STACKVAR0_INT:%.*]] = ptrtoint ptr [[STACKVAR0_RELOAD_ADDR]] to i6419; CHECK-NEXT: store i64 [[STACKVAR0_INT]], ptr @escape_hatch0, align 420; CHECK-NEXT: [[STACKVAR1_INT:%.*]] = ptrtoint ptr [[STACKVAR1_RELOAD_ADDR]] to i6421; CHECK-NEXT: store i64 [[STACKVAR1_INT]], ptr @escape_hatch1, align 422; CHECK-NEXT: br label [[LOOP:%.*]]23; CHECK: loop:24; CHECK-NEXT: store i64 1234, ptr [[STACKVAR0_RELOAD_ADDR]], align 425; CHECK-NEXT: call void @bar()26; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 427; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 128; CHECK-NEXT: br i1 false, label [[LOOP]], label [[AFTERCOROEND:%.*]]29; CHECK: AfterCoroEnd:30; CHECK-NEXT: ret void31;32entry:33 %stackvar0 = alloca i6434 %stackvar1 = alloca i6435 36 ; address of %stackvar escapes and may be relied upon even after37 ; suspending/resuming the coroutine regardless of the lifetime markers.38 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)39 %size = call i64 @llvm.coro.size.i64()40 %alloc = call ptr @malloc(i64 %size)41 %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)42 43 ; %stackvar0 must be rewritten to reference the coroutine Frame!44 %stackvar0_int = ptrtoint ptr %stackvar0 to i6445 store i64 %stackvar0_int, ptr @escape_hatch046 ; %stackvar1 must be rewritten to reference the coroutine Frame!47 %stackvar1_int = ptrtoint ptr %stackvar1 to i6448 store i64 %stackvar1_int, ptr @escape_hatch149 50 br label %loop51 52loop:53 call void @llvm.lifetime.start(ptr %stackvar0)54 55 store i64 1234, ptr %stackvar056 57 ; Call could potentially change value in memory referenced by %stackvar0 /58 ; %stackvar1 and rely on it staying the same across suspension.59 call void @bar()60 61 call void @llvm.lifetime.end(ptr %stackvar0)62 63 %save = call token @llvm.coro.save(ptr null)64 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)65 switch i8 %suspend, label %exit [66 i8 0, label %loop67 i8 1, label %exit68 ]69 70exit:71 call void @llvm.coro.end(ptr null, i1 false, token none)72 ret void73}74 75declare void @bar()76declare ptr @malloc(i64)77 78declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)79declare i64 @llvm.coro.size.i64()80declare ptr @llvm.coro.begin(token, ptr writeonly)81declare token @llvm.coro.save(ptr)82declare i8 @llvm.coro.suspend(token, i1)83declare void @llvm.coro.end(ptr, i1, token)84declare void @llvm.lifetime.start(ptr nocapture)85declare void @llvm.lifetime.end(ptr nocapture)86