Allow AVX vrsqrtps generation.
[oota-llvm.git] / test / CodeGen / PowerPC / ppc64le-aggregates.ll
1 ; RUN: llc < %s -march=ppc64le -mcpu=pwr8 -mattr=+altivec | FileCheck %s
2
3 target datalayout = "e-m:e-i64:64-n32:64"
4 target triple = "powerpc64le-unknown-linux-gnu"
5
6 ;
7 ; Verify use of registers for float/vector aggregate return.
8 ;
9
10 define [8 x float] @return_float([8 x float] %x) {
11 entry:
12   ret [8 x float] %x
13 }
14 ; CHECK-LABEL: @return_float
15 ; CHECK: %entry
16 ; CHECK-NEXT: blr
17
18 define [8 x double] @return_double([8 x double] %x) {
19 entry:
20   ret [8 x double] %x
21 }
22 ; CHECK-LABEL: @return_double
23 ; CHECK: %entry
24 ; CHECK-NEXT: blr
25
26 define [4 x ppc_fp128] @return_ppcf128([4 x ppc_fp128] %x) {
27 entry:
28   ret [4 x ppc_fp128] %x
29 }
30 ; CHECK-LABEL: @return_ppcf128
31 ; CHECK: %entry
32 ; CHECK-NEXT: blr
33
34 define [8 x <4 x i32>] @return_v4i32([8 x <4 x i32>] %x) {
35 entry:
36   ret [8 x <4 x i32>] %x
37 }
38 ; CHECK-LABEL: @return_v4i32
39 ; CHECK: %entry
40 ; CHECK-NEXT: blr
41
42
43 ;
44 ; Verify amount of space taken up by aggregates in the parameter save area.
45 ;
46
47 define i64 @callee_float([7 x float] %a, [7 x float] %b, i64 %c) {
48 entry:
49   ret i64 %c
50 }
51 ; CHECK-LABEL: @callee_float
52 ; CHECK: ld 3, 96(1)
53 ; CHECK: blr
54
55 define void @caller_float(i64 %x, [7 x float] %y) {
56 entry:
57   tail call void @test_float([7 x float] %y, [7 x float] %y, i64 %x)
58   ret void
59 }
60 ; CHECK-LABEL: @caller_float
61 ; CHECK: std 3, 96(1)
62 ; CHECK: bl test_float
63
64 declare void @test_float([7 x float], [7 x float], i64)
65
66 define i64 @callee_double(i64 %a, [7 x double] %b, i64 %c) {
67 entry:
68   ret i64 %c
69 }
70 ; CHECK-LABEL: @callee_double
71 ; CHECK: ld 3, 96(1)
72 ; CHECK: blr
73
74 define void @caller_double(i64 %x, [7 x double] %y) {
75 entry:
76   tail call void @test_double(i64 %x, [7 x double] %y, i64 %x)
77   ret void
78 }
79 ; CHECK-LABEL: @caller_double
80 ; CHECK: std 3, 96(1)
81 ; CHECK: bl test_double
82
83 declare void @test_double(i64, [7 x double], i64)
84
85 define i64 @callee_ppcf128(i64 %a, [4 x ppc_fp128] %b, i64 %c) {
86 entry:
87   ret i64 %c
88 }
89 ; CHECK-LABEL: @callee_ppcf128
90 ; CHECK: ld 3, 104(1)
91 ; CHECK: blr
92
93 define void @caller_ppcf128(i64 %x, [4 x ppc_fp128] %y) {
94 entry:
95   tail call void @test_ppcf128(i64 %x, [4 x ppc_fp128] %y, i64 %x)
96   ret void
97 }
98 ; CHECK-LABEL: @caller_ppcf128
99 ; CHECK: std 3, 104(1)
100 ; CHECK: bl test_ppcf128
101
102 declare void @test_ppcf128(i64, [4 x ppc_fp128], i64)
103
104 define i64 @callee_i64(i64 %a, [7 x i64] %b, i64 %c) {
105 entry:
106   ret i64 %c
107 }
108 ; CHECK-LABEL: @callee_i64
109 ; CHECK: ld 3, 96(1)
110 ; CHECK: blr
111
112 define void @caller_i64(i64 %x, [7 x i64] %y) {
113 entry:
114   tail call void @test_i64(i64 %x, [7 x i64] %y, i64 %x)
115   ret void
116 }
117 ; CHECK-LABEL: @caller_i64
118 ; CHECK: std 3, 96(1)
119 ; CHECK: bl test_i64
120
121 declare void @test_i64(i64, [7 x i64], i64)
122
123 define i64 @callee_i128(i64 %a, [4 x i128] %b, i64 %c) {
124 entry:
125   ret i64 %c
126 }
127 ; CHECK-LABEL: @callee_i128
128 ; CHECK: ld 3, 112(1)
129 ; CHECK: blr
130
131 define void @caller_i128(i64 %x, [4 x i128] %y) {
132 entry:
133   tail call void @test_i128(i64 %x, [4 x i128] %y, i64 %x)
134   ret void
135 }
136 ; CHECK-LABEL: @caller_i128
137 ; CHECK: std 3, 112(1)
138 ; CHECK: bl test_i128
139
140 declare void @test_i128(i64, [4 x i128], i64)
141
142 define i64 @callee_v4i32(i64 %a, [4 x <4 x i32>] %b, i64 %c) {
143 entry:
144   ret i64 %c
145 }
146 ; CHECK-LABEL: @callee_v4i32
147 ; CHECK: ld 3, 112(1)
148 ; CHECK: blr
149
150 define void @caller_v4i32(i64 %x, [4 x <4 x i32>] %y) {
151 entry:
152   tail call void @test_v4i32(i64 %x, [4 x <4 x i32>] %y, i64 %x)
153   ret void
154 }
155 ; CHECK-LABEL: @caller_v4i32
156 ; CHECK: std 3, 112(1)
157 ; CHECK: bl test_v4i32
158
159 declare void @test_v4i32(i64, [4 x <4 x i32>], i64)
160
161
162 ;
163 ; Verify handling of floating point arguments in GPRs
164 ;
165
166 %struct.float8 = type { [8 x float] }
167 %struct.float5 = type { [5 x float] }
168 %struct.float2 = type { [2 x float] }
169
170 @g8 = common global %struct.float8 zeroinitializer, align 4
171 @g5 = common global %struct.float5 zeroinitializer, align 4
172 @g2 = common global %struct.float2 zeroinitializer, align 4
173
174 define float @callee0([7 x float] %a, [7 x float] %b) {
175 entry:
176   %b.extract = extractvalue [7 x float] %b, 6
177   ret float %b.extract
178 }
179 ; CHECK-LABEL: @callee0
180 ; CHECK: stw 10, [[OFF:.*]](1)
181 ; CHECK: lfs 1, [[OFF]](1)
182 ; CHECK: blr
183
184 define void @caller0([7 x float] %a) {
185 entry:
186   tail call void @test0([7 x float] %a, [7 x float] %a)
187   ret void
188 }
189 ; CHECK-LABEL: @caller0
190 ; CHECK-DAG: fmr 8, 1
191 ; CHECK-DAG: fmr 9, 2
192 ; CHECK-DAG: fmr 10, 3
193 ; CHECK-DAG: fmr 11, 4
194 ; CHECK-DAG: fmr 12, 5
195 ; CHECK-DAG: fmr 13, 6
196 ; CHECK-DAG: stfs 7, [[OFF:[0-9]+]](1)
197 ; CHECK-DAG: lwz 10, [[OFF]](1)
198 ; CHECK: bl test0
199
200 declare void @test0([7 x float], [7 x float])
201
202 define float @callee1([8 x float] %a, [8 x float] %b) {
203 entry:
204   %b.extract = extractvalue [8 x float] %b, 7
205   ret float %b.extract
206 }
207 ; CHECK-LABEL: @callee1
208 ; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32
209 ; CHECK: stw [[REG]], [[OFF:.*]](1)
210 ; CHECK: lfs 1, [[OFF]](1)
211 ; CHECK: blr
212
213 define void @caller1([8 x float] %a) {
214 entry:
215   tail call void @test1([8 x float] %a, [8 x float] %a)
216   ret void
217 }
218 ; CHECK-LABEL: @caller1
219 ; CHECK-DAG: fmr 9, 1
220 ; CHECK-DAG: fmr 10, 2
221 ; CHECK-DAG: fmr 11, 3
222 ; CHECK-DAG: fmr 12, 4
223 ; CHECK-DAG: fmr 13, 5
224 ; CHECK-DAG: stfs 5, [[OFF0:[0-9]+]](1)
225 ; CHECK-DAG: stfs 6, [[OFF1:[0-9]+]](1)
226 ; CHECK-DAG: stfs 7, [[OFF2:[0-9]+]](1)
227 ; CHECK-DAG: stfs 8, [[OFF3:[0-9]+]](1)
228 ; CHECK-DAG: lwz [[REG0:[0-9]+]], [[OFF0]](1)
229 ; CHECK-DAG: lwz [[REG1:[0-9]+]], [[OFF1]](1)
230 ; CHECK-DAG: lwz [[REG2:[0-9]+]], [[OFF2]](1)
231 ; CHECK-DAG: lwz [[REG3:[0-9]+]], [[OFF3]](1)
232 ; CHECK-DAG: sldi [[REG1]], [[REG1]], 32
233 ; CHECK-DAG: sldi [[REG3]], [[REG3]], 32
234 ; CHECK-DAG: or 9, [[REG0]], [[REG1]]
235 ; CHECK-DAG: or 10, [[REG2]], [[REG3]]
236 ; CHECK: bl test1
237
238 declare void @test1([8 x float], [8 x float])
239
240 define float @callee2([8 x float] %a, [5 x float] %b, [2 x float] %c) {
241 entry:
242   %c.extract = extractvalue [2 x float] %c, 1
243   ret float %c.extract
244 }
245 ; CHECK-LABEL: @callee2
246 ; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32
247 ; CHECK: stw [[REG]], [[OFF:.*]](1)
248 ; CHECK: lfs 1, [[OFF]](1)
249 ; CHECK: blr
250
251 define void @caller2() {
252 entry:
253   %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4
254   %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4
255   %2 = load [2 x float]* getelementptr inbounds (%struct.float2* @g2, i64 0, i32 0), align 4
256   tail call void @test2([8 x float] %0, [5 x float] %1, [2 x float] %2)
257   ret void
258 }
259 ; CHECK-LABEL: @caller2
260 ; CHECK: ld [[REG:[0-9]+]], .LC
261 ; CHECK-DAG: lfs 1, 0([[REG]])
262 ; CHECK-DAG: lfs 2, 4([[REG]])
263 ; CHECK-DAG: lfs 3, 8([[REG]])
264 ; CHECK-DAG: lfs 4, 12([[REG]])
265 ; CHECK-DAG: lfs 5, 16([[REG]])
266 ; CHECK-DAG: lfs 6, 20([[REG]])
267 ; CHECK-DAG: lfs 7, 24([[REG]])
268 ; CHECK-DAG: lfs 8, 28([[REG]])
269 ; CHECK: ld [[REG:[0-9]+]], .LC
270 ; CHECK-DAG: lfs 9, 0([[REG]])
271 ; CHECK-DAG: lfs 10, 4([[REG]])
272 ; CHECK-DAG: lfs 11, 8([[REG]])
273 ; CHECK-DAG: lfs 12, 12([[REG]])
274 ; CHECK-DAG: lfs 13, 16([[REG]])
275 ; CHECK: ld [[REG:[0-9]+]], .LC
276 ; CHECK-DAG: lwz [[REG0:[0-9]+]], 0([[REG]])
277 ; CHECK-DAG: lwz [[REG1:[0-9]+]], 4([[REG]])
278 ; CHECK-DAG: sldi [[REG1]], [[REG1]], 32
279 ; CHECK-DAG: or 10, [[REG0]], [[REG1]]
280 ; CHECK: bl test2
281
282 declare void @test2([8 x float], [5 x float], [2 x float])
283
284 define double @callee3([8 x float] %a, [5 x float] %b, double %c) {
285 entry:
286   ret double %c
287 }
288 ; CHECK-LABEL: @callee3
289 ; CHECK: std 10, [[OFF:.*]](1)
290 ; CHECK: lfd 1, [[OFF]](1)
291 ; CHECK: blr
292
293 define void @caller3(double %d) {
294 entry:
295   %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4
296   %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4
297   tail call void @test3([8 x float] %0, [5 x float] %1, double %d)
298   ret void
299 }
300 ; CHECK-LABEL: @caller3
301 ; CHECK: stfd 1, [[OFF:.*]](1)
302 ; CHECK: ld 10, [[OFF]](1)
303 ; CHECK: bl test3
304
305 declare void @test3([8 x float], [5 x float], double)
306
307 define float @callee4([8 x float] %a, [5 x float] %b, float %c) {
308 entry:
309   ret float %c
310 }
311 ; CHECK-LABEL: @callee4
312 ; CHECK: stw 10, [[OFF:.*]](1)
313 ; CHECK: lfs 1, [[OFF]](1)
314 ; CHECK: blr
315
316 define void @caller4(float %f) {
317 entry:
318   %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4
319   %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4
320   tail call void @test4([8 x float] %0, [5 x float] %1, float %f)
321   ret void
322 }
323 ; CHECK-LABEL: @caller4
324 ; CHECK: stfs 1, [[OFF:.*]](1)
325 ; CHECK: lwz 10, [[OFF]](1)
326 ; CHECK: bl test4
327
328 declare void @test4([8 x float], [5 x float], float)
329