xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-materialize.ll (revision 51d5d7bbae92493a5bfa7cc6b519de8a5bb32fdb)
1; Verifies that we materialize instruction across suspend points
2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3
4; See that we only spilled one value for f
5; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
6; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 }
7; Check other variants where different levels of materialization are achieved
8; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 }
9; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 }
10; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 }
11; CHECK-LABEL: @f(
12; CHECK-LABEL: @f_optnone
13; CHECK-LABEL: @f_multiple_remat(
14; CHECK-LABEL: @f_common_def(
15; CHECK-LABEL: @f_common_def_multi_result(
16
17define ptr @f(i32 %n) presplitcoroutine {
18entry:
19  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
20  %size = call i32 @llvm.coro.size.i32()
21  %alloc = call ptr @malloc(i32 %size)
22  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
23
24  %inc1 = add i32 %n, 1
25  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
26  switch i8 %sp1, label %suspend [i8 0, label %resume1
27                                  i8 1, label %cleanup]
28resume1:
29  %inc2 = add i32 %inc1, 1
30  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
31  switch i8 %sp1, label %suspend [i8 0, label %resume2
32                                  i8 1, label %cleanup]
33
34resume2:
35  call void @print(i32 %inc1)
36  call void @print(i32 %inc2)
37  br label %cleanup
38
39cleanup:
40  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
41  call void @free(ptr %mem)
42  br label %suspend
43suspend:
44  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
45  ret ptr %hdl
46}
47
48; Checks that we won't transform functions with optnone.
49define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline {
50entry:
51  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
52  %size = call i32 @llvm.coro.size.i32()
53  %alloc = call ptr @malloc(i32 %size)
54  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
55
56  %inc1 = add i32 %n, 1
57  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
58  switch i8 %sp1, label %suspend [i8 0, label %resume1
59                                  i8 1, label %cleanup]
60resume1:
61  %inc2 = add i32 %inc1, 1
62  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
63  switch i8 %sp1, label %suspend [i8 0, label %resume2
64                                  i8 1, label %cleanup]
65
66resume2:
67  call void @print(i32 %inc1)
68  call void @print(i32 %inc2)
69  br label %cleanup
70
71cleanup:
72  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
73  call void @free(ptr %mem)
74  br label %suspend
75suspend:
76  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
77  ret ptr %hdl
78}
79
80define ptr @f_multiple_remat(i32 %n) presplitcoroutine {
81entry:
82  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
83  %size = call i32 @llvm.coro.size.i32()
84  %alloc = call ptr @malloc(i32 %size)
85  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
86
87  %inc1 = add i32 %n, 1
88  %inc2 = add i32 %inc1, 2
89  %inc3 = add i32 %inc2, 3
90  %inc4 = add i32 %inc3, 4
91  %inc5 = add i32 %inc4, 5
92  %inc6 = add i32 %inc5, 5
93  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
94  switch i8 %sp1, label %suspend [i8 0, label %resume1
95                                  i8 1, label %cleanup]
96resume1:
97  %inc7 = add i32 %inc6, 1
98  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
99  switch i8 %sp1, label %suspend [i8 0, label %resume2
100                                  i8 1, label %cleanup]
101
102resume2:
103  call void @print(i32 %inc1)
104  call void @print(i32 %inc7)
105  br label %cleanup
106
107cleanup:
108  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
109  call void @free(ptr %mem)
110  br label %suspend
111suspend:
112  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
113  ret ptr %hdl
114}
115
116define ptr @f_common_def(i32 %n) presplitcoroutine {
117entry:
118  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
119  %size = call i32 @llvm.coro.size.i32()
120  %alloc = call ptr @malloc(i32 %size)
121  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
122
123  %inc1 = add i32 %n, 1
124  %inc2 = add i32 %inc1, 2
125  %inc3 = add i32 %n, 3
126  %inc4 = add i32 %inc3, %inc1
127  %inc5 = add i32 %inc4, %inc1
128  %inc6 = add i32 %inc5, 5
129  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
130  switch i8 %sp1, label %suspend [i8 0, label %resume1
131                                  i8 1, label %cleanup]
132resume1:
133  %inc7 = add i32 %inc6, 1
134  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
135  switch i8 %sp1, label %suspend [i8 0, label %resume2
136                                  i8 1, label %cleanup]
137
138resume2:
139  call void @print(i32 %inc1)
140  call void @print(i32 %inc7)
141  br label %cleanup
142
143cleanup:
144  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
145  call void @free(ptr %mem)
146  br label %suspend
147suspend:
148  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
149  ret ptr %hdl
150}
151
152define ptr @f_common_def_multi_result(i32 %n) presplitcoroutine {
153entry:
154  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
155  %size = call i32 @llvm.coro.size.i32()
156  %alloc = call ptr @malloc(i32 %size)
157  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
158
159  %inc1 = add i32 %n, 1
160  %inc2 = add i32 %inc1, 2
161  %inc3 = add i32 %n, 3
162  %inc4 = add i32 %inc3, %inc1
163  %inc5 = add i32 %inc4, %inc1
164  %inc6 = add i32 %inc5, 4
165  %inc7 = add i32 %inc6, 5
166  %inc8 = add i32 %inc4, %inc2
167  %inc9 = add i32 %inc8, 5
168  %inc10 = add i32 %inc9, 6
169  %inc11 = add i32 %inc10, 7
170  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
171  switch i8 %sp1, label %suspend [i8 0, label %resume1
172                                  i8 1, label %cleanup]
173resume1:
174  %inc12 = add i32 %inc7, 1
175  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
176  switch i8 %sp1, label %suspend [i8 0, label %resume2
177                                  i8 1, label %cleanup]
178
179resume2:
180  call void @print(i32 %inc11)
181  call void @print(i32 %inc12)
182  br label %cleanup
183
184cleanup:
185  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
186  call void @free(ptr %mem)
187  br label %suspend
188suspend:
189  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
190  ret ptr %hdl
191}
192
193
194declare ptr @llvm.coro.free(token, ptr)
195declare i32 @llvm.coro.size.i32()
196declare i8  @llvm.coro.suspend(token, i1)
197declare void @llvm.coro.resume(ptr)
198declare void @llvm.coro.destroy(ptr)
199
200declare token @llvm.coro.id(i32, ptr, ptr, ptr)
201declare i1 @llvm.coro.alloc(token)
202declare ptr @llvm.coro.begin(token, ptr)
203declare i1 @llvm.coro.end(ptr, i1, token)
204
205declare noalias ptr @malloc(i32)
206declare void @print(i32)
207declare void @free(ptr)
208