Implement LowerReturn_64 for SPARC v9.
[oota-llvm.git] / test / CodeGen / SPARC / 64abi.ll
1 ; RUN: llc < %s -march=sparcv9 | FileCheck %s
2
3 ; CHECK: intarg
4 ; CHECK: stb %i0, [%i4]
5 ; CHECK: stb %i1, [%i4]
6 ; CHECK: sth %i2, [%i4]
7 ; CHECK: st  %i3, [%i4]
8 ; CHECK: stx %i4, [%i4]
9 ; CHECK: st  %i5, [%i4]
10 ; CHECK: ld [%fp+2227], [[R:%[gilo][0-7]]]
11 ; CHECK: st  [[R]], [%i4]
12 ; CHECK: ldx [%fp+2231], [[R:%[gilo][0-7]]]
13 ; CHECK: stx [[R]], [%i4]
14 define void @intarg(i8  %a0,   ; %i0
15                     i8  %a1,   ; %i1
16                     i16 %a2,   ; %i2
17                     i32 %a3,   ; %i3
18                     i8* %a4,   ; %i4
19                     i32 %a5,   ; %i5
20                     i32 %a6,   ; [%fp+BIAS+176]
21                     i8* %a7) { ; [%fp+BIAS+184]
22   store i8 %a0, i8* %a4
23   store i8 %a1, i8* %a4
24   %p16 = bitcast i8* %a4 to i16*
25   store i16 %a2, i16* %p16
26   %p32 = bitcast i8* %a4 to i32*
27   store i32 %a3, i32* %p32
28   %pp = bitcast i8* %a4 to i8**
29   store i8* %a4, i8** %pp
30   store i32 %a5, i32* %p32
31   store i32 %a6, i32* %p32
32   store i8* %a7, i8** %pp
33   ret void
34 }
35
36 ; CHECK: floatarg
37 ; CHECK: fstod %f1,
38 ; CHECK: faddd %f2,
39 ; CHECK: faddd %f4,
40 ; CHECK: faddd %f6,
41 ; CHECK: ld [%fp+2307], [[F:%f[0-9]+]]
42 ; CHECK: fadds %f31, [[F]]
43 define double @floatarg(float %a0,    ; %f1
44                         double %a1,   ; %d2
45                         double %a2,   ; %d4
46                         double %a3,   ; %d6
47                         float %a4,    ; %f9
48                         float %a5,    ; %f11
49                         float %a6,    ; %f13
50                         float %a7,    ; %f15
51                         float %a8,    ; %f17
52                         float %a9,    ; %f19
53                         float %a10,   ; %f21
54                         float %a11,   ; %f23
55                         float %a12,   ; %f25
56                         float %a13,   ; %f27
57                         float %a14,   ; %f29
58                         float %a15,   ; %f31
59                         float %a16,   ; [%fp+BIAS+256] (using 8 bytes)
60                         float %a17) { ; [%fp+BIAS+264] (using 8 bytes)
61   %d0 = fpext float %a0 to double
62   %s1 = fadd double %a1, %d0
63   %s2 = fadd double %a2, %s1
64   %s3 = fadd double %a3, %s2
65   %s16 = fadd float %a15, %a16
66   %d16 = fpext float %s16 to double
67   %s17 = fadd double %d16, %s3
68   ret double %s17
69 }
70
71 ; CHECK: mixedarg
72 ; CHECK: fstod %f3
73 ; CHECK: faddd %f6
74 ; CHECK: faddd %f16
75 ; CHECK: ldx [%fp+2231]
76 ; CHECK: ldx [%fp+2247]
77 define void @mixedarg(i8 %a0,      ; %i0
78                       float %a1,   ; %f3
79                       i16 %a2,     ; %i2
80                       double %a3,  ; %d6
81                       i13 %a4,     ; %i4
82                       float %a5,   ; %f11
83                       i64 %a6,     ; [%fp+BIAS+176]
84                       double *%a7, ; [%fp+BIAS+184]
85                       double %a8,  ; %d16
86                       i16* %a9) {  ; [%fp+BIAS+200]
87   %d1 = fpext float %a1 to double
88   %s3 = fadd double %a3, %d1
89   %s8 = fadd double %a8, %s3
90   store double %s8, double* %a7
91   store i16 %a2, i16* %a9
92   ret void
93 }
94
95 ; The inreg attribute is used to indicate 32-bit sized struct elements that
96 ; share an 8-byte slot.
97 ; CHECK: inreg_fi
98 ; CHECK: fstoi %f1
99 ; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]]
100 ; CHECK: sub [[R]],
101 define i32 @inreg_fi(i32 inreg %a0,     ; high bits of %i0
102                      float inreg %a1) { ; %f1
103   %b1 = fptosi float %a1 to i32
104   %rv = sub i32 %a0, %b1
105   ret i32 %rv
106 }
107
108 ; CHECK: inreg_ff
109 ; CHECK: fsubs %f0, %f1, %f1
110 define float @inreg_ff(float inreg %a0,   ; %f0
111                        float inreg %a1) { ; %f1
112   %rv = fsub float %a0, %a1
113   ret float %rv
114 }
115
116 ; CHECK: inreg_if
117 ; CHECK: fstoi %f0
118 ; CHECK: sub %i0
119 define i32 @inreg_if(float inreg %a0, ; %f0
120                      i32 inreg %a1) { ; low bits of %i0
121   %b0 = fptosi float %a0 to i32
122   %rv = sub i32 %a1, %b0
123   ret i32 %rv
124 }
125
126 ; The frontend shouldn't do this. Just pass i64 instead.
127 ; CHECK: inreg_ii
128 ; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]]
129 ; CHECK: sub %i0, [[R]], %i0
130 define i32 @inreg_ii(i32 inreg %a0,   ; high bits of %i0
131                      i32 inreg %a1) { ; low bits of %i0
132   %rv = sub i32 %a1, %a0
133   ret i32 %rv
134 }
135
136 ; Structs up to 32 bytes in size can be returned in registers.
137 ; CHECK: ret_i64_pair
138 ; CHECK: ldx [%i2], %i0
139 ; CHECK: ldx [%i3], %i1
140 define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) {
141   %r1 = load i64* %p
142   %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0
143   store i64 0, i64* %p
144   %r2 = load i64* %q
145   %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1
146   ret { i64, i64 } %rv2
147 }
148
149 ; This is not a C struct, each member uses 8 bytes.
150 ; CHECK: ret_i32_float_pair
151 ; CHECK: ld [%i2], %i0
152 ; CHECK: ld [%i3], %f3
153 define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1,
154                                           i32* %p, float* %q) {
155   %r1 = load i32* %p
156   %rv1 = insertvalue { i32, float } undef, i32 %r1, 0
157   store i32 0, i32* %p
158   %r2 = load float* %q
159   %rv2 = insertvalue { i32, float } %rv1, float %r2, 1
160   ret { i32, float } %rv2
161 }
162
163 ; This is a C struct, each member uses 4 bytes.
164 ; CHECK: ret_i32_float_packed
165 ; CHECK: ld [%i2], [[R:%[gilo][0-7]]]
166 ; CHECK: sllx [[R]], 32, %i0
167 ; CHECK: ld [%i3], %f1
168 define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1,
169                                                   i32* %p, float* %q) {
170   %r1 = load i32* %p
171   %rv1 = insertvalue { i32, float } undef, i32 %r1, 0
172   store i32 0, i32* %p
173   %r2 = load float* %q
174   %rv2 = insertvalue { i32, float } %rv1, float %r2, 1
175   ret { i32, float } %rv2
176 }
177
178 ; The C frontend should use i64 to return { i32, i32 } structs, but verify that
179 ; we don't miscompile thi case where both struct elements are placed in %i0.
180 ; CHECK: ret_i32_packed
181 ; CHECK: ld [%i2], [[R1:%[gilo][0-7]]]
182 ; CHECK: ld [%i3], [[R2:%[gilo][0-7]]]
183 ; CHECK: sllx [[R2]], 32, [[R3:%[gilo][0-7]]]
184 ; CHECK: or [[R3]], [[R1]], %i0
185 define inreg { i32, i32 } @ret_i32_packed(i32 %a0, i32 %a1,
186                                           i32* %p, i32* %q) {
187   %r1 = load i32* %p
188   %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 1
189   store i32 0, i32* %p
190   %r2 = load i32* %q
191   %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 0
192   ret { i32, i32 } %rv2
193 }
194
195 ; The return value must be sign-extended to 64 bits.
196 ; CHECK: ret_sext
197 ; CHECK: sra %i0, 0, %i0
198 define signext i32 @ret_sext(i32 %a0) {
199   ret i32 %a0
200 }
201
202 ; CHECK: ret_zext
203 ; CHECK: srl %i0, 0, %i0
204 define zeroext i32 @ret_zext(i32 %a0) {
205   ret i32 %a0
206 }
207
208 ; CHECK: ret_nosext
209 ; CHECK-NOT: sra
210 define signext i32 @ret_nosext(i32 signext %a0) {
211   ret i32 %a0
212 }
213
214 ; CHECK: ret_nozext
215 ; CHECK-NOT: srl
216 define signext i32 @ret_nozext(i32 signext %a0) {
217   ret i32 %a0
218 }