blob: 5a7eb40334dcb066ed46c82f0194e4a70be5ceec [file] [log] [blame]
Venkatraman Govindarajudd482262013-06-02 02:24:27 +00001; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +00002
3; CHECK: intarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +00004; The save/restore frame is not strictly necessary here, but we would need to
5; refer to %o registers instead.
6; CHECK: save %sp, -128, %sp
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +00007; CHECK: stb %i0, [%i4]
8; CHECK: stb %i1, [%i4]
9; CHECK: sth %i2, [%i4]
10; CHECK: st %i3, [%i4]
11; CHECK: stx %i4, [%i4]
12; CHECK: st %i5, [%i4]
Jakob Stoklund Olesen2b9355f2013-04-06 21:38:57 +000013; CHECK: ld [%fp+2227], [[R:%[gilo][0-7]]]
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000014; CHECK: st [[R]], [%i4]
Jakob Stoklund Olesen2b9355f2013-04-06 21:38:57 +000015; CHECK: ldx [%fp+2231], [[R:%[gilo][0-7]]]
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000016; CHECK: stx [[R]], [%i4]
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +000017; CHECK: restore
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000018define void @intarg(i8 %a0, ; %i0
19 i8 %a1, ; %i1
20 i16 %a2, ; %i2
21 i32 %a3, ; %i3
22 i8* %a4, ; %i4
23 i32 %a5, ; %i5
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000024 i32 signext %a6, ; [%fp+BIAS+176]
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000025 i8* %a7) { ; [%fp+BIAS+184]
26 store i8 %a0, i8* %a4
27 store i8 %a1, i8* %a4
28 %p16 = bitcast i8* %a4 to i16*
29 store i16 %a2, i16* %p16
30 %p32 = bitcast i8* %a4 to i32*
31 store i32 %a3, i32* %p32
32 %pp = bitcast i8* %a4 to i8**
33 store i8* %a4, i8** %pp
34 store i32 %a5, i32* %p32
35 store i32 %a6, i32* %p32
36 store i8* %a7, i8** %pp
37 ret void
38}
39
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000040; CHECK: call_intarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +000041; 16 saved + 8 args.
42; CHECK: save %sp, -192, %sp
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000043; Sign-extend and store the full 64 bits.
44; CHECK: sra %i0, 0, [[R:%[gilo][0-7]]]
45; CHECK: stx [[R]], [%sp+2223]
46; Use %o0-%o5 for outgoing arguments
47; CHECK: or %g0, 5, %o5
48; CHECK: call intarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +000049; CHECK-NOT: add %sp
50; CHECK: restore
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000051define void @call_intarg(i32 %i0, i8* %i1) {
52 call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1)
53 ret void
54}
55
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000056; CHECK: floatarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +000057; CHECK: save %sp, -128, %sp
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000058; CHECK: fstod %f1,
59; CHECK: faddd %f2,
60; CHECK: faddd %f4,
61; CHECK: faddd %f6,
Jakob Stoklund Olesen2b9355f2013-04-06 21:38:57 +000062; CHECK: ld [%fp+2307], [[F:%f[0-9]+]]
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000063; CHECK: fadds %f31, [[F]]
64define double @floatarg(float %a0, ; %f1
65 double %a1, ; %d2
66 double %a2, ; %d4
67 double %a3, ; %d6
68 float %a4, ; %f9
69 float %a5, ; %f11
70 float %a6, ; %f13
71 float %a7, ; %f15
72 float %a8, ; %f17
73 float %a9, ; %f19
74 float %a10, ; %f21
75 float %a11, ; %f23
76 float %a12, ; %f25
77 float %a13, ; %f27
78 float %a14, ; %f29
79 float %a15, ; %f31
80 float %a16, ; [%fp+BIAS+256] (using 8 bytes)
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000081 double %a17) { ; [%fp+BIAS+264] (using 8 bytes)
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +000082 %d0 = fpext float %a0 to double
83 %s1 = fadd double %a1, %d0
84 %s2 = fadd double %a2, %s1
85 %s3 = fadd double %a3, %s2
86 %s16 = fadd float %a15, %a16
87 %d16 = fpext float %s16 to double
88 %s17 = fadd double %d16, %s3
89 ret double %s17
90}
91
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000092; CHECK: call_floatarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +000093; CHECK: save %sp, -272, %sp
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +000094; Store 4 bytes, right-aligned in slot.
95; CHECK: st %f1, [%sp+2307]
96; Store 8 bytes in full slot.
97; CHECK: std %f2, [%sp+2311]
98; CHECK: fmovd %f2, %f4
99; CHECK: call floatarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +0000100; CHECK-NOT: add %sp
101; CHECK: restore
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000102define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
103 %r = call double @floatarg(float %f5, double %d2, double %d2, double %d2,
104 float %f5, float %f5, float %f5, float %f5,
105 float %f5, float %f5, float %f5, float %f5,
106 float %f5, float %f5, float %f5, float %f5,
107 float %f1, double %d2)
108 store double %r, double* %p
109 ret void
110}
111
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000112; CHECK: mixedarg
113; CHECK: fstod %f3
114; CHECK: faddd %f6
115; CHECK: faddd %f16
Jakob Stoklund Olesen2b9355f2013-04-06 21:38:57 +0000116; CHECK: ldx [%fp+2231]
117; CHECK: ldx [%fp+2247]
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000118define void @mixedarg(i8 %a0, ; %i0
119 float %a1, ; %f3
120 i16 %a2, ; %i2
121 double %a3, ; %d6
122 i13 %a4, ; %i4
123 float %a5, ; %f11
124 i64 %a6, ; [%fp+BIAS+176]
125 double *%a7, ; [%fp+BIAS+184]
126 double %a8, ; %d16
127 i16* %a9) { ; [%fp+BIAS+200]
128 %d1 = fpext float %a1 to double
129 %s3 = fadd double %a3, %d1
130 %s8 = fadd double %a8, %s3
131 store double %s8, double* %a7
132 store i16 %a2, i16* %a9
133 ret void
134}
135
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000136; CHECK: call_mixedarg
137; CHECK: stx %i2, [%sp+2247]
138; CHECK: stx %i0, [%sp+2223]
139; CHECK: fmovd %f2, %f6
140; CHECK: fmovd %f2, %f16
141; CHECK: call mixedarg
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +0000142; CHECK-NOT: add %sp
143; CHECK: restore
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000144define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) {
145 call void @mixedarg(i8 undef,
146 float undef,
147 i16 undef,
148 double %f2,
149 i13 undef,
150 float undef,
151 i64 %i0,
152 double* undef,
153 double %f2,
154 i16* %i2)
155 ret void
156}
157
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000158; The inreg attribute is used to indicate 32-bit sized struct elements that
159; share an 8-byte slot.
160; CHECK: inreg_fi
161; CHECK: fstoi %f1
162; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]]
163; CHECK: sub [[R]],
164define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0
165 float inreg %a1) { ; %f1
166 %b1 = fptosi float %a1 to i32
167 %rv = sub i32 %a0, %b1
168 ret i32 %rv
169}
170
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000171; CHECK: call_inreg_fi
Jakob Stoklund Olesen6ed92842013-04-09 04:37:47 +0000172; Allocate space for 6 arguments, even when only 2 are used.
173; CHECK: save %sp, -176, %sp
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000174; CHECK: sllx %i1, 32, %o0
175; CHECK: fmovs %f5, %f1
176; CHECK: call inreg_fi
177define void @call_inreg_fi(i32* %p, i32 %i1, float %f5) {
178 %x = call i32 @inreg_fi(i32 %i1, float %f5)
179 ret void
180}
181
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000182; CHECK: inreg_ff
183; CHECK: fsubs %f0, %f1, %f1
184define float @inreg_ff(float inreg %a0, ; %f0
185 float inreg %a1) { ; %f1
186 %rv = fsub float %a0, %a1
187 ret float %rv
188}
189
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000190; CHECK: call_inreg_ff
191; CHECK: fmovs %f3, %f0
192; CHECK: fmovs %f5, %f1
193; CHECK: call inreg_ff
194define void @call_inreg_ff(i32* %p, float %f3, float %f5) {
195 %x = call float @inreg_ff(float %f3, float %f5)
196 ret void
197}
198
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000199; CHECK: inreg_if
200; CHECK: fstoi %f0
201; CHECK: sub %i0
202define i32 @inreg_if(float inreg %a0, ; %f0
203 i32 inreg %a1) { ; low bits of %i0
204 %b0 = fptosi float %a0 to i32
205 %rv = sub i32 %a1, %b0
206 ret i32 %rv
207}
208
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000209; CHECK: call_inreg_if
210; CHECK: fmovs %f3, %f0
211; CHECK: or %g0, %i2, %o0
212; CHECK: call inreg_if
213define void @call_inreg_if(i32* %p, float %f3, i32 %i2) {
214 %x = call i32 @inreg_if(float %f3, i32 %i2)
215 ret void
216}
217
Jakob Stoklund Olesen1f25fe52013-04-06 18:32:12 +0000218; The frontend shouldn't do this. Just pass i64 instead.
219; CHECK: inreg_ii
220; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]]
221; CHECK: sub %i0, [[R]], %i0
222define i32 @inreg_ii(i32 inreg %a0, ; high bits of %i0
223 i32 inreg %a1) { ; low bits of %i0
224 %rv = sub i32 %a1, %a0
225 ret i32 %rv
226}
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000227
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000228; CHECK: call_inreg_ii
229; CHECK: srl %i2, 0, [[R2:%[gilo][0-7]]]
230; CHECK: sllx %i1, 32, [[R1:%[gilo][0-7]]]
231; CHECK: or [[R1]], [[R2]], %o0
232; CHECK: call inreg_ii
233define void @call_inreg_ii(i32* %p, i32 %i1, i32 %i2) {
234 %x = call i32 @inreg_ii(i32 %i1, i32 %i2)
235 ret void
236}
237
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000238; Structs up to 32 bytes in size can be returned in registers.
239; CHECK: ret_i64_pair
240; CHECK: ldx [%i2], %i0
241; CHECK: ldx [%i3], %i1
242define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) {
243 %r1 = load i64* %p
244 %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0
245 store i64 0, i64* %p
246 %r2 = load i64* %q
247 %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1
248 ret { i64, i64 } %rv2
249}
250
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000251; CHECK: call_ret_i64_pair
252; CHECK: call ret_i64_pair
253; CHECK: stx %o0, [%i0]
254; CHECK: stx %o1, [%i0]
255define void @call_ret_i64_pair(i64* %i0) {
256 %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef,
257 i64* undef, i64* undef)
258 %e0 = extractvalue { i64, i64 } %rv, 0
259 store i64 %e0, i64* %i0
260 %e1 = extractvalue { i64, i64 } %rv, 1
261 store i64 %e1, i64* %i0
262 ret void
263}
264
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000265; This is not a C struct, each member uses 8 bytes.
266; CHECK: ret_i32_float_pair
267; CHECK: ld [%i2], %i0
268; CHECK: ld [%i3], %f3
269define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1,
270 i32* %p, float* %q) {
271 %r1 = load i32* %p
272 %rv1 = insertvalue { i32, float } undef, i32 %r1, 0
273 store i32 0, i32* %p
274 %r2 = load float* %q
275 %rv2 = insertvalue { i32, float } %rv1, float %r2, 1
276 ret { i32, float } %rv2
277}
278
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000279; CHECK: call_ret_i32_float_pair
280; CHECK: call ret_i32_float_pair
281; CHECK: st %o0, [%i0]
282; CHECK: st %f3, [%i1]
283define void @call_ret_i32_float_pair(i32* %i0, float* %i1) {
284 %rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef,
285 i32* undef, float* undef)
286 %e0 = extractvalue { i32, float } %rv, 0
287 store i32 %e0, i32* %i0
288 %e1 = extractvalue { i32, float } %rv, 1
289 store float %e1, float* %i1
290 ret void
291}
292
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000293; This is a C struct, each member uses 4 bytes.
294; CHECK: ret_i32_float_packed
295; CHECK: ld [%i2], [[R:%[gilo][0-7]]]
296; CHECK: sllx [[R]], 32, %i0
297; CHECK: ld [%i3], %f1
298define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1,
299 i32* %p, float* %q) {
300 %r1 = load i32* %p
301 %rv1 = insertvalue { i32, float } undef, i32 %r1, 0
302 store i32 0, i32* %p
303 %r2 = load float* %q
304 %rv2 = insertvalue { i32, float } %rv1, float %r2, 1
305 ret { i32, float } %rv2
306}
307
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000308; CHECK: call_ret_i32_float_packed
309; CHECK: call ret_i32_float_packed
310; CHECK: srlx %o0, 32, [[R:%[gilo][0-7]]]
311; CHECK: st [[R]], [%i0]
312; CHECK: st %f1, [%i1]
313define void @call_ret_i32_float_packed(i32* %i0, float* %i1) {
314 %rv = call { i32, float } @ret_i32_float_packed(i32 undef, i32 undef,
315 i32* undef, float* undef)
316 %e0 = extractvalue { i32, float } %rv, 0
317 store i32 %e0, i32* %i0
318 %e1 = extractvalue { i32, float } %rv, 1
319 store float %e1, float* %i1
320 ret void
321}
322
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000323; The C frontend should use i64 to return { i32, i32 } structs, but verify that
324; we don't miscompile thi case where both struct elements are placed in %i0.
325; CHECK: ret_i32_packed
326; CHECK: ld [%i2], [[R1:%[gilo][0-7]]]
327; CHECK: ld [%i3], [[R2:%[gilo][0-7]]]
328; CHECK: sllx [[R2]], 32, [[R3:%[gilo][0-7]]]
329; CHECK: or [[R3]], [[R1]], %i0
330define inreg { i32, i32 } @ret_i32_packed(i32 %a0, i32 %a1,
331 i32* %p, i32* %q) {
332 %r1 = load i32* %p
333 %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 1
334 store i32 0, i32* %p
335 %r2 = load i32* %q
336 %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 0
337 ret { i32, i32 } %rv2
338}
339
Jakob Stoklund Olesen18fdb392013-04-07 19:10:57 +0000340; CHECK: call_ret_i32_packed
341; CHECK: call ret_i32_packed
342; CHECK: srlx %o0, 32, [[R:%[gilo][0-7]]]
343; CHECK: st [[R]], [%i0]
344; CHECK: st %o0, [%i1]
345define void @call_ret_i32_packed(i32* %i0, i32* %i1) {
346 %rv = call { i32, i32 } @ret_i32_packed(i32 undef, i32 undef,
347 i32* undef, i32* undef)
348 %e0 = extractvalue { i32, i32 } %rv, 0
349 store i32 %e0, i32* %i0
350 %e1 = extractvalue { i32, i32 } %rv, 1
351 store i32 %e1, i32* %i1
352 ret void
353}
354
Jakob Stoklund Olesen53d4bcf2013-04-06 23:57:33 +0000355; The return value must be sign-extended to 64 bits.
356; CHECK: ret_sext
357; CHECK: sra %i0, 0, %i0
358define signext i32 @ret_sext(i32 %a0) {
359 ret i32 %a0
360}
361
362; CHECK: ret_zext
363; CHECK: srl %i0, 0, %i0
364define zeroext i32 @ret_zext(i32 %a0) {
365 ret i32 %a0
366}
367
368; CHECK: ret_nosext
369; CHECK-NOT: sra
370define signext i32 @ret_nosext(i32 signext %a0) {
371 ret i32 %a0
372}
373
374; CHECK: ret_nozext
375; CHECK-NOT: srl
376define signext i32 @ret_nozext(i32 signext %a0) {
377 ret i32 %a0
378}