1 // RUN: %clang_cc1 -target-feature +altivec -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
3 // Test homogeneous float aggregate passing and returning.
5 struct f1
{ float f
[1]; };
6 struct f2
{ float f
[2]; };
7 struct f3
{ float f
[3]; };
8 struct f4
{ float f
[4]; };
9 struct f5
{ float f
[5]; };
10 struct f6
{ float f
[6]; };
11 struct f7
{ float f
[7]; };
12 struct f8
{ float f
[8]; };
13 struct f9
{ float f
[9]; };
15 struct fab
{ float a
; float b
; };
16 struct fabc
{ float a
; float b
; float c
; };
18 struct f2a2b
{ float a
[2]; float b
[2]; };
20 // CHECK: define{{.*}} [1 x float] @func_f1(float inreg %x.coerce)
21 struct f1
func_f1(struct f1 x
) { return x
; }
23 // CHECK: define{{.*}} [2 x float] @func_f2([2 x float] %x.coerce)
24 struct f2
func_f2(struct f2 x
) { return x
; }
26 // CHECK: define{{.*}} [3 x float] @func_f3([3 x float] %x.coerce)
27 struct f3
func_f3(struct f3 x
) { return x
; }
29 // CHECK: define{{.*}} [4 x float] @func_f4([4 x float] %x.coerce)
30 struct f4
func_f4(struct f4 x
) { return x
; }
32 // CHECK: define{{.*}} [5 x float] @func_f5([5 x float] %x.coerce)
33 struct f5
func_f5(struct f5 x
) { return x
; }
35 // CHECK: define{{.*}} [6 x float] @func_f6([6 x float] %x.coerce)
36 struct f6
func_f6(struct f6 x
) { return x
; }
38 // CHECK: define{{.*}} [7 x float] @func_f7([7 x float] %x.coerce)
39 struct f7
func_f7(struct f7 x
) { return x
; }
41 // CHECK: define{{.*}} [8 x float] @func_f8([8 x float] %x.coerce)
42 struct f8
func_f8(struct f8 x
) { return x
; }
44 // CHECK: define{{.*}} void @func_f9(ptr noalias sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce)
45 struct f9
func_f9(struct f9 x
) { return x
; }
47 // CHECK: define{{.*}} [2 x float] @func_fab([2 x float] %x.coerce)
48 struct fab
func_fab(struct fab x
) { return x
; }
50 // CHECK: define{{.*}} [3 x float] @func_fabc([3 x float] %x.coerce)
51 struct fabc
func_fabc(struct fabc x
) { return x
; }
53 // CHECK: define{{.*}} [4 x float] @func_f2a2b([4 x float] %x.coerce)
54 struct f2a2b
func_f2a2b(struct f2a2b x
) { return x
; }
56 // CHECK-LABEL: @call_f1
57 // CHECK: %[[TMP:[^ ]+]] = load float, ptr @global_f1, align 4
58 // CHECK: call [1 x float] @func_f1(float inreg %[[TMP]])
60 void call_f1(void) { global_f1
= func_f1(global_f1
); }
62 // CHECK-LABEL: @call_f2
63 // CHECK: %[[TMP:[^ ]+]] = load [2 x float], ptr @global_f2, align 4
64 // CHECK: call [2 x float] @func_f2([2 x float] %[[TMP]])
66 void call_f2(void) { global_f2
= func_f2(global_f2
); }
68 // CHECK-LABEL: @call_f3
69 // CHECK: %[[TMP:[^ ]+]] = load [3 x float], ptr @global_f3, align 4
70 // CHECK: call [3 x float] @func_f3([3 x float] %[[TMP]])
72 void call_f3(void) { global_f3
= func_f3(global_f3
); }
74 // CHECK-LABEL: @call_f4
75 // CHECK: %[[TMP:[^ ]+]] = load [4 x float], ptr @global_f4, align 4
76 // CHECK: call [4 x float] @func_f4([4 x float] %[[TMP]])
78 void call_f4(void) { global_f4
= func_f4(global_f4
); }
80 // CHECK-LABEL: @call_f5
81 // CHECK: %[[TMP:[^ ]+]] = load [5 x float], ptr @global_f5, align 4
82 // CHECK: call [5 x float] @func_f5([5 x float] %[[TMP]])
84 void call_f5(void) { global_f5
= func_f5(global_f5
); }
86 // CHECK-LABEL: @call_f6
87 // CHECK: %[[TMP:[^ ]+]] = load [6 x float], ptr @global_f6, align 4
88 // CHECK: call [6 x float] @func_f6([6 x float] %[[TMP]])
90 void call_f6(void) { global_f6
= func_f6(global_f6
); }
92 // CHECK-LABEL: @call_f7
93 // CHECK: %[[TMP:[^ ]+]] = load [7 x float], ptr @global_f7, align 4
94 // CHECK: call [7 x float] @func_f7([7 x float] %[[TMP]])
96 void call_f7(void) { global_f7
= func_f7(global_f7
); }
98 // CHECK-LABEL: @call_f8
99 // CHECK: %[[TMP:[^ ]+]] = load [8 x float], ptr @global_f8, align 4
100 // CHECK: call [8 x float] @func_f8([8 x float] %[[TMP]])
102 void call_f8(void) { global_f8
= func_f8(global_f8
); }
104 // CHECK-LABEL: @call_f9
105 // CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64]
106 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f9, i64 36, i1 false)
107 // CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], ptr %[[TMP1]]
108 // CHECK: call void @func_f9(ptr sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]])
110 void call_f9(void) { global_f9
= func_f9(global_f9
); }
112 // CHECK-LABEL: @call_fab
113 // CHECK: %[[TMP:[^ ]+]] = load [2 x float], ptr @global_fab
114 // CHECK: call [2 x float] @func_fab([2 x float] %[[TMP]])
115 struct fab global_fab
;
116 void call_fab(void) { global_fab
= func_fab(global_fab
); }
118 // CHECK-LABEL: @call_fabc
119 // CHECK: %[[TMP:[^ ]+]] = load [3 x float], ptr @global_fabc
120 // CHECK: call [3 x float] @func_fabc([3 x float] %[[TMP]])
121 struct fabc global_fabc
;
122 void call_fabc(void) { global_fabc
= func_fabc(global_fabc
); }
125 // Test homogeneous vector aggregate passing and returning.
127 struct v1
{ vector
int v
[1]; };
128 struct v2
{ vector
int v
[2]; };
129 struct v3
{ vector
int v
[3]; };
130 struct v4
{ vector
int v
[4]; };
131 struct v5
{ vector
int v
[5]; };
132 struct v6
{ vector
int v
[6]; };
133 struct v7
{ vector
int v
[7]; };
134 struct v8
{ vector
int v
[8]; };
135 struct v9
{ vector
int v
[9]; };
137 struct vab
{ vector
int a
; vector
int b
; };
138 struct vabc
{ vector
int a
; vector
int b
; vector
int c
; };
140 // CHECK: define{{.*}} [1 x <4 x i32>] @func_v1(<4 x i32> inreg %x.coerce)
141 struct v1
func_v1(struct v1 x
) { return x
; }
143 // CHECK: define{{.*}} [2 x <4 x i32>] @func_v2([2 x <4 x i32>] %x.coerce)
144 struct v2
func_v2(struct v2 x
) { return x
; }
146 // CHECK: define{{.*}} [3 x <4 x i32>] @func_v3([3 x <4 x i32>] %x.coerce)
147 struct v3
func_v3(struct v3 x
) { return x
; }
149 // CHECK: define{{.*}} [4 x <4 x i32>] @func_v4([4 x <4 x i32>] %x.coerce)
150 struct v4
func_v4(struct v4 x
) { return x
; }
152 // CHECK: define{{.*}} [5 x <4 x i32>] @func_v5([5 x <4 x i32>] %x.coerce)
153 struct v5
func_v5(struct v5 x
) { return x
; }
155 // CHECK: define{{.*}} [6 x <4 x i32>] @func_v6([6 x <4 x i32>] %x.coerce)
156 struct v6
func_v6(struct v6 x
) { return x
; }
158 // CHECK: define{{.*}} [7 x <4 x i32>] @func_v7([7 x <4 x i32>] %x.coerce)
159 struct v7
func_v7(struct v7 x
) { return x
; }
161 // CHECK: define{{.*}} [8 x <4 x i32>] @func_v8([8 x <4 x i32>] %x.coerce)
162 struct v8
func_v8(struct v8 x
) { return x
; }
164 // CHECK: define{{.*}} void @func_v9(ptr noalias sret(%struct.v9) align 16 %agg.result, ptr noundef byval(%struct.v9) align 16 %x)
165 struct v9
func_v9(struct v9 x
) { return x
; }
167 // CHECK: define{{.*}} [2 x <4 x i32>] @func_vab([2 x <4 x i32>] %x.coerce)
168 struct vab
func_vab(struct vab x
) { return x
; }
170 // CHECK: define{{.*}} [3 x <4 x i32>] @func_vabc([3 x <4 x i32>] %x.coerce)
171 struct vabc
func_vabc(struct vabc x
) { return x
; }
173 // CHECK-LABEL: @call_v1
174 // CHECK: %[[TMP:[^ ]+]] = load <4 x i32>, ptr @global_v1, align 1
175 // CHECK: call [1 x <4 x i32>] @func_v1(<4 x i32> inreg %[[TMP]])
177 void call_v1(void) { global_v1
= func_v1(global_v1
); }
179 // CHECK-LABEL: @call_v2
180 // CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x i32>], ptr @global_v2, align 1
181 // CHECK: call [2 x <4 x i32>] @func_v2([2 x <4 x i32>] %[[TMP]])
183 void call_v2(void) { global_v2
= func_v2(global_v2
); }
185 // CHECK-LABEL: @call_v3
186 // CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x i32>], ptr @global_v3, align 1
187 // CHECK: call [3 x <4 x i32>] @func_v3([3 x <4 x i32>] %[[TMP]])
189 void call_v3(void) { global_v3
= func_v3(global_v3
); }
191 // CHECK-LABEL: @call_v4
192 // CHECK: %[[TMP:[^ ]+]] = load [4 x <4 x i32>], ptr @global_v4, align 1
193 // CHECK: call [4 x <4 x i32>] @func_v4([4 x <4 x i32>] %[[TMP]])
195 void call_v4(void) { global_v4
= func_v4(global_v4
); }
197 // CHECK-LABEL: @call_v5
198 // CHECK: %[[TMP:[^ ]+]] = load [5 x <4 x i32>], ptr @global_v5, align 1
199 // CHECK: call [5 x <4 x i32>] @func_v5([5 x <4 x i32>] %[[TMP]])
201 void call_v5(void) { global_v5
= func_v5(global_v5
); }
203 // CHECK-LABEL: @call_v6
204 // CHECK: %[[TMP:[^ ]+]] = load [6 x <4 x i32>], ptr @global_v6, align 1
205 // CHECK: call [6 x <4 x i32>] @func_v6([6 x <4 x i32>] %[[TMP]])
207 void call_v6(void) { global_v6
= func_v6(global_v6
); }
209 // CHECK-LABEL: @call_v7
210 // CHECK: %[[TMP:[^ ]+]] = load [7 x <4 x i32>], ptr @global_v7, align 1
211 // CHECK: call [7 x <4 x i32>] @func_v7([7 x <4 x i32>] %[[TMP]])
213 void call_v7(void) { global_v7
= func_v7(global_v7
); }
215 // CHECK-LABEL: @call_v8
216 // CHECK: %[[TMP:[^ ]+]] = load [8 x <4 x i32>], ptr @global_v8, align 1
217 // CHECK: call [8 x <4 x i32>] @func_v8([8 x <4 x i32>] %[[TMP]])
219 void call_v8(void) { global_v8
= func_v8(global_v8
); }
221 // CHECK-LABEL: @call_v9
222 // CHECK: call void @func_v9(ptr sret(%struct.v9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v9) align 16 @global_v9)
224 void call_v9(void) { global_v9
= func_v9(global_v9
); }
226 // CHECK-LABEL: @call_vab
227 // CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x i32>], ptr @global_vab
228 // CHECK: call [2 x <4 x i32>] @func_vab([2 x <4 x i32>] %[[TMP]])
229 struct vab global_vab
;
230 void call_vab(void) { global_vab
= func_vab(global_vab
); }
232 // CHECK-LABEL: @call_vabc
233 // CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x i32>], ptr @global_vabc
234 // CHECK: call [3 x <4 x i32>] @func_vabc([3 x <4 x i32>] %[[TMP]])
235 struct vabc global_vabc
;
236 void call_vabc(void) { global_vabc
= func_vabc(global_vabc
); }
239 // As clang extension, non-power-of-two vectors may also be part of
240 // homogeneous aggregates.
242 typedef float float3
__attribute__((vector_size (12)));
244 struct v3f1
{ float3 v
[1]; };
245 struct v3f2
{ float3 v
[2]; };
246 struct v3f3
{ float3 v
[3]; };
247 struct v3f4
{ float3 v
[4]; };
248 struct v3f5
{ float3 v
[5]; };
249 struct v3f6
{ float3 v
[6]; };
250 struct v3f7
{ float3 v
[7]; };
251 struct v3f8
{ float3 v
[8]; };
252 struct v3f9
{ float3 v
[9]; };
254 struct v3fab
{ float3 a
; float3 b
; };
255 struct v3fabc
{ float3 a
; float3 b
; float3 c
; };
257 // CHECK: define{{.*}} [1 x <4 x float>] @func_v3f1(<3 x float> inreg %x.coerce)
258 struct v3f1
func_v3f1(struct v3f1 x
) { return x
; }
260 // CHECK: define{{.*}} [2 x <4 x float>] @func_v3f2([2 x <4 x float>] %x.coerce)
261 struct v3f2
func_v3f2(struct v3f2 x
) { return x
; }
263 // CHECK: define{{.*}} [3 x <4 x float>] @func_v3f3([3 x <4 x float>] %x.coerce)
264 struct v3f3
func_v3f3(struct v3f3 x
) { return x
; }
266 // CHECK: define{{.*}} [4 x <4 x float>] @func_v3f4([4 x <4 x float>] %x.coerce)
267 struct v3f4
func_v3f4(struct v3f4 x
) { return x
; }
269 // CHECK: define{{.*}} [5 x <4 x float>] @func_v3f5([5 x <4 x float>] %x.coerce)
270 struct v3f5
func_v3f5(struct v3f5 x
) { return x
; }
272 // CHECK: define{{.*}} [6 x <4 x float>] @func_v3f6([6 x <4 x float>] %x.coerce)
273 struct v3f6
func_v3f6(struct v3f6 x
) { return x
; }
275 // CHECK: define{{.*}} [7 x <4 x float>] @func_v3f7([7 x <4 x float>] %x.coerce)
276 struct v3f7
func_v3f7(struct v3f7 x
) { return x
; }
278 // CHECK: define{{.*}} [8 x <4 x float>] @func_v3f8([8 x <4 x float>] %x.coerce)
279 struct v3f8
func_v3f8(struct v3f8 x
) { return x
; }
281 // CHECK: define{{.*}} void @func_v3f9(ptr noalias sret(%struct.v3f9) align 16 %agg.result, ptr noundef byval(%struct.v3f9) align 16 %x)
282 struct v3f9
func_v3f9(struct v3f9 x
) { return x
; }
284 // CHECK: define{{.*}} [2 x <4 x float>] @func_v3fab([2 x <4 x float>] %x.coerce)
285 struct v3fab
func_v3fab(struct v3fab x
) { return x
; }
287 // CHECK: define{{.*}} [3 x <4 x float>] @func_v3fabc([3 x <4 x float>] %x.coerce)
288 struct v3fabc
func_v3fabc(struct v3fabc x
) { return x
; }
290 // CHECK-LABEL: @call_v3f1
291 // CHECK: %[[TMP:[^ ]+]] = load <3 x float>, ptr @global_v3f1, align 1
292 // CHECK: call [1 x <4 x float>] @func_v3f1(<3 x float> inreg %[[TMP]])
293 struct v3f1 global_v3f1
;
294 void call_v3f1(void) { global_v3f1
= func_v3f1(global_v3f1
); }
296 // CHECK-LABEL: @call_v3f2
297 // CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x float>], ptr @global_v3f2, align 16
298 // CHECK: call [2 x <4 x float>] @func_v3f2([2 x <4 x float>] %[[TMP]])
299 struct v3f2 global_v3f2
;
300 void call_v3f2(void) { global_v3f2
= func_v3f2(global_v3f2
); }
302 // CHECK-LABEL: @call_v3f3
303 // CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x float>], ptr @global_v3f3, align 16
304 // CHECK: call [3 x <4 x float>] @func_v3f3([3 x <4 x float>] %[[TMP]])
305 struct v3f3 global_v3f3
;
306 void call_v3f3(void) { global_v3f3
= func_v3f3(global_v3f3
); }
308 // CHECK-LABEL: @call_v3f4
309 // CHECK: %[[TMP:[^ ]+]] = load [4 x <4 x float>], ptr @global_v3f4, align 16
310 // CHECK: call [4 x <4 x float>] @func_v3f4([4 x <4 x float>] %[[TMP]])
311 struct v3f4 global_v3f4
;
312 void call_v3f4(void) { global_v3f4
= func_v3f4(global_v3f4
); }
314 // CHECK-LABEL: @call_v3f5
315 // CHECK: %[[TMP:[^ ]+]] = load [5 x <4 x float>], ptr @global_v3f5, align 16
316 // CHECK: call [5 x <4 x float>] @func_v3f5([5 x <4 x float>] %[[TMP]])
317 struct v3f5 global_v3f5
;
318 void call_v3f5(void) { global_v3f5
= func_v3f5(global_v3f5
); }
320 // CHECK-LABEL: @call_v3f6
321 // CHECK: %[[TMP:[^ ]+]] = load [6 x <4 x float>], ptr @global_v3f6, align 16
322 // CHECK: call [6 x <4 x float>] @func_v3f6([6 x <4 x float>] %[[TMP]])
323 struct v3f6 global_v3f6
;
324 void call_v3f6(void) { global_v3f6
= func_v3f6(global_v3f6
); }
326 // CHECK-LABEL: @call_v3f7
327 // CHECK: %[[TMP:[^ ]+]] = load [7 x <4 x float>], ptr @global_v3f7, align 16
328 // CHECK: call [7 x <4 x float>] @func_v3f7([7 x <4 x float>] %[[TMP]])
329 struct v3f7 global_v3f7
;
330 void call_v3f7(void) { global_v3f7
= func_v3f7(global_v3f7
); }
332 // CHECK-LABEL: @call_v3f8
333 // CHECK: %[[TMP:[^ ]+]] = load [8 x <4 x float>], ptr @global_v3f8, align 16
334 // CHECK: call [8 x <4 x float>] @func_v3f8([8 x <4 x float>] %[[TMP]])
335 struct v3f8 global_v3f8
;
336 void call_v3f8(void) { global_v3f8
= func_v3f8(global_v3f8
); }
338 // CHECK-LABEL: @call_v3f9
339 // CHECK: call void @func_v3f9(ptr sret(%struct.v3f9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v3f9) align 16 @global_v3f9)
340 struct v3f9 global_v3f9
;
341 void call_v3f9(void) { global_v3f9
= func_v3f9(global_v3f9
); }
343 // CHECK-LABEL: @call_v3fab
344 // CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x float>], ptr @global_v3fab, align 16
345 // CHECK: call [2 x <4 x float>] @func_v3fab([2 x <4 x float>] %[[TMP]])
346 struct v3fab global_v3fab
;
347 void call_v3fab(void) { global_v3fab
= func_v3fab(global_v3fab
); }
349 // CHECK-LABEL: @call_v3fabc
350 // CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x float>], ptr @global_v3fabc, align 16
351 // CHECK: call [3 x <4 x float>] @func_v3fabc([3 x <4 x float>] %[[TMP]])
352 struct v3fabc global_v3fabc
;
353 void call_v3fabc(void) { global_v3fabc
= func_v3fabc(global_v3fabc
); }
356 // Test returning small aggregates.
358 struct s1
{ char c
[1]; };
359 struct s2
{ char c
[2]; };
360 struct s3
{ char c
[3]; };
361 struct s4
{ char c
[4]; };
362 struct s5
{ char c
[5]; };
363 struct s6
{ char c
[6]; };
364 struct s7
{ char c
[7]; };
365 struct s8
{ char c
[8]; };
366 struct s9
{ char c
[9]; };
367 struct s16
{ char c
[16]; };
368 struct s17
{ char c
[17]; };
370 // CHECK: define{{.*}} i8 @ret_s1()
371 struct s1
ret_s1(void) {
372 return (struct s1
) { 17 };
375 // CHECK: define{{.*}} i16 @ret_s2()
376 struct s2
ret_s2(void) {
377 return (struct s2
) { 17, 18 };
380 // CHECK: define{{.*}} i24 @ret_s3()
381 struct s3
ret_s3(void) {
382 return (struct s3
) { 17, 18, 19 };
385 // CHECK: define{{.*}} i32 @ret_s4()
386 struct s4
ret_s4(void) {
387 return (struct s4
) { 17, 18, 19, 20 };
390 // CHECK: define{{.*}} i40 @ret_s5()
391 struct s5
ret_s5(void) {
392 return (struct s5
) { 17, 18, 19, 20, 21 };
395 // CHECK: define{{.*}} i48 @ret_s6()
396 struct s6
ret_s6(void) {
397 return (struct s6
) { 17, 18, 19, 20, 21, 22 };
400 // CHECK: define{{.*}} i56 @ret_s7()
401 struct s7
ret_s7(void) {
402 return (struct s7
) { 17, 18, 19, 20, 21, 22, 23 };
405 // CHECK: define{{.*}} i64 @ret_s8()
406 struct s8
ret_s8(void) {
407 return (struct s8
) { 17, 18, 19, 20, 21, 22, 23, 24 };
410 // CHECK: define{{.*}} { i64, i64 } @ret_s9()
411 struct s9
ret_s9(void) {
412 return (struct s9
) { 17, 18, 19, 20, 21, 22, 23, 24, 25 };
415 // CHECK: define{{.*}} { i64, i64 } @ret_s16()
416 struct s16
ret_s16(void) {
417 return (struct s16
) { 17, 18, 19, 20, 21, 22, 23, 24,
418 25, 26, 27, 28, 29, 30, 31, 32 };
421 // CHECK: define{{.*}} void @ret_s17(ptr
422 struct s17
ret_s17(void) {
423 return (struct s17
) { 17, 18, 19, 20, 21, 22, 23, 24,
424 25, 26, 27, 28, 29, 30, 31, 32, 33 };