xref: /llvm-project/llvm/test/CodeGen/SystemZ/swifterror.ll (revision 16b7cc69ef43110c9776212379ccc37d7d3263c0)
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
3
4declare ptr @malloc(i64)
5declare void @free(ptr)
6%swift_error = type {i64, i8}
7
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".
10define 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
21entry:
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
27}
28
29; "caller" calls "foo" that takes a swifterror parameter.
30define 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
47entry:
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
54cont:
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
59handler:
60  call void @free(ptr %error_from_foo)
61  ret float 1.0
62}
63
64; "caller2" is the caller of "foo", it calls "foo" inside a loop.
65define 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
84entry:
85  %error_ptr_ref = alloca swifterror ptr
86  br label %bb_loop
87bb_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
93cont:
94  %cmp = fcmp ogt float %call, 1.000000e+00
95  br i1 %cmp, label %bb_end, label %bb_loop
96bb_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
101handler:
102  call void @free(ptr %error_from_foo)
103  ret float 1.0
104}
105
106; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
107; under a certain condition.
108define 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
130entry:
131  %cond = icmp ne i32 %cc, 0
132  br i1 %cond, label %gen_error, label %normal
133
134gen_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
140
141normal:
142  ret float 0.0
143}
144
145; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
146; under a certain condition inside a loop.
147define 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
171entry:
172  br label %bb_loop
173
174bb_loop:
175  %cond = icmp ne i32 %cc, 0
176  br i1 %cond, label %gen_error, label %bb_cont
177
178gen_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
184
185bb_cont:
186  %cmp = fcmp ogt float %cc2, 1.000000e+00
187  br i1 %cmp, label %bb_end, label %bb_loop
188bb_end:
189  ret float 0.0
190}
191
192%struct.S = type { i32, i32, i32, i32, i32, i32 }
193
194; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
195; parameter.
196define 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
207
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
221entry:
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
229}
230
231; "caller3" calls "foo_sret" that takes a swifterror parameter.
232define 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
244
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
258entry:
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
266cont:
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
271handler:
272  call void @free(ptr %error_from_foo)
273  ret float 1.0
274}
275
276; This is a caller with multiple swifterror values, it calls "foo" twice, each
277; time with a different swifterror value, from "alloca swifterror".
278define 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
291
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
301
302; CHECK-O0-LABEL: caller_with_multiple_swifterror_values:
303
304; The first swifterror value:
305; CHECK-O0: lghi %r9, 0
306; CHECK-O0: brasl %r14, foo
307; CHECK-O0: jlh
308
309; The second swifterror value:
310; CHECK-O0: lghi %r9, 0
311; CHECK-O0: brasl %r14, foo
312; CHECK-O0: jlh
313entry:
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
320cont:
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
325handler:
326  call void @free(ptr %error_from_foo)
327
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
334cont2:
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
339handler2:
340  call void @free(ptr %error_from_foo2)
341
342  ret float 1.0
343}
344