131 lines · plain
1; Tests that we'll generate the store to the final suspend index if we see the unwind coro end.2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s3 4define ptr @unwind_coro_end() presplitcoroutine personality i32 3 {5entry:6 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)7 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)8 call void @print(i32 0)9 br label %init10 11init:12 %initial_suspend = call i8 @llvm.coro.suspend(token none, i1 false)13 switch i8 %initial_suspend, label %init_suspend [i8 0, label %init_resume14 i8 1, label %init_suspend]15 16init_suspend:17 ret ptr %hdl18 19init_resume:20 invoke void @print(i32 1)21 to label %final_suspend unwind label %lpad22 23final_suspend:24 %0 = call i8 @llvm.coro.suspend(token none, i1 true)25 switch i8 %0, label %suspend [i8 0, label %resume26 i8 1, label %suspend]27resume:28 invoke void @print(i32 1) to label %suspend unwind label %lpad29 30suspend:31 call void @llvm.coro.end(ptr %hdl, i1 false, token none)32 call void @print(i32 0)33 ret ptr %hdl34 35lpad:36 %lpval = landingpad { ptr, i32 }37 cleanup38 39 call void @print(i32 2)40 call void @llvm.coro.end(ptr null, i1 true, token none)41 %in.ramp = call i1 @llvm.coro.is_in_ramp()42 br i1 %in.ramp, label %cleanup.cont, label %eh.resume43 44cleanup.cont:45 call void @print(i32 3)46 br label %eh.resume47 48eh.resume:49 resume { ptr, i32 } %lpval50}51 52; Tests that we need to store the final index if we see unwind coro end.53; CHECK: define{{.*}}@unwind_coro_end.resume54; CHECK: invoke{{.*}}print55; CHECK-NEXT: to label %[[RESUME:.*]] unwind label %[[LPAD:.*]]56 57; CHECK: [[RESUME]]:58; CHECK-NOT: {{.*:}}59; CHECK: store ptr null, ptr %hdl60; CHECK-NOT: {{.*:}}61; CHECK: store i1 true, ptr %index.addr62 63; CHECK: [[LPAD]]:64; CHECK-NOT: {{.*:}}65; CHECK: store ptr null, ptr %hdl66; CHECK-NOT: {{.*:}}67; CHECK: store i1 true, ptr %index.addr68 69; Tests the use of final index in the destroy function.70; CHECK: define{{.*}}@unwind_coro_end.destroy71; CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr72; CHECK-NEXT: switch i1 %[[INDEX]],73 74define ptr @nounwind_coro_end(i1 %val) presplitcoroutine personality i32 3 {75entry:76 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)77 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)78 call void @print(i32 0)79 br label %init80 81init:82 %initial_suspend = call i8 @llvm.coro.suspend(token none, i1 false)83 switch i8 %initial_suspend, label %init_suspend [i8 0, label %init_resume84 i8 1, label %init_suspend]85 86init_suspend:87 ret ptr %hdl88 89init_resume:90 br label %susp91 92susp:93 %0 = call i8 @llvm.coro.suspend(token none, i1 true)94 switch i8 %0, label %suspend [i8 0, label %resume95 i8 1, label %suspend]96resume:97 call void @print(i32 1)98 br label %suspend99 100suspend:101 call void @llvm.coro.end(ptr %hdl, i1 false, token none)102 call void @print(i32 0)103 ret ptr %hdl104}105 106; Tests that we can omit to store the final suspend index if we don't107; see unwind coro end.108; CHECK: define{{.*}}@nounwind_coro_end.resume109; CHECK-NOT: store i1 true, ptr %index.addr110; CHECK: }111 112; Tests that we judge the final suspend case by the nullness of resume function.113; CHECK: define{{.*}}@nounwind_coro_end.destroy114; CHECK: %[[RESUME_FN:.+]] = load ptr, ptr %hdl, align 8115; CHECK: %{{.*}} = icmp eq ptr %[[RESUME_FN]], null116 117declare ptr @llvm.coro.free(token, ptr)118declare i32 @llvm.coro.size.i32()119declare i8 @llvm.coro.suspend(token, i1)120declare void @llvm.coro.resume(ptr)121declare void @llvm.coro.destroy(ptr)122 123declare token @llvm.coro.id(i32, ptr, ptr, ptr)124declare ptr @llvm.coro.alloc(token)125declare ptr @llvm.coro.begin(token, ptr)126declare void @llvm.coro.end(ptr, i1, token)127 128declare noalias ptr @malloc(i32)129declare void @print(i32)130declare void @free(ptr)131