1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 2
2 // RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - \
3 // RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64-LP64F,LP64 %s
4 // RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
5 // RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64F-LP64D,LP64-LP64F,LP64F %s
6 // RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
7 // RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64F-LP64D,LP64D %s
12 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_void
13 // LP64-LP64F-LP64D-SAME: () #[[ATTR0:[0-9]+]] {
14 // LP64-LP64F-LP64D: entry:
18 // Scalar arguments and return values smaller than the word size are extended
19 // according to the sign of their type, up to 32 bits
21 // LP64-LP64F-LP64D-LABEL: define dso_local zeroext i1 @f_scalar_0
22 // LP64-LP64F-LP64D-SAME: (i1 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
23 // LP64-LP64F-LP64D: entry:
25 _Bool
f_scalar_0(_Bool x
) { return x
; }
27 // LP64-LP64F-LP64D-LABEL: define dso_local signext i8 @f_scalar_1
28 // LP64-LP64F-LP64D-SAME: (i8 noundef signext [[X:%.*]]) #[[ATTR0]] {
29 // LP64-LP64F-LP64D: entry:
31 int8_t f_scalar_1(int8_t x
) { return x
; }
33 // LP64-LP64F-LP64D-LABEL: define dso_local zeroext i8 @f_scalar_2
34 // LP64-LP64F-LP64D-SAME: (i8 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
35 // LP64-LP64F-LP64D: entry:
37 uint8_t f_scalar_2(uint8_t x
) { return x
; }
39 // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_3
40 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
41 // LP64-LP64F-LP64D: entry:
43 uint32_t f_scalar_3(int32_t x
) { return x
; }
45 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_scalar_4
46 // LP64-LP64F-LP64D-SAME: (i64 noundef [[X:%.*]]) #[[ATTR0]] {
47 // LP64-LP64F-LP64D: entry:
49 int64_t f_scalar_4(int64_t x
) { return x
; }
51 // LP64-LP64F-LP64D-LABEL: define dso_local float @f_fp_scalar_1
52 // LP64-LP64F-LP64D-SAME: (float noundef [[X:%.*]]) #[[ATTR0]] {
53 // LP64-LP64F-LP64D: entry:
55 float f_fp_scalar_1(float x
) { return x
; }
57 // LP64-LP64F-LP64D-LABEL: define dso_local double @f_fp_scalar_2
58 // LP64-LP64F-LP64D-SAME: (double noundef [[X:%.*]]) #[[ATTR0]] {
59 // LP64-LP64F-LP64D: entry:
61 double f_fp_scalar_2(double x
) { return x
; }
63 // LP64-LP64F-LP64D-LABEL: define dso_local fp128 @f_fp_scalar_3
64 // LP64-LP64F-LP64D-SAME: (fp128 noundef [[X:%.*]]) #[[ATTR0]] {
65 // LP64-LP64F-LP64D: entry:
67 long double f_fp_scalar_3(long double x
) { return x
; }
69 // LP64-LP64F-LP64D-LABEL: define dso_local half @f_fp_scalar_4
70 // LP64-LP64F-LP64D-SAME: (half noundef [[X:%.*]]) #[[ATTR0]] {
71 // LP64-LP64F-LP64D: entry:
73 _Float16
f_fp_scalar_4(_Float16 x
) { return x
; }
75 // Empty structs or unions are ignored.
79 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_empty_struct
80 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
81 // LP64-LP64F-LP64D: entry:
83 struct empty_s
f_agg_empty_struct(struct empty_s x
) {
89 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_empty_union
90 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
91 // LP64-LP64F-LP64D: entry:
93 union empty_u
f_agg_empty_union(union empty_u x
) {
97 // Aggregates <= 2*xlen may be passed in registers, so will be coerced to
98 // integer arguments. The rules for return are the same.
104 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_tiny
105 // LP64-LP64F-LP64D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {
106 // LP64-LP64F-LP64D: entry:
108 void f_agg_tiny(struct tiny x
) {
113 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_agg_tiny_ret
114 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
115 // LP64-LP64F-LP64D: entry:
117 struct tiny
f_agg_tiny_ret(void) {
118 return (struct tiny
){1, 2, 3, 4};
121 typedef uint16_t v4i16
__attribute__((vector_size(8)));
122 typedef int64_t v1i64
__attribute__((vector_size(8)));
124 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_tiny_v4i16
125 // LP64-LP64F-LP64D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
126 // LP64-LP64F-LP64D: entry:
128 void f_vec_tiny_v4i16(v4i16 x
) {
133 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_vec_tiny_v4i16_ret
134 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
135 // LP64-LP64F-LP64D: entry:
137 v4i16
f_vec_tiny_v4i16_ret(void) {
138 return (v4i16
){1, 2, 3, 4};
141 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_tiny_v1i64
142 // LP64-LP64F-LP64D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
143 // LP64-LP64F-LP64D: entry:
145 void f_vec_tiny_v1i64(v1i64 x
) {
149 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_vec_tiny_v1i64_ret
150 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
151 // LP64-LP64F-LP64D: entry:
153 v1i64
f_vec_tiny_v1i64_ret(void) {
161 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_small
162 // LP64-LP64F-LP64D-SAME: ([2 x i64] [[X_COERCE:%.*]]) #[[ATTR0]] {
163 // LP64-LP64F-LP64D: entry:
165 void f_agg_small(struct small x
) {
170 // LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_agg_small_ret
171 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
172 // LP64-LP64F-LP64D: entry:
174 struct small
f_agg_small_ret(void) {
175 return (struct small
){1, 0};
178 typedef uint16_t v8i16
__attribute__((vector_size(16)));
179 typedef __int128_t v1i128
__attribute__((vector_size(16)));
181 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_small_v8i16
182 // LP64-LP64F-LP64D-SAME: (i128 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
183 // LP64-LP64F-LP64D: entry:
185 void f_vec_small_v8i16(v8i16 x
) {
189 // LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_vec_small_v8i16_ret
190 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
191 // LP64-LP64F-LP64D: entry:
193 v8i16
f_vec_small_v8i16_ret(void) {
194 return (v8i16
){1, 2, 3, 4, 5, 6, 7, 8};
197 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_small_v1i128
198 // LP64-LP64F-LP64D-SAME: (i128 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
199 // LP64-LP64F-LP64D: entry:
201 void f_vec_small_v1i128(v1i128 x
) {
205 // LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_vec_small_v1i128_ret
206 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
207 // LP64-LP64F-LP64D: entry:
209 v1i128
f_vec_small_v1i128_ret(void) {
213 // Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a
214 // single 2*xlen-sized argument, to ensure that alignment can be maintained if
215 // passed on the stack.
217 struct small_aligned
{
221 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_small_aligned
222 // LP64-LP64F-LP64D-SAME: (i128 [[X_COERCE:%.*]]) #[[ATTR0]] {
223 // LP64-LP64F-LP64D: entry:
225 void f_agg_small_aligned(struct small_aligned x
) {
229 // LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_agg_small_aligned_ret
230 // LP64-LP64F-LP64D-SAME: (i128 [[X_COERCE:%.*]]) #[[ATTR0]] {
231 // LP64-LP64F-LP64D: entry:
233 struct small_aligned
f_agg_small_aligned_ret(struct small_aligned x
) {
234 return (struct small_aligned
){10};
237 // Aggregates greater > 2*xlen will be passed and returned indirectly
242 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large
243 // LP64-LP64F-LP64D-SAME: (ptr noundef [[X:%.*]]) #[[ATTR0]] {
244 // LP64-LP64F-LP64D: entry:
246 void f_agg_large(struct large x
) {
247 x
.a
= x
.b
+ x
.c
+ x
.d
;
250 // The address where the struct should be written to will be the first
252 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large_ret
253 // LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] {
254 // LP64-LP64F-LP64D: entry:
256 struct large
f_agg_large_ret(int32_t i
, int8_t j
) {
257 return (struct large
){1, 2, 3, 4};
260 typedef unsigned char v32i8
__attribute__((vector_size(32)));
262 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8
263 // LP64-LP64F-LP64D-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] {
264 // LP64-LP64F-LP64D: entry:
266 void f_vec_large_v32i8(v32i8 x
) {
270 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8_ret
271 // LP64-LP64F-LP64D-SAME: (ptr noalias sret(<32 x i8>) align 32 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
272 // LP64-LP64F-LP64D: entry:
274 v32i8
f_vec_large_v32i8_ret(void) {
275 return (v32i8
){1, 2, 3, 4, 5, 6, 7, 8};
278 // Scalars passed on the stack should have signext/zeroext attributes, just as
279 // if they were passed in registers.
281 // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_1
282 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]], [2 x i64] [[B_COERCE:%.*]], i128 [[C_COERCE:%.*]], ptr noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] {
283 // LP64-LP64F-LP64D: entry:
285 int f_scalar_stack_1(struct tiny a
, struct small b
, struct small_aligned c
,
286 struct large d
, uint8_t e
, int8_t f
, uint8_t g
, int8_t h
) {
290 // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_2
291 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] {
292 // LP64-LP64F-LP64D: entry:
294 int f_scalar_stack_2(int32_t a
, __int128_t b
, int64_t c
, long double d
, v32i8 e
,
295 uint8_t f
, int8_t g
, uint8_t h
) {
299 // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_3
300 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] {
301 // LP64-LP64F-LP64D: entry:
303 int f_scalar_stack_3(int32_t a
, __int128_t b
, double c
, long double d
, v32i8 e
,
304 uint8_t f
, int8_t g
, uint8_t h
) {
308 // Ensure that scalars passed on the stack are still determined correctly in
309 // the presence of large return values that consume a register due to the need
310 // to pass a pointer.
312 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_4
313 // LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {
314 // LP64-LP64F-LP64D: entry:
316 struct large
f_scalar_stack_4(uint32_t a
, __int128_t b
, long double c
, v32i8 d
,
317 uint8_t e
, int8_t f
, uint8_t g
) {
318 return (struct large
){a
, e
, f
, g
};
321 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_5
322 // LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {
323 // LP64-LP64F-LP64D: entry:
325 struct large
f_scalar_stack_5(double a
, __int128_t b
, long double c
, v32i8 d
,
326 uint8_t e
, int8_t f
, uint8_t g
) {
327 return (struct large
){a
, e
, f
, g
};
330 // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_6
331 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], float noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]], half noundef [[I:%.*]]) #[[ATTR0]] {
332 // LP64-LP64F-LP64D: entry:
334 int f_scalar_stack_6(int32_t a
, __int128_t b
, float c
, long double d
, v32i8 e
,
335 uint8_t f
, int8_t g
, uint8_t h
, _Float16 i
) {
339 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_fpr_tracking
340 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], float noundef [[H:%.*]], i8 noundef zeroext [[I:%.*]]) #[[ATTR0]] {
341 // LP64-LP64F-LP64D: entry:
343 void f_fpr_tracking(float a
, float b
, float c
, float d
, float e
, float f
,
344 float g
, float h
, uint8_t i
) {}
346 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
347 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
348 // available the widths are <= XLEN and FLEN, and should be expanded to
349 // separate arguments in IR. They are passed by the same rules for returns,
350 // but will be lowered to simple two-element structs if necessary (as LLVM IR
351 // functions cannot return multiple values).
353 // A struct containing just one floating-point real is passed as though it
354 // were a standalone floating-point real.
356 struct float_s
{ float f
; };
358 // LP64-LABEL: define dso_local void @f_float_s_arg
359 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
362 // LP64F-LP64D-LABEL: define dso_local void @f_float_s_arg
363 // LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
364 // LP64F-LP64D: entry:
366 void f_float_s_arg(struct float_s a
) {}
368 // LP64-LABEL: define dso_local i64 @f_ret_float_s
369 // LP64-SAME: () #[[ATTR0]] {
372 // LP64F-LP64D-LABEL: define dso_local float @f_ret_float_s
373 // LP64F-LP64D-SAME: () #[[ATTR0]] {
374 // LP64F-LP64D: entry:
376 struct float_s
f_ret_float_s(void) {
377 return (struct float_s
){1.0};
380 // A struct containing a float and any number of zero-width bitfields is
381 // passed as though it were a standalone floating-point real.
383 struct zbf_float_s
{ int : 0; float f
; };
384 struct zbf_float_zbf_s
{ int : 0; float f
; int : 0; };
386 // LP64-LABEL: define dso_local void @f_zbf_float_s_arg
387 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
390 // LP64F-LP64D-LABEL: define dso_local void @f_zbf_float_s_arg
391 // LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
392 // LP64F-LP64D: entry:
394 void f_zbf_float_s_arg(struct zbf_float_s a
) {}
396 // LP64-LABEL: define dso_local i64 @f_ret_zbf_float_s
397 // LP64-SAME: () #[[ATTR0]] {
400 // LP64F-LP64D-LABEL: define dso_local float @f_ret_zbf_float_s
401 // LP64F-LP64D-SAME: () #[[ATTR0]] {
402 // LP64F-LP64D: entry:
404 struct zbf_float_s
f_ret_zbf_float_s(void) {
405 return (struct zbf_float_s
){1.0};
408 // LP64-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
409 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
412 // LP64F-LP64D-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
413 // LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
414 // LP64F-LP64D: entry:
416 void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a
) {}
418 // LP64-LABEL: define dso_local i64 @f_ret_zbf_float_zbf_s
419 // LP64-SAME: () #[[ATTR0]] {
422 // LP64F-LP64D-LABEL: define dso_local float @f_ret_zbf_float_zbf_s
423 // LP64F-LP64D-SAME: () #[[ATTR0]] {
424 // LP64F-LP64D: entry:
426 struct zbf_float_zbf_s
f_ret_zbf_float_zbf_s(void) {
427 return (struct zbf_float_zbf_s
){1.0};
430 // Check that structs containing two float values (FLEN <= width) are expanded
431 // provided sufficient FPRs are available.
433 struct float_float_s
{ float f
; float g
; };
435 // LP64-LABEL: define dso_local void @f_float_float_s_arg
436 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
439 // LP64F-LP64D-LABEL: define dso_local void @f_float_float_s_arg
440 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
441 // LP64F-LP64D: entry:
443 void f_float_float_s_arg(struct float_float_s a
) {}
445 // LP64-LABEL: define dso_local i64 @f_ret_float_float_s
446 // LP64-SAME: () #[[ATTR0]] {
449 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_float_float_s
450 // LP64F-LP64D-SAME: () #[[ATTR0]] {
451 // LP64F-LP64D: entry:
453 struct float_float_s
f_ret_float_float_s(void) {
454 return (struct float_float_s
){1.0, 2.0};
457 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_float_s_arg_insufficient_fprs
458 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], i64 [[H_COERCE:%.*]]) #[[ATTR0]] {
459 // LP64-LP64F-LP64D: entry:
461 void f_float_float_s_arg_insufficient_fprs(float a
, float b
, float c
, float d
,
462 float e
, float f
, float g
, struct float_float_s h
) {}
464 // Check that structs containing int+float values are expanded, provided
465 // sufficient FPRs and GPRs are available. The integer components are neither
466 // sign or zero-extended.
468 struct float_int8_s
{ float f
; int8_t i
; };
469 struct float_uint8_s
{ float f
; uint8_t i
; };
470 struct float_int32_s
{ float f
; int32_t i
; };
471 struct float_int64_s
{ float f
; int64_t i
; };
472 struct float_int128bf_s
{ float f
; __int128_t i
: 64; };
473 struct float_int8_zbf_s
{ float f
; int8_t i
; int : 0; };
475 // LP64-LABEL: define dso_local void @f_float_int8_s_arg
476 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
479 // LP64F-LP64D-LABEL: define dso_local void @f_float_int8_s_arg
480 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
481 // LP64F-LP64D: entry:
483 void f_float_int8_s_arg(struct float_int8_s a
) {}
485 // LP64-LABEL: define dso_local i64 @f_ret_float_int8_s
486 // LP64-SAME: () #[[ATTR0]] {
489 // LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_s
490 // LP64F-LP64D-SAME: () #[[ATTR0]] {
491 // LP64F-LP64D: entry:
493 struct float_int8_s
f_ret_float_int8_s(void) {
494 return (struct float_int8_s
){1.0, 2};
497 // LP64-LABEL: define dso_local void @f_float_uint8_s_arg
498 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
501 // LP64F-LP64D-LABEL: define dso_local void @f_float_uint8_s_arg
502 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
503 // LP64F-LP64D: entry:
505 void f_float_uint8_s_arg(struct float_uint8_s a
) {}
507 // LP64-LABEL: define dso_local i64 @f_ret_float_uint8_s
508 // LP64-SAME: () #[[ATTR0]] {
511 // LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_uint8_s
512 // LP64F-LP64D-SAME: () #[[ATTR0]] {
513 // LP64F-LP64D: entry:
515 struct float_uint8_s
f_ret_float_uint8_s(void) {
516 return (struct float_uint8_s
){1.0, 2};
519 // LP64-LABEL: define dso_local void @f_float_int32_s_arg
520 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
523 // LP64F-LP64D-LABEL: define dso_local void @f_float_int32_s_arg
524 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
525 // LP64F-LP64D: entry:
527 void f_float_int32_s_arg(struct float_int32_s a
) {}
529 // LP64-LABEL: define dso_local i64 @f_ret_float_int32_s
530 // LP64-SAME: () #[[ATTR0]] {
533 // LP64F-LP64D-LABEL: define dso_local { float, i32 } @f_ret_float_int32_s
534 // LP64F-LP64D-SAME: () #[[ATTR0]] {
535 // LP64F-LP64D: entry:
537 struct float_int32_s
f_ret_float_int32_s(void) {
538 return (struct float_int32_s
){1.0, 2};
541 // LP64-LABEL: define dso_local void @f_float_int64_s_arg
542 // LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
545 // LP64F-LP64D-LABEL: define dso_local void @f_float_int64_s_arg
546 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
547 // LP64F-LP64D: entry:
549 void f_float_int64_s_arg(struct float_int64_s a
) {}
551 // LP64-LABEL: define dso_local [2 x i64] @f_ret_float_int64_s
552 // LP64-SAME: () #[[ATTR0]] {
555 // LP64F-LP64D-LABEL: define dso_local { float, i64 } @f_ret_float_int64_s
556 // LP64F-LP64D-SAME: () #[[ATTR0]] {
557 // LP64F-LP64D: entry:
559 struct float_int64_s
f_ret_float_int64_s(void) {
560 return (struct float_int64_s
){1.0, 2};
563 // LP64-LABEL: define dso_local void @f_float_int128bf_s_arg
564 // LP64-SAME: (i128 [[A_COERCE:%.*]]) #[[ATTR0]] {
567 // LP64F-LP64D-LABEL: define dso_local void @f_float_int128bf_s_arg
568 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
569 // LP64F-LP64D: entry:
571 void f_float_int128bf_s_arg(struct float_int128bf_s a
) {}
573 // LP64-LABEL: define dso_local i128 @f_ret_float_int128bf_s
574 // LP64-SAME: () #[[ATTR0]] {
577 // LP64F-LP64D-LABEL: define dso_local <{ float, i64 }> @f_ret_float_int128bf_s
578 // LP64F-LP64D-SAME: () #[[ATTR0]] {
579 // LP64F-LP64D: entry:
581 struct float_int128bf_s
f_ret_float_int128bf_s(void) {
582 return (struct float_int128bf_s
){1.0, 2};
585 // The zero-width bitfield means the struct can't be passed according to the
586 // floating point calling convention.
588 // LP64-LABEL: define dso_local void @f_float_int8_zbf_s
589 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
592 // LP64F-LP64D-LABEL: define dso_local void @f_float_int8_zbf_s
593 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
594 // LP64F-LP64D: entry:
596 void f_float_int8_zbf_s(struct float_int8_zbf_s a
) {}
598 // LP64-LABEL: define dso_local i64 @f_ret_float_int8_zbf_s
599 // LP64-SAME: () #[[ATTR0]] {
602 // LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_zbf_s
603 // LP64F-LP64D-SAME: () #[[ATTR0]] {
604 // LP64F-LP64D: entry:
606 struct float_int8_zbf_s
f_ret_float_int8_zbf_s(void) {
607 return (struct float_int8_zbf_s
){1.0, 2};
610 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_int8_s_arg_insufficient_gprs
611 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {
612 // LP64-LP64F-LP64D: entry:
614 void f_float_int8_s_arg_insufficient_gprs(int a
, int b
, int c
, int d
, int e
,
615 int f
, int g
, int h
, struct float_int8_s i
) {}
617 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_struct_float_int8_insufficient_fprs
618 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], float noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {
619 // LP64-LP64F-LP64D: entry:
621 void f_struct_float_int8_insufficient_fprs(float a
, float b
, float c
, float d
,
622 float e
, float f
, float g
, float h
, struct float_int8_s i
) {}
624 // Complex floating-point values or structs containing a single complex
625 // floating-point value should be passed as if it were an fp+fp struct.
627 // LP64-LABEL: define dso_local void @f_floatcomplex
628 // LP64-SAME: (i64 noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
631 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex
632 // LP64F-LP64D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
633 // LP64F-LP64D: entry:
635 void f_floatcomplex(float __complex__ a
) {}
637 // LP64-LABEL: define dso_local i64 @f_ret_floatcomplex
638 // LP64-SAME: () #[[ATTR0]] {
641 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatcomplex
642 // LP64F-LP64D-SAME: () #[[ATTR0]] {
643 // LP64F-LP64D: entry:
645 float __complex__
f_ret_floatcomplex(void) {
649 struct floatcomplex_s
{ float __complex__ c
; };
651 // LP64-LABEL: define dso_local void @f_floatcomplex_s_arg
652 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
655 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg
656 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
657 // LP64F-LP64D: entry:
659 void f_floatcomplex_s_arg(struct floatcomplex_s a
) {}
661 // LP64-LABEL: define dso_local i64 @f_ret_floatcomplex_s
662 // LP64-SAME: () #[[ATTR0]] {
665 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatcomplex_s
666 // LP64F-LP64D-SAME: () #[[ATTR0]] {
667 // LP64F-LP64D: entry:
669 struct floatcomplex_s
f_ret_floatcomplex_s(void) {
670 return (struct floatcomplex_s
){1.0};
673 // Complex floating-point values or structs containing a single complex
674 // floating-point value should be passed in GPRs if no two FPRs is available.
676 // LP64-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs1
677 // LP64-SAME: (i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]], i64 noundef [[C_COERCE:%.*]], i64 noundef [[D_COERCE:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {
680 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs1
681 // LP64F-LP64D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]], float noundef [[D_COERCE0:%.*]], float noundef [[D_COERCE1:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {
682 // LP64F-LP64D: entry:
684 void f_floatcomplex_insufficient_fprs1(float __complex__ a
, float __complex__ b
,
685 float __complex__ c
, float __complex__ d
,
686 float __complex__ e
) {}
689 // LP64-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs1
690 // LP64-SAME: (i64 [[A_COERCE:%.*]], i64 [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], i64 [[D_COERCE:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {
693 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs1
694 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]], float [[TMP3:%.*]], float [[TMP4:%.*]], float [[TMP5:%.*]], float [[TMP6:%.*]], float [[TMP7:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {
695 // LP64F-LP64D: entry:
697 void f_floatcomplex_s_arg_insufficient_fprs1(struct floatcomplex_s a
,
698 struct floatcomplex_s b
,
699 struct floatcomplex_s c
,
700 struct floatcomplex_s d
,
701 struct floatcomplex_s e
) {}
703 // LP64-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs2
704 // LP64-SAME: (float noundef [[A:%.*]], i64 noundef [[B_COERCE:%.*]], i64 noundef [[C_COERCE:%.*]], i64 noundef [[D_COERCE:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {
707 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs2
708 // LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]], float noundef [[D_COERCE0:%.*]], float noundef [[D_COERCE1:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {
709 // LP64F-LP64D: entry:
711 void f_floatcomplex_insufficient_fprs2(float a
,
712 float __complex__ b
, float __complex__ c
,
713 float __complex__ d
, float __complex__ e
) {}
716 // LP64-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs2
717 // LP64-SAME: (float noundef [[A:%.*]], i64 [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], i64 [[D_COERCE:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {
720 // LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs2
721 // LP64F-LP64D-SAME: (float noundef [[A:%.*]], float [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]], float [[TMP3:%.*]], float [[TMP4:%.*]], float [[TMP5:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {
722 // LP64F-LP64D: entry:
724 void f_floatcomplex_s_arg_insufficient_fprs2(float a
,
725 struct floatcomplex_s b
,
726 struct floatcomplex_s c
,
727 struct floatcomplex_s d
,
728 struct floatcomplex_s e
) {}
730 // Test single or two-element structs that need flattening. e.g. those
731 // containing nested structs, floats in small arrays, zero-length structs etc.
733 struct floatarr1_s
{ float a
[1]; };
735 // LP64-LABEL: define dso_local void @f_floatarr1_s_arg
736 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
739 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr1_s_arg
740 // LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
741 // LP64F-LP64D: entry:
743 void f_floatarr1_s_arg(struct floatarr1_s a
) {}
745 // LP64-LABEL: define dso_local i64 @f_ret_floatarr1_s
746 // LP64-SAME: () #[[ATTR0]] {
749 // LP64F-LP64D-LABEL: define dso_local float @f_ret_floatarr1_s
750 // LP64F-LP64D-SAME: () #[[ATTR0]] {
751 // LP64F-LP64D: entry:
753 struct floatarr1_s
f_ret_floatarr1_s(void) {
754 return (struct floatarr1_s
){{1.0}};
757 struct floatarr2_s
{ float a
[2]; };
759 // LP64-LABEL: define dso_local void @f_floatarr2_s_arg
760 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
763 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_s_arg
764 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
765 // LP64F-LP64D: entry:
767 void f_floatarr2_s_arg(struct floatarr2_s a
) {}
769 // LP64-LABEL: define dso_local i64 @f_ret_floatarr2_s
770 // LP64-SAME: () #[[ATTR0]] {
773 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_s
774 // LP64F-LP64D-SAME: () #[[ATTR0]] {
775 // LP64F-LP64D: entry:
777 struct floatarr2_s
f_ret_floatarr2_s(void) {
778 return (struct floatarr2_s
){{1.0, 2.0}};
781 struct floatarr2_tricky1_s
{ struct { float f
[1]; } g
[2]; };
783 // LP64-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
784 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
787 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
788 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
789 // LP64F-LP64D: entry:
791 void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a
) {}
793 // LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky1_s
794 // LP64-SAME: () #[[ATTR0]] {
797 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky1_s
798 // LP64F-LP64D-SAME: () #[[ATTR0]] {
799 // LP64F-LP64D: entry:
801 struct floatarr2_tricky1_s
f_ret_floatarr2_tricky1_s(void) {
802 return (struct floatarr2_tricky1_s
){{{{1.0}}, {{2.0}}}};
805 struct floatarr2_tricky2_s
{ struct {}; struct { float f
[1]; } g
[2]; };
807 // LP64-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
808 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
811 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
812 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
813 // LP64F-LP64D: entry:
815 void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a
) {}
817 // LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky2_s
818 // LP64-SAME: () #[[ATTR0]] {
821 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky2_s
822 // LP64F-LP64D-SAME: () #[[ATTR0]] {
823 // LP64F-LP64D: entry:
825 struct floatarr2_tricky2_s
f_ret_floatarr2_tricky2_s(void) {
826 return (struct floatarr2_tricky2_s
){{}, {{{1.0}}, {{2.0}}}};
829 struct floatarr2_tricky3_s
{ union {}; struct { float f
[1]; } g
[2]; };
831 // LP64-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
832 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
835 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
836 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
837 // LP64F-LP64D: entry:
839 void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a
) {}
841 // LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky3_s
842 // LP64-SAME: () #[[ATTR0]] {
845 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky3_s
846 // LP64F-LP64D-SAME: () #[[ATTR0]] {
847 // LP64F-LP64D: entry:
849 struct floatarr2_tricky3_s
f_ret_floatarr2_tricky3_s(void) {
850 return (struct floatarr2_tricky3_s
){{}, {{{1.0}}, {{2.0}}}};
853 struct floatarr2_tricky4_s
{ union {}; struct { struct {}; float f
[1]; } g
[2]; };
855 // LP64-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
856 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
859 // LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
860 // LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
861 // LP64F-LP64D: entry:
863 void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a
) {}
865 // LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky4_s
866 // LP64-SAME: () #[[ATTR0]] {
869 // LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky4_s
870 // LP64F-LP64D-SAME: () #[[ATTR0]] {
871 // LP64F-LP64D: entry:
873 struct floatarr2_tricky4_s
f_ret_floatarr2_tricky4_s(void) {
874 return (struct floatarr2_tricky4_s
){{}, {{{}, {1.0}}, {{}, {2.0}}}};
877 // Test structs that should be passed according to the normal integer calling
880 struct int_float_int_s
{ int a
; float b
; int c
; };
882 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_float_int_s_arg
883 // LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
884 // LP64-LP64F-LP64D: entry:
886 void f_int_float_int_s_arg(struct int_float_int_s a
) {}
888 // LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_int_float_int_s
889 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
890 // LP64-LP64F-LP64D: entry:
892 struct int_float_int_s
f_ret_int_float_int_s(void) {
893 return (struct int_float_int_s
){1, 2.0, 3};
896 struct char_char_float_s
{ char a
; char b
; float c
; };
898 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_float_s_arg
899 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
900 // LP64-LP64F-LP64D: entry:
902 void f_char_char_float_s_arg(struct char_char_float_s a
) {}
904 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_char_char_float_s
905 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
906 // LP64-LP64F-LP64D: entry:
908 struct char_char_float_s
f_ret_char_char_float_s(void) {
909 return (struct char_char_float_s
){1, 2, 3.0};
912 // Unions are always passed according to the integer calling convention, even
913 // if they can only contain a float.
915 union float_u
{ float a
; };
917 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_u_arg
918 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
919 // LP64-LP64F-LP64D: entry:
921 void f_float_u_arg(union float_u a
) {}
923 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_float_u
924 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
925 // LP64-LP64F-LP64D: entry:
927 union float_u
f_ret_float_u(void) {
928 return (union float_u
){1.0};
931 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_fpr_tracking2
932 // LP64-LP64F-LP64D-SAME: (double noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i8 noundef zeroext [[I:%.*]]) #[[ATTR0]] {
933 // LP64-LP64F-LP64D: entry:
935 void f_fpr_tracking2(double a
, double b
, double c
, double d
, double e
, double f
,
936 double g
, double h
, uint8_t i
) {}
938 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
939 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
940 // available the widths are <= XLEN and FLEN, and should be expanded to
941 // separate arguments in IR. They are passed by the same rules for returns,
942 // but will be lowered to simple two-element structs if necessary (as LLVM IR
943 // functions cannot return multiple values).
945 // A struct containing just one floating-point real is passed as though it
946 // were a standalone floating-point real.
948 struct double_s
{ double f
; };
950 // LP64-LP64F-LABEL: define dso_local void @f_double_s_arg
951 // LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
952 // LP64-LP64F: entry:
954 // LP64D-LABEL: define dso_local void @f_double_s_arg
955 // LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
958 void f_double_s_arg(struct double_s a
) {}
960 // LP64-LP64F-LABEL: define dso_local i64 @f_ret_double_s
961 // LP64-LP64F-SAME: () #[[ATTR0]] {
962 // LP64-LP64F: entry:
964 // LP64D-LABEL: define dso_local double @f_ret_double_s
965 // LP64D-SAME: () #[[ATTR0]] {
968 struct double_s
f_ret_double_s(void) {
969 return (struct double_s
){1.0};
972 // A struct containing a double and any number of zero-width bitfields is
973 // passed as though it were a standalone floating-point real.
975 struct zbf_double_s
{ int : 0; double f
; };
976 struct zbf_double_zbf_s
{ int : 0; double f
; int : 0; };
978 // LP64-LP64F-LABEL: define dso_local void @f_zbf_double_s_arg
979 // LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
980 // LP64-LP64F: entry:
982 // LP64D-LABEL: define dso_local void @f_zbf_double_s_arg
983 // LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
986 void f_zbf_double_s_arg(struct zbf_double_s a
) {}
988 // LP64-LP64F-LABEL: define dso_local i64 @f_ret_zbf_double_s
989 // LP64-LP64F-SAME: () #[[ATTR0]] {
990 // LP64-LP64F: entry:
992 // LP64D-LABEL: define dso_local double @f_ret_zbf_double_s
993 // LP64D-SAME: () #[[ATTR0]] {
996 struct zbf_double_s
f_ret_zbf_double_s(void) {
997 return (struct zbf_double_s
){1.0};
1000 // LP64-LP64F-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
1001 // LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1002 // LP64-LP64F: entry:
1004 // LP64D-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
1005 // LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
1008 void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a
) {}
1010 // LP64-LP64F-LABEL: define dso_local i64 @f_ret_zbf_double_zbf_s
1011 // LP64-LP64F-SAME: () #[[ATTR0]] {
1012 // LP64-LP64F: entry:
1014 // LP64D-LABEL: define dso_local double @f_ret_zbf_double_zbf_s
1015 // LP64D-SAME: () #[[ATTR0]] {
1018 struct zbf_double_zbf_s
f_ret_zbf_double_zbf_s(void) {
1019 return (struct zbf_double_zbf_s
){1.0};
1022 // Check that structs containing two floating point values (FLEN <= width) are
1023 // expanded provided sufficient FPRs are available.
1025 struct double_double_s
{ double f
; double g
; };
1026 struct double_float_s
{ double f
; float g
; };
1028 // LP64-LP64F-LABEL: define dso_local void @f_double_double_s_arg
1029 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1030 // LP64-LP64F: entry:
1032 // LP64D-LABEL: define dso_local void @f_double_double_s_arg
1033 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1036 void f_double_double_s_arg(struct double_double_s a
) {}
1038 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_double_s
1039 // LP64-LP64F-SAME: () #[[ATTR0]] {
1040 // LP64-LP64F: entry:
1042 // LP64D-LABEL: define dso_local { double, double } @f_ret_double_double_s
1043 // LP64D-SAME: () #[[ATTR0]] {
1046 struct double_double_s
f_ret_double_double_s(void) {
1047 return (struct double_double_s
){1.0, 2.0};
1050 // LP64-LP64F-LABEL: define dso_local void @f_double_float_s_arg
1051 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1052 // LP64-LP64F: entry:
1054 // LP64D-LABEL: define dso_local void @f_double_float_s_arg
1055 // LP64D-SAME: (double [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1058 void f_double_float_s_arg(struct double_float_s a
) {}
1060 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_float_s
1061 // LP64-LP64F-SAME: () #[[ATTR0]] {
1062 // LP64-LP64F: entry:
1064 // LP64D-LABEL: define dso_local { double, float } @f_ret_double_float_s
1065 // LP64D-SAME: () #[[ATTR0]] {
1068 struct double_float_s
f_ret_double_float_s(void) {
1069 return (struct double_float_s
){1.0, 2.0};
1072 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_double_s_arg_insufficient_fprs
1073 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], [2 x i64] [[H_COERCE:%.*]]) #[[ATTR0]] {
1074 // LP64-LP64F-LP64D: entry:
1076 void f_double_double_s_arg_insufficient_fprs(float a
, double b
, double c
, double d
,
1077 double e
, double f
, double g
, struct double_double_s h
) {}
1079 // Check that structs containing int+double values are expanded, provided
1080 // sufficient FPRs and GPRs are available. The integer components are neither
1081 // sign or zero-extended.
1083 struct double_int8_s
{ double f
; int8_t i
; };
1084 struct double_uint8_s
{ double f
; uint8_t i
; };
1085 struct double_int32_s
{ double f
; int32_t i
; };
1086 struct double_int64_s
{ double f
; int64_t i
; };
1087 struct double_int128bf_s
{ double f
; __int128_t i
: 64; };
1088 struct double_int8_zbf_s
{ double f
; int8_t i
; int : 0; };
1090 // LP64-LP64F-LABEL: define dso_local void @f_double_int8_s_arg
1091 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1092 // LP64-LP64F: entry:
1094 // LP64D-LABEL: define dso_local void @f_double_int8_s_arg
1095 // LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1098 void f_double_int8_s_arg(struct double_int8_s a
) {}
1100 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int8_s
1101 // LP64-LP64F-SAME: () #[[ATTR0]] {
1102 // LP64-LP64F: entry:
1104 // LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_s
1105 // LP64D-SAME: () #[[ATTR0]] {
1108 struct double_int8_s
f_ret_double_int8_s(void) {
1109 return (struct double_int8_s
){1.0, 2};
1112 // LP64-LP64F-LABEL: define dso_local void @f_double_uint8_s_arg
1113 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1114 // LP64-LP64F: entry:
1116 // LP64D-LABEL: define dso_local void @f_double_uint8_s_arg
1117 // LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1120 void f_double_uint8_s_arg(struct double_uint8_s a
) {}
1122 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_uint8_s
1123 // LP64-LP64F-SAME: () #[[ATTR0]] {
1124 // LP64-LP64F: entry:
1126 // LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_uint8_s
1127 // LP64D-SAME: () #[[ATTR0]] {
1130 struct double_uint8_s
f_ret_double_uint8_s(void) {
1131 return (struct double_uint8_s
){1.0, 2};
1134 // LP64-LP64F-LABEL: define dso_local void @f_double_int32_s_arg
1135 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1136 // LP64-LP64F: entry:
1138 // LP64D-LABEL: define dso_local void @f_double_int32_s_arg
1139 // LP64D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1142 void f_double_int32_s_arg(struct double_int32_s a
) {}
1144 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int32_s
1145 // LP64-LP64F-SAME: () #[[ATTR0]] {
1146 // LP64-LP64F: entry:
1148 // LP64D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s
1149 // LP64D-SAME: () #[[ATTR0]] {
1152 struct double_int32_s
f_ret_double_int32_s(void) {
1153 return (struct double_int32_s
){1.0, 2};
1156 // LP64-LP64F-LABEL: define dso_local void @f_double_int64_s_arg
1157 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1158 // LP64-LP64F: entry:
1160 // LP64D-LABEL: define dso_local void @f_double_int64_s_arg
1161 // LP64D-SAME: (double [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
1164 void f_double_int64_s_arg(struct double_int64_s a
) {}
1166 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int64_s
1167 // LP64-LP64F-SAME: () #[[ATTR0]] {
1168 // LP64-LP64F: entry:
1170 // LP64D-LABEL: define dso_local { double, i64 } @f_ret_double_int64_s
1171 // LP64D-SAME: () #[[ATTR0]] {
1174 struct double_int64_s
f_ret_double_int64_s(void) {
1175 return (struct double_int64_s
){1.0, 2};
1178 // LP64-LP64F-LABEL: define dso_local void @f_double_int128bf_s_arg
1179 // LP64-LP64F-SAME: (i128 [[A_COERCE:%.*]]) #[[ATTR0]] {
1180 // LP64-LP64F: entry:
1182 // LP64D-LABEL: define dso_local void @f_double_int128bf_s_arg
1183 // LP64D-SAME: (double [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
1186 void f_double_int128bf_s_arg(struct double_int128bf_s a
) {}
1188 // LP64-LP64F-LABEL: define dso_local i128 @f_ret_double_int128bf_s
1189 // LP64-LP64F-SAME: () #[[ATTR0]] {
1190 // LP64-LP64F: entry:
1192 // LP64D-LABEL: define dso_local { double, i64 } @f_ret_double_int128bf_s
1193 // LP64D-SAME: () #[[ATTR0]] {
1196 struct double_int128bf_s
f_ret_double_int128bf_s(void) {
1197 return (struct double_int128bf_s
){1.0, 2};
1200 // The zero-width bitfield means the struct can't be passed according to the
1201 // floating point calling convention.
1203 // LP64-LP64F-LABEL: define dso_local void @f_double_int8_zbf_s
1204 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1205 // LP64-LP64F: entry:
1207 // LP64D-LABEL: define dso_local void @f_double_int8_zbf_s
1208 // LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1211 void f_double_int8_zbf_s(struct double_int8_zbf_s a
) {}
1213 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int8_zbf_s
1214 // LP64-LP64F-SAME: () #[[ATTR0]] {
1215 // LP64-LP64F: entry:
1217 // LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_zbf_s
1218 // LP64D-SAME: () #[[ATTR0]] {
1221 struct double_int8_zbf_s
f_ret_double_int8_zbf_s(void) {
1222 return (struct double_int8_zbf_s
){1.0, 2};
1225 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_int8_s_arg_insufficient_gprs
1226 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], [2 x i64] [[I_COERCE:%.*]]) #[[ATTR0]] {
1227 // LP64-LP64F-LP64D: entry:
1229 void f_double_int8_s_arg_insufficient_gprs(int a
, int b
, int c
, int d
, int e
,
1230 int f
, int g
, int h
, struct double_int8_s i
) {}
1232 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_struct_double_int8_insufficient_fprs
1233 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], [2 x i64] [[I_COERCE:%.*]]) #[[ATTR0]] {
1234 // LP64-LP64F-LP64D: entry:
1236 void f_struct_double_int8_insufficient_fprs(float a
, double b
, double c
, double d
,
1237 double e
, double f
, double g
, double h
, struct double_int8_s i
) {}
1239 // Complex floating-point values or structs containing a single complex
1240 // floating-point value should be passed as if it were an fp+fp struct.
1242 // LP64-LP64F-LABEL: define dso_local void @f_doublecomplex
1243 // LP64-LP64F-SAME: ([2 x i64] noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
1244 // LP64-LP64F: entry:
1246 // LP64D-LABEL: define dso_local void @f_doublecomplex
1247 // LP64D-SAME: (double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1250 void f_doublecomplex(double __complex__ a
) {}
1252 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublecomplex
1253 // LP64-LP64F-SAME: () #[[ATTR0]] {
1254 // LP64-LP64F: entry:
1256 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublecomplex
1257 // LP64D-SAME: () #[[ATTR0]] {
1260 double __complex__
f_ret_doublecomplex(void) {
1264 struct doublecomplex_s
{ double __complex__ c
; };
1266 // LP64-LP64F-LABEL: define dso_local void @f_doublecomplex_s_arg
1267 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1268 // LP64-LP64F: entry:
1270 // LP64D-LABEL: define dso_local void @f_doublecomplex_s_arg
1271 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1274 void f_doublecomplex_s_arg(struct doublecomplex_s a
) {}
1276 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublecomplex_s
1277 // LP64-LP64F-SAME: () #[[ATTR0]] {
1278 // LP64-LP64F: entry:
1280 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_s
1281 // LP64D-SAME: () #[[ATTR0]] {
1284 struct doublecomplex_s
f_ret_doublecomplex_s(void) {
1285 return (struct doublecomplex_s
){1.0};
1288 // Test single or two-element structs that need flattening. e.g. those
1289 // containing nested structs, doubles in small arrays, zero-length structs etc.
1291 struct doublearr1_s
{ double a
[1]; };
1293 // LP64-LP64F-LABEL: define dso_local void @f_doublearr1_s_arg
1294 // LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1295 // LP64-LP64F: entry:
1297 // LP64D-LABEL: define dso_local void @f_doublearr1_s_arg
1298 // LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
1301 void f_doublearr1_s_arg(struct doublearr1_s a
) {}
1303 // LP64-LP64F-LABEL: define dso_local i64 @f_ret_doublearr1_s
1304 // LP64-LP64F-SAME: () #[[ATTR0]] {
1305 // LP64-LP64F: entry:
1307 // LP64D-LABEL: define dso_local double @f_ret_doublearr1_s
1308 // LP64D-SAME: () #[[ATTR0]] {
1311 struct doublearr1_s
f_ret_doublearr1_s(void) {
1312 return (struct doublearr1_s
){{1.0}};
1315 struct doublearr2_s
{ double a
[2]; };
1317 // LP64-LP64F-LABEL: define dso_local void @f_doublearr2_s_arg
1318 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1319 // LP64-LP64F: entry:
1321 // LP64D-LABEL: define dso_local void @f_doublearr2_s_arg
1322 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1325 void f_doublearr2_s_arg(struct doublearr2_s a
) {}
1327 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_s
1328 // LP64-LP64F-SAME: () #[[ATTR0]] {
1329 // LP64-LP64F: entry:
1331 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_s
1332 // LP64D-SAME: () #[[ATTR0]] {
1335 struct doublearr2_s
f_ret_doublearr2_s(void) {
1336 return (struct doublearr2_s
){{1.0, 2.0}};
1339 struct doublearr2_tricky1_s
{ struct { double f
[1]; } g
[2]; };
1341 // LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
1342 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1343 // LP64-LP64F: entry:
1345 // LP64D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
1346 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1349 void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a
) {}
1351 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky1_s
1352 // LP64-LP64F-SAME: () #[[ATTR0]] {
1353 // LP64-LP64F: entry:
1355 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky1_s
1356 // LP64D-SAME: () #[[ATTR0]] {
1359 struct doublearr2_tricky1_s
f_ret_doublearr2_tricky1_s(void) {
1360 return (struct doublearr2_tricky1_s
){{{{1.0}}, {{2.0}}}};
1363 struct doublearr2_tricky2_s
{ struct {}; struct { double f
[1]; } g
[2]; };
1365 // LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
1366 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1367 // LP64-LP64F: entry:
1369 // LP64D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
1370 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1373 void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a
) {}
1375 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky2_s
1376 // LP64-LP64F-SAME: () #[[ATTR0]] {
1377 // LP64-LP64F: entry:
1379 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky2_s
1380 // LP64D-SAME: () #[[ATTR0]] {
1383 struct doublearr2_tricky2_s
f_ret_doublearr2_tricky2_s(void) {
1384 return (struct doublearr2_tricky2_s
){{}, {{{1.0}}, {{2.0}}}};
1387 struct doublearr2_tricky3_s
{ union {}; struct { double f
[1]; } g
[2]; };
1389 // LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
1390 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1391 // LP64-LP64F: entry:
1393 // LP64D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
1394 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1397 void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a
) {}
1399 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky3_s
1400 // LP64-LP64F-SAME: () #[[ATTR0]] {
1401 // LP64-LP64F: entry:
1403 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky3_s
1404 // LP64D-SAME: () #[[ATTR0]] {
1407 struct doublearr2_tricky3_s
f_ret_doublearr2_tricky3_s(void) {
1408 return (struct doublearr2_tricky3_s
){{}, {{{1.0}}, {{2.0}}}};
1411 struct doublearr2_tricky4_s
{ union {}; struct { struct {}; double f
[1]; } g
[2]; };
1413 // LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
1414 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1415 // LP64-LP64F: entry:
1417 // LP64D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
1418 // LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
1421 void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a
) {}
1423 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky4_s
1424 // LP64-LP64F-SAME: () #[[ATTR0]] {
1425 // LP64-LP64F: entry:
1427 // LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky4_s
1428 // LP64D-SAME: () #[[ATTR0]] {
1431 struct doublearr2_tricky4_s
f_ret_doublearr2_tricky4_s(void) {
1432 return (struct doublearr2_tricky4_s
){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1435 // Test structs that should be passed according to the normal integer calling
1438 struct int_double_int_s
{ int a
; double b
; int c
; };
1440 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_double_int_s_arg
1441 // LP64-LP64F-LP64D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1442 // LP64-LP64F-LP64D: entry:
1444 void f_int_double_int_s_arg(struct int_double_int_s a
) {}
1446 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_ret_int_double_int_s
1447 // LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1448 // LP64-LP64F-LP64D: entry:
1450 struct int_double_int_s
f_ret_int_double_int_s(void) {
1451 return (struct int_double_int_s
){1, 2.0, 3};
1454 struct char_char_double_s
{ char a
; char b
; double c
; };
1456 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_double_s_arg
1457 // LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1458 // LP64-LP64F-LP64D: entry:
1460 void f_char_char_double_s_arg(struct char_char_double_s a
) {}
1462 // LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_char_char_double_s
1463 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
1464 // LP64-LP64F-LP64D: entry:
1466 struct char_char_double_s
f_ret_char_char_double_s(void) {
1467 return (struct char_char_double_s
){1, 2, 3.0};
1470 // Unions are always passed according to the integer calling convention, even
1471 // if they can only contain a double.
1473 union double_u
{ double a
; };
1475 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_u_arg
1476 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1477 // LP64-LP64F-LP64D: entry:
1479 void f_double_u_arg(union double_u a
) {}
1481 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_double_u
1482 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
1483 // LP64-LP64F-LP64D: entry:
1485 union double_u
f_ret_double_u(void) {
1486 return (union double_u
){1.0};
1489 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
1490 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
1491 // available the widths are <= XLEN and FLEN, and should be expanded to
1492 // separate arguments in IR. They are passed by the same rules for returns,
1493 // but will be lowered to simple two-element structs if necessary (as LLVM IR
1494 // functions cannot return multiple values).
1496 struct float16_s
{ _Float16 f
; };
1498 // A struct containing just one floating-point real is passed as though it
1499 // were a standalone floating-point real.
1501 // LP64-LABEL: define dso_local void @f_float16_s_arg
1502 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1505 // LP64F-LP64D-LABEL: define dso_local void @f_float16_s_arg
1506 // LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1507 // LP64F-LP64D: entry:
1509 void f_float16_s_arg(struct float16_s a
) {}
1511 // LP64-LABEL: define dso_local i64 @f_ret_float16_s
1512 // LP64-SAME: () #[[ATTR0]] {
1515 // LP64F-LP64D-LABEL: define dso_local half @f_ret_float16_s
1516 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1517 // LP64F-LP64D: entry:
1519 struct float16_s
f_ret_float16_s(void) {
1520 return (struct float16_s
){1.0};
1523 // A struct containing a double and any number of zero-width bitfields is
1524 // passed as though it were a standalone floating-point real.
1526 struct zbf_float16_s
{ int : 0; _Float16 f
; };
1527 struct zbf_float16_zbf_s
{ int : 0; _Float16 f
; int : 0; };
1529 // LP64-LABEL: define dso_local void @f_zbf_float16_s_arg
1530 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1533 // LP64F-LP64D-LABEL: define dso_local void @f_zbf_float16_s_arg
1534 // LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1535 // LP64F-LP64D: entry:
1537 void f_zbf_float16_s_arg(struct zbf_float16_s a
) {}
1539 // LP64-LABEL: define dso_local i64 @f_ret_zbf_float16_s
1540 // LP64-SAME: () #[[ATTR0]] {
1543 // LP64F-LP64D-LABEL: define dso_local half @f_ret_zbf_float16_s
1544 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1545 // LP64F-LP64D: entry:
1547 struct zbf_float16_s
f_ret_zbf_float16_s(void) {
1548 return (struct zbf_float16_s
){1.0};
1551 // LP64-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1552 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1555 // LP64F-LP64D-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1556 // LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1557 // LP64F-LP64D: entry:
1559 void f_zbf_float16_zbf_s_arg(struct zbf_float16_zbf_s a
) {}
1561 // LP64-LABEL: define dso_local i64 @f_ret_zbf_float16_zbf_s
1562 // LP64-SAME: () #[[ATTR0]] {
1565 // LP64F-LP64D-LABEL: define dso_local half @f_ret_zbf_float16_zbf_s
1566 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1567 // LP64F-LP64D: entry:
1569 struct zbf_float16_zbf_s
f_ret_zbf_float16_zbf_s(void) {
1570 return (struct zbf_float16_zbf_s
){1.0};
1573 // Check that structs containing two floating point values (FLEN <= width) are
1574 // expanded provided sufficient FPRs are available.
1576 struct double_float16_s
{ double f
; _Float16 g
; };
1578 // LP64-LP64F-LABEL: define dso_local void @f_double_float16_s_arg
1579 // LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1580 // LP64-LP64F: entry:
1582 // LP64D-LABEL: define dso_local void @f_double_float16_s_arg
1583 // LP64D-SAME: (double [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1586 void f_double_float16_s_arg(struct double_float16_s a
) {}
1588 // LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_float16_s
1589 // LP64-LP64F-SAME: () #[[ATTR0]] {
1590 // LP64-LP64F: entry:
1592 // LP64D-LABEL: define dso_local { double, half } @f_ret_double_float16_s
1593 // LP64D-SAME: () #[[ATTR0]] {
1596 struct double_float16_s
f_ret_double_float16_s(void) {
1597 return (struct double_float16_s
){1.0, 2.0};
1600 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_float16_s_arg_insufficient_fprs
1601 // LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], [2 x i64] [[H_COERCE:%.*]]) #[[ATTR0]] {
1602 // LP64-LP64F-LP64D: entry:
1604 void f_double_float16_s_arg_insufficient_fprs(float a
, double b
, double c
, double d
,
1605 double e
, double f
, double g
, struct double_float16_s h
) {}
1607 // Check that structs containing int+_Float16 values are expanded, provided
1608 // sufficient FPRs and GPRs are available. The integer components are neither
1609 // sign or zero-extended.
1611 struct float16_int8_s
{ _Float16 f
; int8_t i
; };
1612 struct float16_uint8_s
{ _Float16 f
; uint8_t i
; };
1613 struct float16_int32_s
{ _Float16 f
; int32_t i
; };
1614 struct float16_int64_s
{ _Float16 f
; int64_t i
; };
1615 struct float16_int64bf_s
{ _Float16 f
; int64_t i
: 32; };
1616 struct float16_int8_zbf_s
{ _Float16 f
; int8_t i
; int : 0; };
1618 // LP64-LABEL: define dso_local void @f_float16_int8_s_arg
1619 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1622 // LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_s_arg
1623 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1624 // LP64F-LP64D: entry:
1626 void f_float16_int8_s_arg(struct float16_int8_s a
) {}
1628 // LP64-LABEL: define dso_local i64 @f_ret_float16_int8_s
1629 // LP64-SAME: () #[[ATTR0]] {
1632 // LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_s
1633 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1634 // LP64F-LP64D: entry:
1636 struct float16_int8_s
f_ret_float16_int8_s(void) {
1637 return (struct float16_int8_s
){1.0, 2};
1640 // LP64-LABEL: define dso_local void @f_float16_uint8_s_arg
1641 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1644 // LP64F-LP64D-LABEL: define dso_local void @f_float16_uint8_s_arg
1645 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1646 // LP64F-LP64D: entry:
1648 void f_float16_uint8_s_arg(struct float16_uint8_s a
) {}
1650 // LP64-LABEL: define dso_local i64 @f_ret_float16_uint8_s
1651 // LP64-SAME: () #[[ATTR0]] {
1654 // LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_uint8_s
1655 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1656 // LP64F-LP64D: entry:
1658 struct float16_uint8_s
f_ret_float16_uint8_s(void) {
1659 return (struct float16_uint8_s
){1.0, 2};
1662 // LP64-LABEL: define dso_local void @f_float16_int32_s_arg
1663 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1666 // LP64F-LP64D-LABEL: define dso_local void @f_float16_int32_s_arg
1667 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1668 // LP64F-LP64D: entry:
1670 void f_float16_int32_s_arg(struct float16_int32_s a
) {}
1672 // LP64-LABEL: define dso_local i64 @f_ret_float16_int32_s
1673 // LP64-SAME: () #[[ATTR0]] {
1676 // LP64F-LP64D-LABEL: define dso_local { half, i32 } @f_ret_float16_int32_s
1677 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1678 // LP64F-LP64D: entry:
1680 struct float16_int32_s
f_ret_float16_int32_s(void) {
1681 return (struct float16_int32_s
){1.0, 2};
1684 // LP64-LABEL: define dso_local void @f_float16_int64_s_arg
1685 // LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1688 // LP64F-LP64D-LABEL: define dso_local void @f_float16_int64_s_arg
1689 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
1690 // LP64F-LP64D: entry:
1692 void f_float16_int64_s_arg(struct float16_int64_s a
) {}
1694 // LP64-LABEL: define dso_local [2 x i64] @f_ret_float16_int64_s
1695 // LP64-SAME: () #[[ATTR0]] {
1698 // LP64F-LP64D-LABEL: define dso_local { half, i64 } @f_ret_float16_int64_s
1699 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1700 // LP64F-LP64D: entry:
1702 struct float16_int64_s
f_ret_float16_int64_s(void) {
1703 return (struct float16_int64_s
){1.0, 2};
1706 // LP64-LABEL: define dso_local void @f_float16_int64bf_s_arg
1707 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1710 // LP64F-LP64D-LABEL: define dso_local void @f_float16_int64bf_s_arg
1711 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
1712 // LP64F-LP64D: entry:
1714 void f_float16_int64bf_s_arg(struct float16_int64bf_s a
) {}
1716 // LP64-LABEL: define dso_local i64 @f_ret_float16_int64bf_s
1717 // LP64-SAME: () #[[ATTR0]] {
1720 // LP64F-LP64D-LABEL: define dso_local <{ half, i64 }> @f_ret_float16_int64bf_s
1721 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1722 // LP64F-LP64D: entry:
1724 struct float16_int64bf_s
f_ret_float16_int64bf_s(void) {
1725 return (struct float16_int64bf_s
){1.0, 2};
1728 // The zero-width bitfield means the struct can't be passed according to the
1729 // floating point calling convention.
1731 // LP64-LABEL: define dso_local void @f_float16_int8_zbf_s
1732 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1735 // LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_zbf_s
1736 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1737 // LP64F-LP64D: entry:
1739 void f_float16_int8_zbf_s(struct float16_int8_zbf_s a
) {}
1741 // LP64-LABEL: define dso_local i64 @f_ret_float16_int8_zbf_s
1742 // LP64-SAME: () #[[ATTR0]] {
1745 // LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_zbf_s
1746 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1747 // LP64F-LP64D: entry:
1749 struct float16_int8_zbf_s
f_ret_float16_int8_zbf_s(void) {
1750 return (struct float16_int8_zbf_s
){1.0, 2};
1753 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_s_arg_insufficient_gprs
1754 // LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {
1755 // LP64-LP64F-LP64D: entry:
1757 void f_float16_int8_s_arg_insufficient_gprs(int a
, int b
, int c
, int d
, int e
,
1758 int f
, int g
, int h
, struct float16_int8_s i
) {}
1760 // LP64-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs
1761 // LP64-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {
1764 // LP64F-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs
1765 // LP64F-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1768 // LP64D-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs
1769 // LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {
1772 void f_struct_float16_int8_insufficient_fprs(float a
, double b
, double c
, double d
,
1773 double e
, double f
, double g
, double h
, struct float16_int8_s i
) {}
1775 // Complex floating-point values or structs containing a single complex
1776 // floating-point value should be passed as if it were an fp+fp struct.
1778 // LP64-LABEL: define dso_local void @f_float16complex
1779 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1782 // LP64F-LP64D-LABEL: define dso_local void @f_float16complex
1783 // LP64F-LP64D-SAME: (half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1784 // LP64F-LP64D: entry:
1786 void f_float16complex(_Float16 __complex__ a
) {}
1788 // LP64-LABEL: define dso_local i64 @f_ret_float16complex
1789 // LP64-SAME: () #[[ATTR0]] {
1792 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16complex
1793 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1794 // LP64F-LP64D: entry:
1796 _Float16 __complex__
f_ret_float16complex(void) {
1800 struct float16complex_s
{ _Float16 __complex__ c
; };
1802 // LP64-LABEL: define dso_local void @f_float16complex_s_arg
1803 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1806 // LP64F-LP64D-LABEL: define dso_local void @f_float16complex_s_arg
1807 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1808 // LP64F-LP64D: entry:
1810 void f_float16complex_s_arg(struct float16complex_s a
) {}
1812 // LP64-LABEL: define dso_local i64 @f_ret_float16complex_s
1813 // LP64-SAME: () #[[ATTR0]] {
1816 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16complex_s
1817 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1818 // LP64F-LP64D: entry:
1820 struct float16complex_s
f_ret_float16complex_s(void) {
1821 return (struct float16complex_s
){1.0};
1824 // Test single or two-element structs that need flattening. e.g. those
1825 // containing nested structs, _Float16 in small arrays, zero-length structs etc.
1827 struct float16arr1_s
{ _Float16 a
[1]; };
1829 // LP64-LABEL: define dso_local void @f_float16arr1_s_arg
1830 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1833 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr1_s_arg
1834 // LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1835 // LP64F-LP64D: entry:
1837 void f_float16arr1_s_arg(struct float16arr1_s a
) {}
1839 // LP64-LABEL: define dso_local i64 @f_ret_float16arr1_s
1840 // LP64-SAME: () #[[ATTR0]] {
1843 // LP64F-LP64D-LABEL: define dso_local half @f_ret_float16arr1_s
1844 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1845 // LP64F-LP64D: entry:
1847 struct float16arr1_s
f_ret_float16arr1_s(void) {
1848 return (struct float16arr1_s
){{1.0}};
1851 struct float16arr2_s
{ _Float16 a
[2]; };
1853 // LP64-LABEL: define dso_local void @f_float16arr2_s_arg
1854 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1857 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_s_arg
1858 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1859 // LP64F-LP64D: entry:
1861 void f_float16arr2_s_arg(struct float16arr2_s a
) {}
1863 // LP64-LABEL: define dso_local i64 @f_ret_float16arr2_s
1864 // LP64-SAME: () #[[ATTR0]] {
1867 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_s
1868 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1869 // LP64F-LP64D: entry:
1871 struct float16arr2_s
f_ret_float16arr2_s(void) {
1872 return (struct float16arr2_s
){{1.0, 2.0}};
1875 struct float16arr2_tricky1_s
{ struct { _Float16 f
[1]; } g
[2]; };
1877 // LP64-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1878 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1881 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1882 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1883 // LP64F-LP64D: entry:
1885 void f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a
) {}
1887 // LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky1_s
1888 // LP64-SAME: () #[[ATTR0]] {
1891 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky1_s
1892 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1893 // LP64F-LP64D: entry:
1895 struct float16arr2_tricky1_s
f_ret_float16arr2_tricky1_s(void) {
1896 return (struct float16arr2_tricky1_s
){{{{1.0}}, {{2.0}}}};
1899 struct float16arr2_tricky2_s
{ struct {}; struct { _Float16 f
[1]; } g
[2]; };
1901 // LP64-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1902 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1905 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1906 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1907 // LP64F-LP64D: entry:
1909 void f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a
) {}
1911 // LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky2_s
1912 // LP64-SAME: () #[[ATTR0]] {
1915 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky2_s
1916 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1917 // LP64F-LP64D: entry:
1919 struct float16arr2_tricky2_s
f_ret_float16arr2_tricky2_s(void) {
1920 return (struct float16arr2_tricky2_s
){{}, {{{1.0}}, {{2.0}}}};
1923 struct float16arr2_tricky3_s
{ union {}; struct { _Float16 f
[1]; } g
[2]; };
1925 // LP64-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1926 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1929 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1930 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1931 // LP64F-LP64D: entry:
1933 void f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a
) {}
1935 // LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky3_s
1936 // LP64-SAME: () #[[ATTR0]] {
1939 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky3_s
1940 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1941 // LP64F-LP64D: entry:
1943 struct float16arr2_tricky3_s
f_ret_float16arr2_tricky3_s(void) {
1944 return (struct float16arr2_tricky3_s
){{}, {{{1.0}}, {{2.0}}}};
1947 struct float16arr2_tricky4_s
{ union {}; struct { struct {}; _Float16 f
[1]; } g
[2]; };
1949 // LP64-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1950 // LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1953 // LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1954 // LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1955 // LP64F-LP64D: entry:
1957 void f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a
) {}
1959 // LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky4_s
1960 // LP64-SAME: () #[[ATTR0]] {
1963 // LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky4_s
1964 // LP64F-LP64D-SAME: () #[[ATTR0]] {
1965 // LP64F-LP64D: entry:
1967 struct float16arr2_tricky4_s
f_ret_float16arr2_tricky4_s(void) {
1968 return (struct float16arr2_tricky4_s
){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1971 // Test structs that should be passed according to the normal integer calling
1974 struct int_float16_int_s
{ int a
; _Float16 b
; int c
; };
1976 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_float16_int_s_arg
1977 // LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1978 // LP64-LP64F-LP64D: entry:
1980 void f_int_float16_int_s_arg(struct int_float16_int_s a
) {}
1982 // LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_int_float16_int_s
1983 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
1984 // LP64-LP64F-LP64D: entry:
1986 struct int_float16_int_s
f_ret_int_float16_int_s(void) {
1987 return (struct int_float16_int_s
){1, 2.0, 3};
1990 struct int64_float16_s
{ int64_t a
; _Float16 b
; };
1992 // LP64-LABEL: define dso_local void @f_int64_float16_s_arg
1993 // LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
1996 // LP64F-LP64D-LABEL: define dso_local void @f_int64_float16_s_arg
1997 // LP64F-LP64D-SAME: (i64 [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1998 // LP64F-LP64D: entry:
2000 void f_int64_float16_s_arg(struct int64_float16_s a
) {}
2002 // LP64-LABEL: define dso_local [2 x i64] @f_ret_int64_float16_s
2003 // LP64-SAME: () #[[ATTR0]] {
2006 // LP64F-LP64D-LABEL: define dso_local { i64, half } @f_ret_int64_float16_s
2007 // LP64F-LP64D-SAME: () #[[ATTR0]] {
2008 // LP64F-LP64D: entry:
2010 struct int64_float16_s
f_ret_int64_float16_s(void) {
2011 return (struct int64_float16_s
){1, 2.0};
2014 struct char_char_float16_s
{ char a
; char b
; _Float16 c
; };
2016 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_float16_s_arg
2017 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
2018 // LP64-LP64F-LP64D: entry:
2020 void f_char_char_float16_s_arg(struct char_char_float16_s a
) {}
2022 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_char_char_float16_s
2023 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
2024 // LP64-LP64F-LP64D: entry:
2026 struct char_char_float16_s
f_ret_char_char_float16_s(void) {
2027 return (struct char_char_float16_s
){1, 2, 3.0};
2030 // Unions are always passed according to the integer calling convention, even
2031 // if they can only contain a double.
2033 union float16_u
{ _Float16 a
; };
2035 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_float16_u_arg
2036 // LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
2037 // LP64-LP64F-LP64D: entry:
2039 void f_float16_u_arg(union float16_u a
) {}
2041 // LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_float16_u
2042 // LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {
2043 // LP64-LP64F-LP64D: entry:
2045 union float16_u
f_ret_float16_u(void) {
2046 return (union float16_u
){1.0};