1; Tests that the coro.destroy and coro.resume are devirtualized where possible, 2; SCC pipeline restarts and inlines the direct calls. 3; RUN: opt < %s -S \ 4; RUN: -passes='cgscc(inline,function(coro-elide,dce),inline,function(coro-elide,dce))' \ 5; RUN: | FileCheck %s 6 7declare void @print(i32) nounwind 8 9; resume part of the coroutine 10define fastcc void @f.resume(ptr dereferenceable(1)) { 11 tail call void @print(i32 0) 12 ret void 13} 14 15; destroy part of the coroutine 16define fastcc void @f.destroy(ptr) { 17 tail call void @print(i32 1) 18 ret void 19} 20 21; cleanup part of the coroutine 22define fastcc void @f.cleanup(ptr) { 23 tail call void @print(i32 2) 24 ret void 25} 26 27@f.resumers = internal constant [3 x ptr] [ptr @f.resume, 28 ptr @f.destroy, 29 ptr @f.cleanup] 30 31; a coroutine start function 32define ptr @f() { 33entry: 34 %id = call token @llvm.coro.id(i32 0, ptr null, 35 ptr @f, 36 ptr @f.resumers) 37 %alloc = call i1 @llvm.coro.alloc(token %id) 38 %hdl = call ptr @llvm.coro.begin(token %id, ptr null) 39 ret ptr %hdl 40} 41 42; CHECK-LABEL: @callResume( 43define void @callResume() { 44entry: 45 %hdl = call ptr @f() 46 47; CHECK: call void @print(i32 0) 48 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 49 call fastcc void %0(ptr %hdl) 50 51; CHECK-NEXT: call void @print(i32 2) 52 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 53 call fastcc void %1(ptr %hdl) 54 55; CHECK-NEXT: ret void 56 ret void 57} 58 59; CHECK-LABEL: @callResumeMultiRet( 60define void @callResumeMultiRet(i1 %b) { 61entry: 62 %hdl = call ptr @f() 63; CHECK: %alloc.i = call i1 @llvm.coro.alloc 64; CHECK: call void @print(i32 0) 65 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 66 call fastcc void %0(ptr %hdl) 67 br i1 %b, label %destroy, label %ret 68 69destroy: 70; CHECK: call void @print(i32 1) 71 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 72 call fastcc void %1(ptr %hdl) 73 ret void 74 75ret: 76 ret void 77} 78 79; CHECK-LABEL: @callResumeMultiRetDommmed( 80define void @callResumeMultiRetDommmed(i1 %b) { 81entry: 82 %hdl = call ptr @f() 83; CHECK-NOT: %alloc.i = call i1 @llvm.coro.alloc 84; CHECK: call void @print(i32 0) 85 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 86 call fastcc void %0(ptr %hdl) 87; CHECK: call void @print(i32 2) 88 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 89 call fastcc void %1(ptr %hdl) 90 br i1 %b, label %destroy, label %ret 91 92destroy: 93 ret void 94 95ret: 96 ret void 97} 98 99; CHECK-LABEL: @eh( 100define void @eh() personality ptr null { 101entry: 102 %hdl = call ptr @f() 103 104; CHECK: call void @print(i32 0) 105 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 106 invoke void %0(ptr %hdl) 107 to label %cont unwind label %ehcleanup 108cont: 109 ret void 110 111ehcleanup: 112 %tok = cleanuppad within none [] 113 cleanupret from %tok unwind to caller 114} 115 116; CHECK-LABEL: @no_devirt_info_null( 117; no devirtualization here, since coro.begin info parameter is null 118define void @no_devirt_info_null() { 119entry: 120 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 121 %hdl = call ptr @llvm.coro.begin(token %id, ptr null) 122 123; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 124 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 125 call fastcc void %0(ptr %hdl) 126 127; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 128 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 129 call fastcc void %1(ptr %hdl) 130 131; CHECK: ret void 132 ret void 133} 134 135; CHECK-LABEL: @no_devirt_no_begin( 136; no devirtualization here, since coro.begin is not visible 137define void @no_devirt_no_begin(ptr %hdl) { 138entry: 139 140; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 141 %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0) 142 call fastcc void %0(ptr %hdl) 143 144; CHECK: call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 145 %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1) 146 call fastcc void %1(ptr %hdl) 147 148; CHECK: ret void 149 ret void 150} 151 152declare token @llvm.coro.id(i32, ptr, ptr, ptr) 153declare ptr @llvm.coro.begin(token, ptr) 154declare ptr @llvm.coro.frame() 155declare ptr @llvm.coro.subfn.addr(ptr, i8) 156declare i1 @llvm.coro.alloc(token) 157