[X86] combineTargetShuffle - commute VPERMV3 shuffles so any load is on the RHS
[llvm-project.git] / llvm / test / CodeGen / SystemZ / swifterror.ll
blob1b18287cac1468f89755cade1a7c9b82f23ff248
1 ; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck %s
2 ; RUN: llc < %s -O0 -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck --check-prefix=CHECK-O0 %s
4 declare ptr @malloc(i64)
5 declare void @free(ptr)
6 %swift_error = type {i64, i8}
8 ; This tests the basic usage of a swifterror parameter. "foo" is the function
9 ; that takes a swifterror parameter and "caller" is the caller of "foo".
10 define float @foo(ptr swifterror %error_ptr_ref) {
11 ; CHECK-LABEL: foo:
12 ; CHECK: lghi %r2, 16
13 ; CHECK: brasl %r14, malloc
14 ; CHECK: mvi 8(%r2), 1
15 ; CHECK: lgr %r9, %r2
16 ; CHECK-O0-LABEL: foo:
17 ; CHECK-O0: lghi %r2, 16
18 ; CHECK-O0: brasl %r14, malloc
19 ; CHECK-O0: lgr [[T0:%r[0-9]+]], %r2
20 ; CHECK-O0: mvi 8(%r2), 1
21 entry:
22   %call = call ptr @malloc(i64 16)
23   store ptr %call, ptr %error_ptr_ref
24   %tmp = getelementptr inbounds i8, ptr %call, i64 8
25   store i8 1, ptr %tmp
26   ret float 1.0
29 ; "caller" calls "foo" that takes a swifterror parameter.
30 define float @caller(ptr %error_ref) {
31 ; CHECK-LABEL: caller:
32 ; Make a copy of error_ref because r2 is getting clobbered
33 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
34 ; CHECK-DAG: lghi %r9, 0
35 ; CHECK: brasl %r14, foo
36 ; CHECK: %r2, %r9
37 ; CHECK: jlh
38 ; Access part of the error object and save it to error_ref
39 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2)
40 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
41 ; CHECK: brasl %r14, free
42 ; CHECK-O0-LABEL: caller:
43 ; CHECK-O0: lghi %r9, 0
44 ; CHECK-O0: brasl %r14, foo
45 ; CHECK-O0: cghi %r9, 0
46 ; CHECK-O0: jlh
47 entry:
48   %error_ptr_ref = alloca swifterror ptr
49   store ptr null, ptr %error_ptr_ref
50   %call = call float @foo(ptr swifterror %error_ptr_ref)
51   %error_from_foo = load ptr, ptr %error_ptr_ref
52   %had_error_from_foo = icmp ne ptr %error_from_foo, null
53   br i1 %had_error_from_foo, label %handler, label %cont
54 cont:
55   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
56   %t = load i8, ptr %v1
57   store i8 %t, ptr %error_ref
58   br label %handler
59 handler:
60   call void @free(ptr %error_from_foo)
61   ret float 1.0
64 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
65 define float @caller2(ptr %error_ref) {
66 ; CHECK-LABEL: caller2:
67 ; Make a copy of error_ref because r2 is getting clobbered
68 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
69 ; CHECK: lghi %r9, 0
70 ; CHECK: brasl %r14, foo
71 ; CHECK: cgijlh %r9, 0,
72 ; CHECK: ceb %f0,
73 ; CHECK: jnh
74 ; Access part of the error object and save it to error_ref
75 ; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9)
76 ; CHECK: stc %r[[REG2]], 0(%r[[REG1]])
77 ; CHECK: lgr %r2, %r9
78 ; CHECK: brasl %r14, free
79 ; CHECK-O0-LABEL: caller2:
80 ; CHECK-O0: lghi %r9, 0
81 ; CHECK-O0: brasl %r14, foo
82 ; CHECK-O0: cghi %r9, 0
83 ; CHECK-O0: jlh
84 entry:
85   %error_ptr_ref = alloca swifterror ptr
86   br label %bb_loop
87 bb_loop:
88   store ptr null, ptr %error_ptr_ref
89   %call = call float @foo(ptr swifterror %error_ptr_ref)
90   %error_from_foo = load ptr, ptr %error_ptr_ref
91   %had_error_from_foo = icmp ne ptr %error_from_foo, null
92   br i1 %had_error_from_foo, label %handler, label %cont
93 cont:
94   %cmp = fcmp ogt float %call, 1.000000e+00
95   br i1 %cmp, label %bb_end, label %bb_loop
96 bb_end:
97   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
98   %t = load i8, ptr %v1
99   store i8 %t, ptr %error_ref
100   br label %handler
101 handler:
102   call void @free(ptr %error_from_foo)
103   ret float 1.0
106 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
107 ; under a certain condition.
108 define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) {
109 ; CHECK-LABEL: foo_if:
110 ; CHECK: cije %r2, 0
111 ; CHECK: lghi %r2, 16
112 ; CHECK: brasl %r14, malloc
113 ; CHECK: mvi 8(%r2), 1
114 ; CHECK: lgr %r9, %r2
115 ; CHECK-NOT: %r9
116 ; CHECK: br %r14
117 ; CHECK-O0-LABEL: foo_if:
118 ; spill to stack
119 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
120 ; CHECK-O0: chi %r2, 0
121 ; CHECK-O0: je
122 ; CHECK-O0: lghi %r2, 16
123 ; CHECK-O0: brasl %r14, malloc
124 ; CHECK-O0: lgr %r9, %r2
125 ; CHECK-O0: mvi 8(%r2), 1
126 ; CHECK-O0: br %r14
127 ; reload from stack
128 ; CHECK-O0: lg %r9, [[OFFS]](%r15)
129 ; CHECK-O0: br %r14
130 entry:
131   %cond = icmp ne i32 %cc, 0
132   br i1 %cond, label %gen_error, label %normal
134 gen_error:
135   %call = call ptr @malloc(i64 16)
136   store ptr %call, ptr %error_ptr_ref
137   %tmp = getelementptr inbounds i8, ptr %call, i64 8
138   store i8 1, ptr %tmp
139   ret float 1.0
141 normal:
142   ret float 0.0
145 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
146 ; under a certain condition inside a loop.
147 define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) {
148 ; CHECK-LABEL: foo_loop:
149 ; CHECK: lr %r[[REG1:[0-9]+]], %r2
150 ; CHECK: cije %r[[REG1]], 0
151 ; CHECK: lghi %r2, 16
152 ; CHECK: brasl %r14, malloc
153 ; CHECK: mvi 8(%r2), 1
154 ; CHECK: ceb %f8,
155 ; CHECK: jnh
156 ; CHECK: lgr %r9, %r2
157 ; CHECK: br %r14
158 ; CHECK-O0-LABEL: foo_loop:
159 ; spill to stack
160 ; CHECK-O0: stg %r9, [[OFFS:[0-9]+]](%r15)
161 ; CHECK-O0: chi %r{{.*}}, 0
162 ; CHECK-O0: je
163 ; CHECK-O0: lghi %r2, 16
164 ; CHECK-O0: brasl %r14, malloc
165 ; CHECK-O0: lgr %r[[REG1:[0-9]+]], %r2
166 ; CHECK-O0: mvi 8(%r[[REG1]]), 1
167 ; CHECK-O0: jnh
168 ; reload from stack
169 ; CHECK-O0: lg %r9, [[OFFS:[0-9]+]](%r15)
170 ; CHECK-O0: br %r14
171 entry:
172   br label %bb_loop
174 bb_loop:
175   %cond = icmp ne i32 %cc, 0
176   br i1 %cond, label %gen_error, label %bb_cont
178 gen_error:
179   %call = call ptr @malloc(i64 16)
180   store ptr %call, ptr %error_ptr_ref
181   %tmp = getelementptr inbounds i8, ptr %call, i64 8
182   store i8 1, ptr %tmp
183   br label %bb_cont
185 bb_cont:
186   %cmp = fcmp ogt float %cc2, 1.000000e+00
187   br i1 %cmp, label %bb_end, label %bb_loop
188 bb_end:
189   ret float 0.0
192 %struct.S = type { i32, i32, i32, i32, i32, i32 }
194 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
195 ; parameter.
196 define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) {
197 ; CHECK-LABEL: foo_sret:
198 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
199 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3
200 ; CHECK-DAG: lghi %r2, 16
201 ; CHECK: brasl %r14, malloc
202 ; CHECK: mvi 8(%r2), 1
203 ; CHECK: st %r[[REG2]], 4(%r[[REG1]])
204 ; CHECK: lgr %r9, %r2
205 ; CHECK-NOT: %r9
206 ; CHECK: br %r14
208 ; CHECK-O0-LABEL: foo_sret:
209 ; spill sret to stack
210 ; CHECK-O0-DAG: stg %r2, [[OFFS1:[0-9]+]](%r15)
211 ; CHECK-O0-DAG: st %r3, [[OFFS2:[0-9]+]](%r15)
212 ; CHECK-O0: lghi %r2, 16
213 ; CHECK-O0: brasl %r14, malloc
214 ; CHECK-O0-DAG: lgr %r[[REG3:[0-9]+]], %r2
215 ; CHECK-O0-DAG: mvi 8(%r[[REG3]]), 1
216 ; CHECK-O0-DAG: lg %r[[REG1:[0-9]+]], [[OFFS1]](%r15)
217 ; CHECK-O0-DAG: lgr %r9, %r[[REG3]]
218 ; CHECK-O0-DAG: l %r[[REG2:[0-9]+]], [[OFFS2]](%r15)
219 ; CHECK-O0: st %r[[REG2]], 4(%r[[REG1]])
220 ; CHECK-O0: br %r14
221 entry:
222   %call = call ptr @malloc(i64 16)
223   store ptr %call, ptr %error_ptr_ref
224   %tmp = getelementptr inbounds i8, ptr %call, i64 8
225   store i8 1, ptr %tmp
226   %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1
227   store i32 %val1, ptr %v2
228   ret void
231 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
232 define float @caller3(ptr %error_ref) {
233 ; CHECK-LABEL: caller3:
234 ; Make a copy of error_ref because r2 is getting clobbered
235 ; CHECK: lgr %r[[REG1:[0-9]+]], %r2
236 ; CHECK: lhi %r3, 1
237 ; CHECK: lghi %r9, 0
238 ; CHECK: brasl %r14, foo_sret
239 ; CHECK: jlh
240 ; Access part of the error object and save it to error_ref
241 ; CHECK: lb %r0, 8(%r2)
242 ; CHECK: stc %r0, 0(%r[[REG1]])
243 ; CHECK: brasl %r14, free
245 ; CHECK-O0-LABEL: caller3:
246 ; CHECK-O0: lghi %r9, 0
247 ; CHECK-O0: lhi %r3, 1
248 ; CHECK-O0: brasl %r14, foo_sret
249 ; CHECK-O0: lgr {{.*}}, %r9
250 ; CHECK-O0: cghi %r9, 0
251 ; CHECK-O0: jlh
252 ; Access part of the error object and save it to error_ref
253 ; CHECK-O0: lb %r0, 8(%r{{.*}})
254 ; CHECK-O0: stc %r0, 0(%r{{.*}})
255 ; reload from stack
256 ; CHECK-O0: lg %r2, {{.*}}(%r15)
257 ; CHECK-O0: brasl %r14, free
258 entry:
259   %s = alloca %struct.S, align 8
260   %error_ptr_ref = alloca swifterror ptr
261   store ptr null, ptr %error_ptr_ref
262   call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref)
263   %error_from_foo = load ptr, ptr %error_ptr_ref
264   %had_error_from_foo = icmp ne ptr %error_from_foo, null
265   br i1 %had_error_from_foo, label %handler, label %cont
266 cont:
267   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
268   %t = load i8, ptr %v1
269   store i8 %t, ptr %error_ref
270   br label %handler
271 handler:
272   call void @free(ptr %error_from_foo)
273   ret float 1.0
276 ; This is a caller with multiple swifterror values, it calls "foo" twice, each
277 ; time with a different swifterror value, from "alloca swifterror".
278 define float @caller_with_multiple_swifterror_values(ptr %error_ref, ptr %error_ref2) {
279 ; CHECK-LABEL: caller_with_multiple_swifterror_values:
280 ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2
281 ; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3
282 ; The first swifterror value:
283 ; CHECK-DAG: lghi %r9, 0
284 ; CHECK: brasl %r14, foo
285 ; CHECK: ltgr %r2, %r9
286 ; CHECK: jlh
287 ; Access part of the error object and save it to error_ref
288 ; CHECK: lb %r0, 8(%r2)
289 ; CHECK: stc %r0, 0(%r[[REG1]])
290 ; CHECK: brasl %r14, free
292 ; The second swifterror value:
293 ; CHECK: lghi %r9, 0
294 ; CHECK: brasl %r14, foo
295 ; CHECK: ltgr %r2, %r9
296 ; CHECK: jlh
297 ; Access part of the error object and save it to error_ref
298 ; CHECK: lb %r0, 8(%r2)
299 ; CHECK: stc %r0, 0(%r[[REG2]])
300 ; CHECK: brasl %r14, free
302 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
304 ; The first swifterror value:
305 ; CHECK-O0: lghi %r9, 0
306 ; CHECK-O0: brasl %r14, foo
307 ; CHECK-O0: jlh
309 ; The second swifterror value:
310 ; CHECK-O0: lghi %r9, 0
311 ; CHECK-O0: brasl %r14, foo
312 ; CHECK-O0: jlh
313 entry:
314   %error_ptr_ref = alloca swifterror ptr
315   store ptr null, ptr %error_ptr_ref
316   %call = call float @foo(ptr swifterror %error_ptr_ref)
317   %error_from_foo = load ptr, ptr %error_ptr_ref
318   %had_error_from_foo = icmp ne ptr %error_from_foo, null
319   br i1 %had_error_from_foo, label %handler, label %cont
320 cont:
321   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
322   %t = load i8, ptr %v1
323   store i8 %t, ptr %error_ref
324   br label %handler
325 handler:
326   call void @free(ptr %error_from_foo)
328   %error_ptr_ref2 = alloca swifterror ptr
329   store ptr null, ptr %error_ptr_ref2
330   %call2 = call float @foo(ptr swifterror %error_ptr_ref2)
331   %error_from_foo2 = load ptr, ptr %error_ptr_ref2
332   %had_error_from_foo2 = icmp ne ptr %error_from_foo2, null
333   br i1 %had_error_from_foo2, label %handler2, label %cont2
334 cont2:
335   %v2 = getelementptr inbounds %swift_error, ptr %error_from_foo2, i64 0, i32 1
336   %t2 = load i8, ptr %v2
337   store i8 %t2, ptr %error_ref2
338   br label %handler2
339 handler2:
340   call void @free(ptr %error_from_foo2)
342   ret float 1.0