[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-elide.ll
blob674996b79e9235c06b8356c2875d1ef6572649ba
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(repeat<2>(inline,function(coro-elide,dce)))' \
5 ; RUN:   | FileCheck %s
7 declare void @print(i32) nounwind
9 ; resume part of the coroutine
10 define fastcc void @f.resume(i8*) {
11   tail call void @print(i32 0)
12   ret void
15 ; destroy part of the coroutine
16 define fastcc void @f.destroy(i8*) {
17   tail call void @print(i32 1)
18   ret void
21 ; cleanup part of the coroutine
22 define fastcc void @f.cleanup(i8*) {
23   tail call void @print(i32 2)
24   ret void
27 @f.resumers = internal constant [3 x void (i8*)*] [void (i8*)* @f.resume,
28                                                    void (i8*)* @f.destroy,
29                                                    void (i8*)* @f.cleanup]
31 ; a coroutine start function
32 define i8* @f() {
33 entry:
34   %id = call token @llvm.coro.id(i32 0, i8* null,
35                           i8* bitcast (i8*()* @f to i8*),
36                           i8* bitcast ([3 x void (i8*)*]* @f.resumers to i8*))
37   %alloc = call i1 @llvm.coro.alloc(token %id)
38   %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
39   ret i8* %hdl
42 ; CHECK-LABEL: @callResume(
43 define void @callResume() {
44 entry:
45   %hdl = call i8* @f()
47 ; CHECK: call void @print(i32 0)
48   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
49   %1 = bitcast i8* %0 to void (i8*)*
50   call fastcc void %1(i8* %hdl)
52 ; CHECK-NEXT: call void @print(i32 2)
53   %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
54   %3 = bitcast i8* %2 to void (i8*)*
55   call fastcc void %3(i8* %hdl)
57 ; CHECK-NEXT: ret void
58   ret void
61 ; CHECK-LABEL: @callResumeMultiRet(
62 define void @callResumeMultiRet(i1 %b) {
63 entry:
64   %hdl = call i8* @f()
65 ; CHECK: %alloc.i = call i1 @llvm.coro.alloc
66 ; CHECK: call void @print(i32 0)
67   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
68   %1 = bitcast i8* %0 to void (i8*)*
69   call fastcc void %1(i8* %hdl)
70   br i1 %b, label %destroy, label %ret
72 destroy:
73 ; CHECK: call void @print(i32 1)
74   %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
75   %3 = bitcast i8* %2 to void (i8*)*
76   call fastcc void %3(i8* %hdl)
77   ret void
79 ret:
80   ret void
83 ; CHECK-LABEL: @callResumeMultiRetDommmed(
84 define void @callResumeMultiRetDommmed(i1 %b) {
85 entry:
86   %hdl = call i8* @f()
87 ; CHECK-NOT: %alloc.i = call i1 @llvm.coro.alloc
88 ; CHECK: call void @print(i32 0)
89   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
90   %1 = bitcast i8* %0 to void (i8*)*
91   call fastcc void %1(i8* %hdl)
92 ; CHECK: call void @print(i32 2)
93   %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
94   %3 = bitcast i8* %2 to void (i8*)*
95   call fastcc void %3(i8* %hdl)
96   br i1 %b, label %destroy, label %ret
98 destroy:
99   ret void
101 ret:
102   ret void
105 ; CHECK-LABEL: @eh(
106 define void @eh() personality i8* null {
107 entry:
108   %hdl = call i8* @f()
110 ; CHECK: call void @print(i32 0)
111   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
112   %1 = bitcast i8* %0 to void (i8*)*
113   invoke void %1(i8* %hdl)
114           to label %cont unwind label %ehcleanup
115 cont:
116   ret void
118 ehcleanup:
119   %tok = cleanuppad within none []
120   cleanupret from %tok unwind to caller
123 ; CHECK-LABEL: @no_devirt_info_null(
124 ; no devirtualization here, since coro.begin info parameter is null
125 define void @no_devirt_info_null() {
126 entry:
127   %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
128   %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
130 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
131   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
132   %1 = bitcast i8* %0 to void (i8*)*
133   call fastcc void %1(i8* %hdl)
135 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
136   %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
137   %3 = bitcast i8* %2 to void (i8*)*
138   call fastcc void %3(i8* %hdl)
140 ; CHECK: ret void
141   ret void
144 ; CHECK-LABEL: @no_devirt_no_begin(
145 ; no devirtualization here, since coro.begin is not visible
146 define void @no_devirt_no_begin(i8* %hdl) {
147 entry:
149 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
150   %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
151   %1 = bitcast i8* %0 to void (i8*)*
152   call fastcc void %1(i8* %hdl)
154 ; CHECK: call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
155   %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1)
156   %3 = bitcast i8* %2 to void (i8*)*
157   call fastcc void %3(i8* %hdl)
159 ; CHECK: ret void
160   ret void
163 declare token @llvm.coro.id(i32, i8*, i8*, i8*)
164 declare i8* @llvm.coro.begin(token, i8*)
165 declare i8* @llvm.coro.frame()
166 declare i8* @llvm.coro.subfn.addr(i8*, i8)
167 declare i1 @llvm.coro.alloc(token)