1 ; Verifies that we materialize instruction across suspend points
2 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
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 }
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(
17 define ptr @f(i32 %n) presplitcoroutine {
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)
25 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
26 switch i8 %sp1, label %suspend [i8 0, label %resume1
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
35 call void @print(i32 %inc1)
36 call void @print(i32 %inc2)
40 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
41 call void @free(ptr %mem)
44 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
48 ; Checks that we won't transform functions with optnone.
49 define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline {
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)
57 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
58 switch i8 %sp1, label %suspend [i8 0, label %resume1
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
67 call void @print(i32 %inc1)
68 call void @print(i32 %inc2)
72 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
73 call void @free(ptr %mem)
76 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
80 define ptr @f_multiple_remat(i32 %n) presplitcoroutine {
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)
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
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]
103 call void @print(i32 %inc1)
104 call void @print(i32 %inc7)
108 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
109 call void @free(ptr %mem)
112 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
116 define ptr @f_common_def(i32 %n) presplitcoroutine {
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)
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]
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]
139 call void @print(i32 %inc1)
140 call void @print(i32 %inc7)
144 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
145 call void @free(ptr %mem)
148 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
152 define ptr @f_common_def_multi_result(i32 %n) presplitcoroutine {
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)
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]
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]
180 call void @print(i32 %inc11)
181 call void @print(i32 %inc12)
185 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
186 call void @free(ptr %mem)
189 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
194 declare ptr @llvm.coro.free(token, ptr)
195 declare i32 @llvm.coro.size.i32()
196 declare i8 @llvm.coro.suspend(token, i1)
197 declare void @llvm.coro.resume(ptr)
198 declare void @llvm.coro.destroy(ptr)
200 declare token @llvm.coro.id(i32, ptr, ptr, ptr)
201 declare i1 @llvm.coro.alloc(token)
202 declare ptr @llvm.coro.begin(token, ptr)
203 declare i1 @llvm.coro.end(ptr, i1, token)
205 declare noalias ptr @malloc(i32)
206 declare void @print(i32)
207 declare void @free(ptr)