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