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