Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / RISCV / riscv64-abi.c
blob8c857f86ddfff94ff898f47c5bfad59d02be02e3
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
9 #include <stddef.h>
10 #include <stdint.h>
12 // LP64-LP64F-LP64D-LABEL: define dso_local void @f_void
13 // LP64-LP64F-LP64D-SAME: () #[[ATTR0:[0-9]+]] {
14 // LP64-LP64F-LP64D: entry:
16 void f_void(void) {}
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.
77 struct empty_s {};
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) {
84 return x;
87 union empty_u {};
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) {
94 return 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.
100 struct tiny {
101 uint16_t a, b, c, d;
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) {
109 x.a += x.b;
110 x.c += x.d;
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) {
129 x[0] = x[1];
130 x[2] = x[3];
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) {
146 x[0] = 114;
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) {
154 return (v1i64){1};
157 struct small {
158 int64_t a, *b;
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) {
166 x.a += *x.b;
167 x.b = &x.a;
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) {
186 x[0] = x[7];
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) {
202 x[0] = 114;
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) {
210 return (v1i128){1};
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 {
218 __int128_t a;
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) {
226 x.a += x.a;
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
238 struct large {
239 int64_t a, b, c, d;
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
251 // argument
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) {
267 x[0] = x[7];
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) {
287 return g + 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) {
296 return g + 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) {
305 return g + 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) {
336 return g + h;
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]] {
360 // LP64: entry:
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]] {
370 // LP64: entry:
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]] {
388 // LP64: entry:
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]] {
398 // LP64: entry:
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]] {
410 // LP64: entry:
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]] {
420 // LP64: entry:
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]] {
437 // LP64: entry:
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]] {
447 // LP64: entry:
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]] {
477 // LP64: entry:
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]] {
487 // LP64: entry:
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]] {
499 // LP64: entry:
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]] {
509 // LP64: entry:
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]] {
521 // LP64: entry:
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]] {
531 // LP64: entry:
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]] {
543 // LP64: entry:
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]] {
553 // LP64: entry:
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]] {
565 // LP64: entry:
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]] {
575 // LP64: entry:
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]] {
590 // LP64: entry:
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]] {
600 // LP64: entry:
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]] {
629 // LP64: entry:
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]] {
639 // LP64: entry:
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) {
646 return 1.0;
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]] {
653 // LP64: entry:
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]] {
663 // LP64: entry:
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]] {
678 // LP64: entry:
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]] {
691 // LP64: entry:
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]] {
705 // LP64: entry:
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]] {
718 // LP64: entry:
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]] {
737 // LP64: entry:
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]] {
747 // LP64: entry:
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]] {
761 // LP64: entry:
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]] {
771 // LP64: entry:
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]] {
785 // LP64: entry:
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]] {
795 // LP64: entry:
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]] {
809 // LP64: entry:
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]] {
819 // LP64: entry:
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]] {
833 // LP64: entry:
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]] {
843 // LP64: entry:
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]] {
857 // LP64: entry:
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]] {
867 // LP64: entry:
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
878 // convention.
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]] {
956 // LP64D: entry:
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]] {
966 // LP64D: entry:
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]] {
984 // LP64D: entry:
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]] {
994 // LP64D: entry:
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]] {
1006 // LP64D: entry:
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]] {
1016 // LP64D: entry:
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]] {
1034 // LP64D: entry:
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]] {
1044 // LP64D: entry:
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]] {
1056 // LP64D: entry:
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]] {
1066 // LP64D: entry:
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]] {
1096 // LP64D: entry:
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]] {
1106 // LP64D: entry:
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]] {
1118 // LP64D: entry:
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]] {
1128 // LP64D: entry:
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]] {
1140 // LP64D: entry:
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]] {
1150 // LP64D: entry:
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]] {
1162 // LP64D: entry:
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]] {
1172 // LP64D: entry:
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]] {
1184 // LP64D: entry:
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]] {
1194 // LP64D: entry:
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]] {
1209 // LP64D: entry:
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]] {
1219 // LP64D: entry:
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]] {
1248 // LP64D: entry:
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]] {
1258 // LP64D: entry:
1260 double __complex__ f_ret_doublecomplex(void) {
1261 return 1.0;
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]] {
1272 // LP64D: entry:
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]] {
1282 // LP64D: entry:
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]] {
1299 // LP64D: entry:
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]] {
1309 // LP64D: entry:
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]] {
1323 // LP64D: entry:
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]] {
1333 // LP64D: entry:
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]] {
1347 // LP64D: entry:
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]] {
1357 // LP64D: entry:
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]] {
1371 // LP64D: entry:
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]] {
1381 // LP64D: entry:
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]] {
1395 // LP64D: entry:
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]] {
1405 // LP64D: entry:
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]] {
1419 // LP64D: entry:
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]] {
1429 // LP64D: entry:
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
1436 // convention.
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]] {
1503 // LP64: entry:
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]] {
1513 // LP64: entry:
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]] {
1531 // LP64: entry:
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]] {
1541 // LP64: entry:
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]] {
1553 // LP64: entry:
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]] {
1563 // LP64: entry:
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]] {
1584 // LP64D: entry:
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]] {
1594 // LP64D: entry:
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]] {
1620 // LP64: entry:
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]] {
1630 // LP64: entry:
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]] {
1642 // LP64: entry:
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]] {
1652 // LP64: entry:
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]] {
1664 // LP64: entry:
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]] {
1674 // LP64: entry:
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]] {
1686 // LP64: entry:
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]] {
1696 // LP64: entry:
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]] {
1708 // LP64: entry:
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]] {
1718 // LP64: entry:
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]] {
1733 // LP64: entry:
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]] {
1743 // LP64: entry:
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]] {
1762 // LP64: entry:
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]] {
1766 // LP64F: entry:
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]] {
1770 // LP64D: entry:
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]] {
1780 // LP64: entry:
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]] {
1790 // LP64: entry:
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) {
1797 return 1.0;
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]] {
1804 // LP64: entry:
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]] {
1814 // LP64: entry:
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]] {
1831 // LP64: entry:
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]] {
1841 // LP64: entry:
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]] {
1855 // LP64: entry:
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]] {
1865 // LP64: entry:
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]] {
1879 // LP64: entry:
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]] {
1889 // LP64: entry:
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]] {
1903 // LP64: entry:
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]] {
1913 // LP64: entry:
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]] {
1927 // LP64: entry:
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]] {
1937 // LP64: entry:
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]] {
1951 // LP64: entry:
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]] {
1961 // LP64: entry:
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
1972 // convention.
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]] {
1994 // LP64: entry:
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]] {
2004 // LP64: entry:
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};