Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / RISCV / riscv32-abi.c
blob040ae500fc60e43bc4606088cbd10a31eef34e5e
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 riscv32 -emit-llvm %s -o - \
3 // RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32-ILP32F,ILP32 %s
4 // RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
5 // RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32F-ILP32D,ILP32-ILP32F,ILP32F %s
6 // RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
7 // RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32F-ILP32D,ILP32D %s
9 #include <stddef.h>
10 #include <stdint.h>
12 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_void
13 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0:[0-9]+]] {
14 // ILP32-ILP32F-ILP32D: 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 // ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i1 @f_scalar_0
22 // ILP32-ILP32F-ILP32D-SAME: (i1 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
23 // ILP32-ILP32F-ILP32D: entry:
25 _Bool f_scalar_0(_Bool x) { return x; }
27 // ILP32-ILP32F-ILP32D-LABEL: define dso_local signext i8 @f_scalar_1
28 // ILP32-ILP32F-ILP32D-SAME: (i8 noundef signext [[X:%.*]]) #[[ATTR0]] {
29 // ILP32-ILP32F-ILP32D: entry:
31 int8_t f_scalar_1(int8_t x) { return x; }
33 // ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i8 @f_scalar_2
34 // ILP32-ILP32F-ILP32D-SAME: (i8 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
35 // ILP32-ILP32F-ILP32D: entry:
37 uint8_t f_scalar_2(uint8_t x) { return x; }
39 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_3
40 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] {
41 // ILP32-ILP32F-ILP32D: entry:
43 int32_t f_scalar_3(int32_t x) { return x; }
45 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_scalar_4
46 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X:%.*]]) #[[ATTR0]] {
47 // ILP32-ILP32F-ILP32D: entry:
49 int64_t f_scalar_4(int64_t x) { return x; }
51 // ILP32-ILP32F-ILP32D-LABEL: define dso_local float @f_fp_scalar_1
52 // ILP32-ILP32F-ILP32D-SAME: (float noundef [[X:%.*]]) #[[ATTR0]] {
53 // ILP32-ILP32F-ILP32D: entry:
55 float f_fp_scalar_1(float x) { return x; }
57 // ILP32-ILP32F-ILP32D-LABEL: define dso_local double @f_fp_scalar_2
58 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[X:%.*]]) #[[ATTR0]] {
59 // ILP32-ILP32F-ILP32D: entry:
61 double f_fp_scalar_2(double x) { return x; }
63 // Scalars larger than 2*xlen are passed/returned indirect. However, the
64 // RISC-V LLVM backend can handle this fine, so the function doesn't need to
65 // be modified.
67 // ILP32-ILP32F-ILP32D-LABEL: define dso_local fp128 @f_fp_scalar_3
68 // ILP32-ILP32F-ILP32D-SAME: (fp128 noundef [[X:%.*]]) #[[ATTR0]] {
69 // ILP32-ILP32F-ILP32D: entry:
71 long double f_fp_scalar_3(long double x) { return x; }
73 // ILP32-ILP32F-ILP32D-LABEL: define dso_local half @f_fp_scalar_4
74 // ILP32-ILP32F-ILP32D-SAME: (half noundef [[X:%.*]]) #[[ATTR0]] {
75 // ILP32-ILP32F-ILP32D: entry:
77 _Float16 f_fp_scalar_4(_Float16 x) { return x; }
79 // Empty structs or unions are ignored.
81 struct empty_s {};
83 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_struct
84 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
85 // ILP32-ILP32F-ILP32D: entry:
87 struct empty_s f_agg_empty_struct(struct empty_s x) {
88 return x;
91 union empty_u {};
93 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_union
94 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
95 // ILP32-ILP32F-ILP32D: entry:
97 union empty_u f_agg_empty_union(union empty_u x) {
98 return x;
101 // Aggregates <= 2*xlen may be passed in registers, so will be coerced to
102 // integer arguments. The rules for return are the same.
104 struct tiny {
105 uint8_t a, b, c, d;
108 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_tiny
109 // ILP32-ILP32F-ILP32D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] {
110 // ILP32-ILP32F-ILP32D: entry:
112 void f_agg_tiny(struct tiny x) {
113 x.a += x.b;
114 x.c += x.d;
117 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_agg_tiny_ret
118 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
119 // ILP32-ILP32F-ILP32D: entry:
121 struct tiny f_agg_tiny_ret(void) {
122 return (struct tiny){1, 2, 3, 4};
125 typedef uint8_t v4i8 __attribute__((vector_size(4)));
126 typedef int32_t v1i32 __attribute__((vector_size(4)));
128 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_tiny_v4i8
129 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
130 // ILP32-ILP32F-ILP32D: entry:
132 void f_vec_tiny_v4i8(v4i8 x) {
133 x[0] = x[1];
134 x[2] = x[3];
137 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_vec_tiny_v4i8_ret
138 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
139 // ILP32-ILP32F-ILP32D: entry:
141 v4i8 f_vec_tiny_v4i8_ret(void) {
142 return (v4i8){1, 2, 3, 4};
145 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_tiny_v1i32
146 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
147 // ILP32-ILP32F-ILP32D: entry:
149 void f_vec_tiny_v1i32(v1i32 x) {
150 x[0] = 114;
153 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_vec_tiny_v1i32_ret
154 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
155 // ILP32-ILP32F-ILP32D: entry:
157 v1i32 f_vec_tiny_v1i32_ret(void) {
158 return (v1i32){1};
161 struct small {
162 int32_t a, *b;
165 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small
166 // ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[X_COERCE:%.*]]) #[[ATTR0]] {
167 // ILP32-ILP32F-ILP32D: entry:
169 void f_agg_small(struct small x) {
170 x.a += *x.b;
171 x.b = &x.a;
174 // ILP32-ILP32F-ILP32D-LABEL: define dso_local [2 x i32] @f_agg_small_ret
175 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
176 // ILP32-ILP32F-ILP32D: entry:
178 struct small f_agg_small_ret(void) {
179 return (struct small){1, 0};
182 typedef uint8_t v8i8 __attribute__((vector_size(8)));
183 typedef int64_t v1i64 __attribute__((vector_size(8)));
185 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_small_v8i8
186 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
187 // ILP32-ILP32F-ILP32D: entry:
189 void f_vec_small_v8i8(v8i8 x) {
190 x[0] = x[7];
193 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_vec_small_v8i8_ret
194 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
195 // ILP32-ILP32F-ILP32D: entry:
197 v8i8 f_vec_small_v8i8_ret(void) {
198 return (v8i8){1, 2, 3, 4, 5, 6, 7, 8};
201 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_small_v1i64
202 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
203 // ILP32-ILP32F-ILP32D: entry:
205 void f_vec_small_v1i64(v1i64 x) {
206 x[0] = 114;
209 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_vec_small_v1i64_ret
210 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
211 // ILP32-ILP32F-ILP32D: entry:
213 v1i64 f_vec_small_v1i64_ret(void) {
214 return (v1i64){1};
217 // Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a
218 // single 2*xlen-sized argument, to ensure that alignment can be maintained if
219 // passed on the stack.
221 struct small_aligned {
222 int64_t a;
225 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small_aligned
226 // ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {
227 // ILP32-ILP32F-ILP32D: entry:
229 void f_agg_small_aligned(struct small_aligned x) {
230 x.a += x.a;
233 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_agg_small_aligned_ret
234 // ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {
235 // ILP32-ILP32F-ILP32D: entry:
237 struct small_aligned f_agg_small_aligned_ret(struct small_aligned x) {
238 return (struct small_aligned){10};
241 // Aggregates greater > 2*xlen will be passed and returned indirectly
242 struct large {
243 int32_t a, b, c, d;
246 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large
247 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[X:%.*]]) #[[ATTR0]] {
248 // ILP32-ILP32F-ILP32D: entry:
250 void f_agg_large(struct large x) {
251 x.a = x.b + x.c + x.d;
254 // The address where the struct should be written to will be the first
255 // argument
256 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large_ret
257 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] {
258 // ILP32-ILP32F-ILP32D: entry:
260 struct large f_agg_large_ret(int32_t i, int8_t j) {
261 return (struct large){1, 2, 3, 4};
264 typedef unsigned char v16i8 __attribute__((vector_size(16)));
266 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8
267 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] {
268 // ILP32-ILP32F-ILP32D: entry:
270 void f_vec_large_v16i8(v16i8 x) {
271 x[0] = x[7];
274 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8_ret
275 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret(<16 x i8>) align 16 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
276 // ILP32-ILP32F-ILP32D: entry:
278 v16i8 f_vec_large_v16i8_ret(void) {
279 return (v16i8){1, 2, 3, 4, 5, 6, 7, 8};
282 // Scalars passed on the stack should have signext/zeroext attributes, just as
283 // if they were passed in registers.
285 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_1
286 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]], [2 x i32] [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], ptr noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] {
287 // ILP32-ILP32F-ILP32D: entry:
289 int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,
290 struct large d, uint8_t e, int8_t f, uint8_t g, int8_t h) {
291 return g + h;
294 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_2
295 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {
296 // ILP32-ILP32F-ILP32D: entry:
298 struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d,
299 uint8_t e, int8_t f, uint8_t g) {
300 return (struct large){a, e, f, g};
303 // ILP32-ILP32F-ILP32D-LABEL: define dso_local fp128 @f_scalar_stack_3
304 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {
305 // ILP32-ILP32F-ILP32D: entry:
307 long double f_scalar_stack_3(int32_t a, int64_t b, int64_t c, long double d,
308 uint8_t e, int8_t f, uint8_t g) {
309 return d;
312 // Aggregates and >=XLen scalars passed on the stack should be lowered just as
313 // they would be if passed via registers.
315 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_4
316 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], i64 noundef [[D:%.*]], i32 noundef [[E:%.*]], i64 noundef [[F:%.*]], float noundef [[G:%.*]], double noundef [[H:%.*]], fp128 noundef [[I:%.*]]) #[[ATTR0]] {
317 // ILP32-ILP32F-ILP32D: entry:
319 void f_scalar_stack_4(double a, int64_t b, double c, int64_t d, int e,
320 int64_t f, float g, double h, long double i) {}
322 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_5
323 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i64 noundef [[B:%.*]], float noundef [[C:%.*]], double noundef [[D:%.*]], fp128 noundef [[E:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]], half noundef [[I:%.*]]) #[[ATTR0]] {
324 // ILP32-ILP32F-ILP32D: entry:
326 int f_scalar_stack_5(int32_t a, int64_t b, float c, double d, long double e,
327 uint8_t f, int8_t g, uint8_t h, _Float16 i) {
328 return g + h;
331 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_6
332 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {
333 // ILP32-ILP32F-ILP32D: entry:
335 struct large f_scalar_stack_6(float a, int64_t b, double c, long double d,
336 uint8_t e, int8_t f, uint8_t g) {
337 return (struct large){a, e, f, g};
340 // Aggregates and >=XLen scalars passed on the stack should be lowered just as
341 // they would be if passed via registers.
343 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_stack
344 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], i64 noundef [[D:%.*]], i32 [[E_COERCE:%.*]], [2 x i32] [[F_COERCE:%.*]], i64 [[G_COERCE:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
345 // ILP32-ILP32F-ILP32D: entry:
347 void f_agg_stack(double a, int64_t b, double c, int64_t d, struct tiny e,
348 struct small f, struct small_aligned g, struct large h) {}
350 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking
351 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], i8 noundef signext [[E:%.*]]) #[[ATTR0]] {
352 // ILP32-ILP32F-ILP32D: entry:
354 void f_fpr_tracking(double a, double b, double c, double d, int8_t e) {}
356 // Lowering for doubles is unnmodified, as 64 > FLEN.
358 struct double_s { double d; };
360 struct double_double_s { double d; double e; };
362 struct double_int8_s { double d; int64_t i; };
364 struct int_double_s { int a; double b; };
366 // ILP32-ILP32F-LABEL: define dso_local void @f_int_double_s_arg
367 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
368 // ILP32-ILP32F: entry:
370 // ILP32D-LABEL: define dso_local void @f_int_double_s_arg
371 // ILP32D-SAME: (i32 [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
372 // ILP32D: entry:
374 void f_int_double_s_arg(struct int_double_s a) {}
376 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_int_double_s
377 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
378 // ILP32-ILP32F: entry:
380 // ILP32D-LABEL: define dso_local { i32, double } @f_ret_int_double_s
381 // ILP32D-SAME: () #[[ATTR0]] {
382 // ILP32D: entry:
384 struct int_double_s f_ret_int_double_s(void) {
385 return (struct int_double_s){1, 2.0};
388 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking2
389 // ILP32-ILP32F-ILP32D-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]] {
390 // ILP32-ILP32F-ILP32D: entry:
392 void f_fpr_tracking2(double a, double b, double c, double d, double e, double f,
393 double g, double h, uint8_t i) {}
395 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
396 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
397 // available the widths are <= XLEN and FLEN, and should be expanded to
398 // separate arguments in IR. They are passed by the same rules for returns,
399 // but will be lowered to simple two-element structs if necessary (as LLVM IR
400 // functions cannot return multiple values).
402 // A struct containing just one floating-point real is passed as though it
403 // were a standalone floating-point real.
405 // ILP32-ILP32F-LABEL: define dso_local void @f_double_s_arg
406 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
407 // ILP32-ILP32F: entry:
409 // ILP32D-LABEL: define dso_local void @f_double_s_arg
410 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
411 // ILP32D: entry:
413 void f_double_s_arg(struct double_s a) {}
415 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_double_s
416 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
417 // ILP32-ILP32F: entry:
419 // ILP32D-LABEL: define dso_local double @f_ret_double_s
420 // ILP32D-SAME: () #[[ATTR0]] {
421 // ILP32D: entry:
423 struct double_s f_ret_double_s(void) {
424 return (struct double_s){1.0};
427 // A struct containing a double and any number of zero-width bitfields is
428 // passed as though it were a standalone floating-point real.
430 struct zbf_double_s { int : 0; double f; };
431 struct zbf_double_zbf_s { int : 0; double f; int : 0; };
433 // ILP32-ILP32F-LABEL: define dso_local void @f_zbf_double_s_arg
434 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
435 // ILP32-ILP32F: entry:
437 // ILP32D-LABEL: define dso_local void @f_zbf_double_s_arg
438 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
439 // ILP32D: entry:
441 void f_zbf_double_s_arg(struct zbf_double_s a) {}
443 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_zbf_double_s
444 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
445 // ILP32-ILP32F: entry:
447 // ILP32D-LABEL: define dso_local double @f_ret_zbf_double_s
448 // ILP32D-SAME: () #[[ATTR0]] {
449 // ILP32D: entry:
451 struct zbf_double_s f_ret_zbf_double_s(void) {
452 return (struct zbf_double_s){1.0};
455 // ILP32-ILP32F-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
456 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
457 // ILP32-ILP32F: entry:
459 // ILP32D-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
460 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
461 // ILP32D: entry:
463 void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {}
465 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_zbf_double_zbf_s
466 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
467 // ILP32-ILP32F: entry:
469 // ILP32D-LABEL: define dso_local double @f_ret_zbf_double_zbf_s
470 // ILP32D-SAME: () #[[ATTR0]] {
471 // ILP32D: entry:
473 struct zbf_double_zbf_s f_ret_zbf_double_zbf_s(void) {
474 return (struct zbf_double_zbf_s){1.0};
477 // Check that structs containing two floating point values (FLEN <= width) are
478 // expanded provided sufficient FPRs are available.
480 struct double_float_s { double f; float g; };
482 // ILP32-ILP32F-LABEL: define dso_local void @f_double_double_s_arg
483 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
484 // ILP32-ILP32F: entry:
486 // ILP32D-LABEL: define dso_local void @f_double_double_s_arg
487 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
488 // ILP32D: entry:
490 void f_double_double_s_arg(struct double_double_s a) {}
492 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s
493 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
494 // ILP32-ILP32F: entry:
496 // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s
497 // ILP32D-SAME: () #[[ATTR0]] {
498 // ILP32D: entry:
500 struct double_double_s f_ret_double_double_s(void) {
501 return (struct double_double_s){1.0, 2.0};
504 // ILP32-ILP32F-LABEL: define dso_local void @f_double_float_s_arg
505 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
506 // ILP32-ILP32F: entry:
508 // ILP32D-LABEL: define dso_local void @f_double_float_s_arg
509 // ILP32D-SAME: (double [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
510 // ILP32D: entry:
512 void f_double_float_s_arg(struct double_float_s a) {}
514 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float_s
515 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
516 // ILP32-ILP32F: entry:
518 // ILP32D-LABEL: define dso_local { double, float } @f_ret_double_float_s
519 // ILP32D-SAME: () #[[ATTR0]] {
520 // ILP32D: entry:
522 struct double_float_s f_ret_double_float_s(void) {
523 return (struct double_float_s){1.0, 2.0};
526 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_double_s_arg_insufficient_fprs
527 // ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
528 // ILP32-ILP32F-ILP32D: entry:
530 void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d,
531 double e, double f, double g, struct double_double_s h) {}
533 // Check that structs containing int+double values are expanded, provided
534 // sufficient FPRs and GPRs are available. The integer components are neither
535 // sign or zero-extended.
537 struct double_uint8_s { double d; uint8_t i; };
538 struct double_int32_s { double d; int32_t i; };
539 struct double_int64_s { double d; int64_t i; };
540 struct double_int64bf_s { double d; int64_t i : 32; };
541 struct double_int8_zbf_s { double d; int8_t i; int : 0; };
543 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg
544 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
545 // ILP32-ILP32F-ILP32D: entry:
547 void f_double_int8_s_arg(struct double_int8_s a) {}
549 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int8_s
550 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
551 // ILP32-ILP32F-ILP32D: entry:
553 struct double_int8_s f_ret_double_int8_s(void) {
554 return (struct double_int8_s){1.0, 2};
557 // ILP32-ILP32F-LABEL: define dso_local void @f_double_uint8_s_arg
558 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
559 // ILP32-ILP32F: entry:
561 // ILP32D-LABEL: define dso_local void @f_double_uint8_s_arg
562 // ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
563 // ILP32D: entry:
565 void f_double_uint8_s_arg(struct double_uint8_s a) {}
567 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_uint8_s
568 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_UINT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
569 // ILP32-ILP32F: entry:
571 // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_uint8_s
572 // ILP32D-SAME: () #[[ATTR0]] {
573 // ILP32D: entry:
575 struct double_uint8_s f_ret_double_uint8_s(void) {
576 return (struct double_uint8_s){1.0, 2};
579 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int32_s_arg
580 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
581 // ILP32-ILP32F: entry:
583 // ILP32D-LABEL: define dso_local void @f_double_int32_s_arg
584 // ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
585 // ILP32D: entry:
587 void f_double_int32_s_arg(struct double_int32_s a) {}
589 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s
590 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
591 // ILP32-ILP32F: entry:
593 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s
594 // ILP32D-SAME: () #[[ATTR0]] {
595 // ILP32D: entry:
597 struct double_int32_s f_ret_double_int32_s(void) {
598 return (struct double_int32_s){1.0, 2};
601 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int64_s_arg
602 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
603 // ILP32-ILP32F-ILP32D: entry:
605 void f_double_int64_s_arg(struct double_int64_s a) {}
607 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int64_s
608 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
609 // ILP32-ILP32F-ILP32D: entry:
611 struct double_int64_s f_ret_double_int64_s(void) {
612 return (struct double_int64_s){1.0, 2};
615 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int64bf_s_arg
616 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
617 // ILP32-ILP32F: entry:
619 // ILP32D-LABEL: define dso_local void @f_double_int64bf_s_arg
620 // ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
621 // ILP32D: entry:
623 void f_double_int64bf_s_arg(struct double_int64bf_s a) {}
625 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int64bf_s
626 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT64BF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
627 // ILP32-ILP32F: entry:
629 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int64bf_s
630 // ILP32D-SAME: () #[[ATTR0]] {
631 // ILP32D: entry:
633 struct double_int64bf_s f_ret_double_int64bf_s(void) {
634 return (struct double_int64bf_s){1.0, 2};
637 // The zero-width bitfield means the struct can't be passed according to the
638 // floating point calling convention.
640 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int8_zbf_s
641 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
642 // ILP32-ILP32F: entry:
644 // ILP32D-LABEL: define dso_local void @f_double_int8_zbf_s
645 // ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
646 // ILP32D: entry:
648 void f_double_int8_zbf_s(struct double_int8_zbf_s a) {}
650 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int8_zbf_s
651 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT8_ZBF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
652 // ILP32-ILP32F: entry:
654 // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_zbf_s
655 // ILP32D-SAME: () #[[ATTR0]] {
656 // ILP32D: entry:
658 struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) {
659 return (struct double_int8_zbf_s){1.0, 2};
662 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg_insufficient_gprs
663 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], i32 noundef [[H:%.*]], ptr noundef [[I:%.*]]) #[[ATTR0]] {
664 // ILP32-ILP32F-ILP32D: entry:
666 void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
667 int f, int g, int h, struct double_int8_s i) {}
669 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_double_int8_insufficient_fprs
670 // ILP32-ILP32F-ILP32D-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:%.*]], ptr noundef [[I:%.*]]) #[[ATTR0]] {
671 // ILP32-ILP32F-ILP32D: entry:
673 void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d,
674 double e, double f, double g, double h, struct double_int8_s i) {}
676 // Complex floating-point values or structs containing a single complex
677 // floating-point value should be passed as if it were an fp+fp struct.
679 // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex
680 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
681 // ILP32-ILP32F: entry:
683 // ILP32D-LABEL: define dso_local void @f_doublecomplex
684 // ILP32D-SAME: (double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
685 // ILP32D: entry:
687 void f_doublecomplex(double __complex__ a) {}
689 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex
690 // ILP32-ILP32F-SAME: (ptr noalias sret({ double, double }) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
691 // ILP32-ILP32F: entry:
693 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex
694 // ILP32D-SAME: () #[[ATTR0]] {
695 // ILP32D: entry:
697 double __complex__ f_ret_doublecomplex(void) {
698 return 1.0;
701 struct doublecomplex_s { double __complex__ c; };
703 // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex_s_arg
704 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
705 // ILP32-ILP32F: entry:
707 // ILP32D-LABEL: define dso_local void @f_doublecomplex_s_arg
708 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
709 // ILP32D: entry:
711 void f_doublecomplex_s_arg(struct doublecomplex_s a) {}
713 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_s
714 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLECOMPLEX_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
715 // ILP32-ILP32F: entry:
717 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_s
718 // ILP32D-SAME: () #[[ATTR0]] {
719 // ILP32D: entry:
721 struct doublecomplex_s f_ret_doublecomplex_s(void) {
722 return (struct doublecomplex_s){1.0};
725 // Test single or two-element structs that need flattening. e.g. those
726 // containing nested structs, doubles in small arrays, zero-length structs etc.
728 struct doublearr1_s { double a[1]; };
730 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr1_s_arg
731 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
732 // ILP32-ILP32F: entry:
734 // ILP32D-LABEL: define dso_local void @f_doublearr1_s_arg
735 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
736 // ILP32D: entry:
738 void f_doublearr1_s_arg(struct doublearr1_s a) {}
740 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_doublearr1_s
741 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
742 // ILP32-ILP32F: entry:
744 // ILP32D-LABEL: define dso_local double @f_ret_doublearr1_s
745 // ILP32D-SAME: () #[[ATTR0]] {
746 // ILP32D: entry:
748 struct doublearr1_s f_ret_doublearr1_s(void) {
749 return (struct doublearr1_s){{1.0}};
752 struct doublearr2_s { double a[2]; };
754 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_s_arg
755 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
756 // ILP32-ILP32F: entry:
758 // ILP32D-LABEL: define dso_local void @f_doublearr2_s_arg
759 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
760 // ILP32D: entry:
762 void f_doublearr2_s_arg(struct doublearr2_s a) {}
764 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_s
765 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
766 // ILP32-ILP32F: entry:
768 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_s
769 // ILP32D-SAME: () #[[ATTR0]] {
770 // ILP32D: entry:
772 struct doublearr2_s f_ret_doublearr2_s(void) {
773 return (struct doublearr2_s){{1.0, 2.0}};
776 struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; };
778 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
779 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
780 // ILP32-ILP32F: entry:
782 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
783 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
784 // ILP32D: entry:
786 void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}
788 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky1_s
789 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY1_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
790 // ILP32-ILP32F: entry:
792 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky1_s
793 // ILP32D-SAME: () #[[ATTR0]] {
794 // ILP32D: entry:
796 struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {
797 return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};
800 struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; };
802 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
803 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
804 // ILP32-ILP32F: entry:
806 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
807 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
808 // ILP32D: entry:
810 void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}
812 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky2_s
813 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
814 // ILP32-ILP32F: entry:
816 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky2_s
817 // ILP32D-SAME: () #[[ATTR0]] {
818 // ILP32D: entry:
820 struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {
821 return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
824 struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; };
826 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
827 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
828 // ILP32-ILP32F: entry:
830 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
831 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
832 // ILP32D: entry:
834 void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}
836 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky3_s
837 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY3_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
838 // ILP32-ILP32F: entry:
840 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky3_s
841 // ILP32D-SAME: () #[[ATTR0]] {
842 // ILP32D: entry:
844 struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {
845 return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
848 struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; };
850 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
851 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
852 // ILP32-ILP32F: entry:
854 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
855 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
856 // ILP32D: entry:
858 void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}
860 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky4_s
861 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY4_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
862 // ILP32-ILP32F: entry:
864 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky4_s
865 // ILP32D-SAME: () #[[ATTR0]] {
866 // ILP32D: entry:
868 struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) {
869 return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
872 // Test structs that should be passed according to the normal integer calling
873 // convention.
875 struct int_double_int_s { int a; double b; int c; };
877 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_double_int_s_arg
878 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
879 // ILP32-ILP32F-ILP32D: entry:
881 void f_int_double_int_s_arg(struct int_double_int_s a) {}
883 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_double_int_s
884 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
885 // ILP32-ILP32F-ILP32D: entry:
887 struct int_double_int_s f_ret_int_double_int_s(void) {
888 return (struct int_double_int_s){1, 2.0, 3};
891 struct int64_double_s { int64_t a; double b; };
893 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_double_s_arg
894 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
895 // ILP32-ILP32F-ILP32D: entry:
897 void f_int64_double_s_arg(struct int64_double_s a) {}
899 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_double_s
900 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
901 // ILP32-ILP32F-ILP32D: entry:
903 struct int64_double_s f_ret_int64_double_s(void) {
904 return (struct int64_double_s){1, 2.0};
907 struct char_char_double_s { char a; char b; double c; };
909 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_double_s_arg
910 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
911 // ILP32-ILP32F-ILP32D: entry:
913 void f_char_char_double_s_arg(struct char_char_double_s a) {}
915 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_char_char_double_s
916 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_CHAR_CHAR_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
917 // ILP32-ILP32F-ILP32D: entry:
919 struct char_char_double_s f_ret_char_char_double_s(void) {
920 return (struct char_char_double_s){1, 2, 3.0};
923 // Unions are always passed according to the integer calling convention, even
924 // if they can only contain a double.
926 union double_u { double a; };
928 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_u_arg
929 // ILP32-ILP32F-ILP32D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
930 // ILP32-ILP32F-ILP32D: entry:
932 void f_double_u_arg(union double_u a) {}
934 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_ret_double_u
935 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
936 // ILP32-ILP32F-ILP32D: entry:
938 union double_u f_ret_double_u(void) {
939 return (union double_u){1.0};
942 // Test that we don't incorrectly think double+int/double+double structs will
943 // be returned indirectly and thus have an off-by-one error for the number of
944 // GPRs available (this is an edge case when structs > 2*XLEN are still
945 // returned in registers). This includes complex doubles, which are treated as
946 // double+double structs by the ABI.
948 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs
949 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
950 // ILP32-ILP32F: entry:
952 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs
953 // ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
954 // ILP32D: entry:
956 struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(
957 int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
958 return (struct double_int32_s){1.0, 2};
961 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs
962 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
963 // ILP32-ILP32F: entry:
965 // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s_double_int32_s_just_sufficient_gprs
966 // ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
967 // ILP32D: entry:
969 struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs(
970 int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
971 return (struct double_double_s){1.0, 2.0};
974 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs
975 // ILP32-ILP32F-SAME: (ptr noalias sret({ double, double }) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
976 // ILP32-ILP32F: entry:
978 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs
979 // ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
980 // ILP32D: entry:
982 double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(
983 int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
984 return 1.0;
987 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking_3
988 // ILP32-ILP32F-ILP32D-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]] {
989 // ILP32-ILP32F-ILP32D: entry:
991 void f_fpr_tracking_3(float a, float b, float c, float d, float e, float f,
992 float g, float h, uint8_t i) {}
994 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
995 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
996 // available the widths are <= XLEN and FLEN, and should be expanded to
997 // separate arguments in IR. They are passed by the same rules for returns,
998 // but will be lowered to simple two-element structs if necessary (as LLVM IR
999 // functions cannot return multiple values).
1001 // A struct containing just one floating-point real is passed as though it
1002 // were a standalone floating-point real.
1004 struct float_s { float f; };
1006 // ILP32-LABEL: define dso_local void @f_float_s_arg
1007 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1008 // ILP32: entry:
1010 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_s_arg
1011 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1012 // ILP32F-ILP32D: entry:
1014 void f_float_s_arg(struct float_s a) {}
1016 // ILP32-LABEL: define dso_local i32 @f_ret_float_s
1017 // ILP32-SAME: () #[[ATTR0]] {
1018 // ILP32: entry:
1020 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_float_s
1021 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1022 // ILP32F-ILP32D: entry:
1024 struct float_s f_ret_float_s(void) {
1025 return (struct float_s){1.0};
1028 // A struct containing a float and any number of zero-width bitfields is
1029 // passed as though it were a standalone floating-point real.
1031 struct zbf_float_s { int : 0; float f; };
1032 struct zbf_float_zbf_s { int : 0; float f; int : 0; };
1034 // ILP32-LABEL: define dso_local void @f_zbf_float_s_arg
1035 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1036 // ILP32: entry:
1038 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_s_arg
1039 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1040 // ILP32F-ILP32D: entry:
1042 void f_zbf_float_s_arg(struct zbf_float_s a) {}
1044 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float_s
1045 // ILP32-SAME: () #[[ATTR0]] {
1046 // ILP32: entry:
1048 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_s
1049 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1050 // ILP32F-ILP32D: entry:
1052 struct zbf_float_s f_ret_zbf_float_s(void) {
1053 return (struct zbf_float_s){1.0};
1056 // ILP32-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
1057 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1058 // ILP32: entry:
1060 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
1061 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1062 // ILP32F-ILP32D: entry:
1064 void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {}
1066 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float_zbf_s
1067 // ILP32-SAME: () #[[ATTR0]] {
1068 // ILP32: entry:
1070 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_zbf_s
1071 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1072 // ILP32F-ILP32D: entry:
1074 struct zbf_float_zbf_s f_ret_zbf_float_zbf_s(void) {
1075 return (struct zbf_float_zbf_s){1.0};
1078 // Check that structs containing two float values (FLEN <= width) are expanded
1079 // provided sufficient FPRs are available.
1081 struct float_float_s { float f; float g; };
1083 // ILP32-LABEL: define dso_local void @f_float_float_s_arg
1084 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1085 // ILP32: entry:
1087 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_float_s_arg
1088 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1089 // ILP32F-ILP32D: entry:
1091 void f_float_float_s_arg(struct float_float_s a) {}
1093 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_float_s
1094 // ILP32-SAME: () #[[ATTR0]] {
1095 // ILP32: entry:
1097 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_float_float_s
1098 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1099 // ILP32F-ILP32D: entry:
1101 struct float_float_s f_ret_float_float_s(void) {
1102 return (struct float_float_s){1.0, 2.0};
1105 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_float_s_arg_insufficient_fprs
1106 // ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], [2 x i32] [[H_COERCE:%.*]]) #[[ATTR0]] {
1107 // ILP32-ILP32F-ILP32D: entry:
1109 void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d,
1110 float e, float f, float g, struct float_float_s h) {}
1112 // Check that structs containing int+float values are expanded, provided
1113 // sufficient FPRs and GPRs are available. The integer components are neither
1114 // sign or zero-extended.
1116 struct float_int8_s { float f; int8_t i; };
1117 struct float_uint8_s { float f; uint8_t i; };
1118 struct float_int32_s { float f; int32_t i; };
1119 struct float_int64_s { float f; int64_t i; };
1120 struct float_int64bf_s { float f; int64_t i : 32; };
1121 struct float_int8_zbf_s { float f; int8_t i; int : 0; };
1123 // ILP32-LABEL: define dso_local void @f_float_int8_s_arg
1124 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1125 // ILP32: entry:
1127 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_s_arg
1128 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1129 // ILP32F-ILP32D: entry:
1131 void f_float_int8_s_arg(struct float_int8_s a) {}
1133 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int8_s
1134 // ILP32-SAME: () #[[ATTR0]] {
1135 // ILP32: entry:
1137 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_s
1138 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1139 // ILP32F-ILP32D: entry:
1141 struct float_int8_s f_ret_float_int8_s(void) {
1142 return (struct float_int8_s){1.0, 2};
1145 // ILP32-LABEL: define dso_local void @f_float_uint8_s_arg
1146 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1147 // ILP32: entry:
1149 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_uint8_s_arg
1150 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1151 // ILP32F-ILP32D: entry:
1153 void f_float_uint8_s_arg(struct float_uint8_s a) {}
1155 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_uint8_s
1156 // ILP32-SAME: () #[[ATTR0]] {
1157 // ILP32: entry:
1159 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_uint8_s
1160 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1161 // ILP32F-ILP32D: entry:
1163 struct float_uint8_s f_ret_float_uint8_s(void) {
1164 return (struct float_uint8_s){1.0, 2};
1167 // ILP32-LABEL: define dso_local void @f_float_int32_s_arg
1168 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1169 // ILP32: entry:
1171 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int32_s_arg
1172 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1173 // ILP32F-ILP32D: entry:
1175 void f_float_int32_s_arg(struct float_int32_s a) {}
1177 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int32_s
1178 // ILP32-SAME: () #[[ATTR0]] {
1179 // ILP32: entry:
1181 // ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int32_s
1182 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1183 // ILP32F-ILP32D: entry:
1185 struct float_int32_s f_ret_float_int32_s(void) {
1186 return (struct float_int32_s){1.0, 2};
1189 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64_s_arg
1190 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1191 // ILP32-ILP32F-ILP32D: entry:
1193 void f_float_int64_s_arg(struct float_int64_s a) {}
1195 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float_int64_s
1196 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_FLOAT_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1197 // ILP32-ILP32F-ILP32D: entry:
1199 struct float_int64_s f_ret_float_int64_s(void) {
1200 return (struct float_int64_s){1.0, 2};
1203 // ILP32-LABEL: define dso_local void @f_float_int64bf_s_arg
1204 // ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1205 // ILP32: entry:
1207 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64bf_s_arg
1208 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1209 // ILP32F-ILP32D: entry:
1211 void f_float_int64bf_s_arg(struct float_int64bf_s a) {}
1213 // ILP32-LABEL: define dso_local i64 @f_ret_float_int64bf_s
1214 // ILP32-SAME: () #[[ATTR0]] {
1215 // ILP32: entry:
1217 // ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int64bf_s
1218 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1219 // ILP32F-ILP32D: entry:
1221 struct float_int64bf_s f_ret_float_int64bf_s(void) {
1222 return (struct float_int64bf_s){1.0, 2};
1225 // The zero-width bitfield means the struct can't be passed according to the
1226 // floating point calling convention.
1228 // ILP32-LABEL: define dso_local void @f_float_int8_zbf_s
1229 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1230 // ILP32: entry:
1232 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_zbf_s
1233 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1234 // ILP32F-ILP32D: entry:
1236 void f_float_int8_zbf_s(struct float_int8_zbf_s a) {}
1238 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int8_zbf_s
1239 // ILP32-SAME: () #[[ATTR0]] {
1240 // ILP32: entry:
1242 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_zbf_s
1243 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1244 // ILP32F-ILP32D: entry:
1246 struct float_int8_zbf_s f_ret_float_int8_zbf_s(void) {
1247 return (struct float_int8_zbf_s){1.0, 2};
1250 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_s_arg_insufficient_gprs
1251 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], i32 noundef [[H:%.*]], [2 x i32] [[I_COERCE:%.*]]) #[[ATTR0]] {
1252 // ILP32-ILP32F-ILP32D: entry:
1254 void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
1255 int f, int g, int h, struct float_int8_s i) {}
1257 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_float_int8_insufficient_fprs
1258 // ILP32-ILP32F-ILP32D-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:%.*]], [2 x i32] [[I_COERCE:%.*]]) #[[ATTR0]] {
1259 // ILP32-ILP32F-ILP32D: entry:
1261 void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d,
1262 float e, float f, float g, float h, struct float_int8_s i) {}
1264 // Complex floating-point values or structs containing a single complex
1265 // floating-point value should be passed as if it were an fp+fp struct.
1267 // ILP32-LABEL: define dso_local void @f_floatcomplex
1268 // ILP32-SAME: ([2 x i32] noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
1269 // ILP32: entry:
1271 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex
1272 // ILP32F-ILP32D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1273 // ILP32F-ILP32D: entry:
1275 void f_floatcomplex(float __complex__ a) {}
1277 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex
1278 // ILP32-SAME: () #[[ATTR0]] {
1279 // ILP32: entry:
1281 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex
1282 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1283 // ILP32F-ILP32D: entry:
1285 float __complex__ f_ret_floatcomplex(void) {
1286 return 1.0;
1289 struct floatcomplex_s { float __complex__ c; };
1291 // ILP32-LABEL: define dso_local void @f_floatcomplex_s_arg
1292 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1293 // ILP32: entry:
1295 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex_s_arg
1296 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1297 // ILP32F-ILP32D: entry:
1299 void f_floatcomplex_s_arg(struct floatcomplex_s a) {}
1301 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex_s
1302 // ILP32-SAME: () #[[ATTR0]] {
1303 // ILP32: entry:
1305 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex_s
1306 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1307 // ILP32F-ILP32D: entry:
1309 struct floatcomplex_s f_ret_floatcomplex_s(void) {
1310 return (struct floatcomplex_s){1.0};
1313 // Test single or two-element structs that need flattening. e.g. those
1314 // containing nested structs, floats in small arrays, zero-length structs etc.
1316 struct floatarr1_s { float a[1]; };
1318 // ILP32-LABEL: define dso_local void @f_floatarr1_s_arg
1319 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1320 // ILP32: entry:
1322 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr1_s_arg
1323 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1324 // ILP32F-ILP32D: entry:
1326 void f_floatarr1_s_arg(struct floatarr1_s a) {}
1328 // ILP32-LABEL: define dso_local i32 @f_ret_floatarr1_s
1329 // ILP32-SAME: () #[[ATTR0]] {
1330 // ILP32: entry:
1332 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_floatarr1_s
1333 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1334 // ILP32F-ILP32D: entry:
1336 struct floatarr1_s f_ret_floatarr1_s(void) {
1337 return (struct floatarr1_s){{1.0}};
1340 struct floatarr2_s { float a[2]; };
1342 // ILP32-LABEL: define dso_local void @f_floatarr2_s_arg
1343 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1344 // ILP32: entry:
1346 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_s_arg
1347 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1348 // ILP32F-ILP32D: entry:
1350 void f_floatarr2_s_arg(struct floatarr2_s a) {}
1352 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_s
1353 // ILP32-SAME: () #[[ATTR0]] {
1354 // ILP32: entry:
1356 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_s
1357 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1358 // ILP32F-ILP32D: entry:
1360 struct floatarr2_s f_ret_floatarr2_s(void) {
1361 return (struct floatarr2_s){{1.0, 2.0}};
1364 struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; };
1366 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
1367 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1368 // ILP32: entry:
1370 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
1371 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1372 // ILP32F-ILP32D: entry:
1374 void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {}
1376 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky1_s
1377 // ILP32-SAME: () #[[ATTR0]] {
1378 // ILP32: entry:
1380 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky1_s
1381 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1382 // ILP32F-ILP32D: entry:
1384 struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s(void) {
1385 return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}};
1388 struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; };
1390 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
1391 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1392 // ILP32: entry:
1394 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
1395 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1396 // ILP32F-ILP32D: entry:
1398 void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {}
1400 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky2_s
1401 // ILP32-SAME: () #[[ATTR0]] {
1402 // ILP32: entry:
1404 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky2_s
1405 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1406 // ILP32F-ILP32D: entry:
1408 struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s(void) {
1409 return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
1412 struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; };
1414 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
1415 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1416 // ILP32: entry:
1418 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
1419 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1420 // ILP32F-ILP32D: entry:
1422 void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {}
1424 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky3_s
1425 // ILP32-SAME: () #[[ATTR0]] {
1426 // ILP32: entry:
1428 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky3_s
1429 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1430 // ILP32F-ILP32D: entry:
1432 struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s(void) {
1433 return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
1436 struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; };
1438 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
1439 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1440 // ILP32: entry:
1442 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
1443 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1444 // ILP32F-ILP32D: entry:
1446 void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {}
1448 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky4_s
1449 // ILP32-SAME: () #[[ATTR0]] {
1450 // ILP32: entry:
1452 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky4_s
1453 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1454 // ILP32F-ILP32D: entry:
1456 struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s(void) {
1457 return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1460 // Test structs that should be passed according to the normal integer calling
1461 // convention.
1463 struct int_float_int_s { int a; float b; int c; };
1465 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float_int_s_arg
1466 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1467 // ILP32-ILP32F-ILP32D: entry:
1469 void f_int_float_int_s_arg(struct int_float_int_s a) {}
1471 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float_int_s
1472 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_FLOAT_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1473 // ILP32-ILP32F-ILP32D: entry:
1475 struct int_float_int_s f_ret_int_float_int_s(void) {
1476 return (struct int_float_int_s){1, 2.0, 3};
1479 struct int64_float_s { int64_t a; float b; };
1481 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float_s_arg
1482 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1483 // ILP32-ILP32F-ILP32D: entry:
1485 void f_int64_float_s_arg(struct int64_float_s a) {}
1487 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float_s
1488 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1489 // ILP32-ILP32F-ILP32D: entry:
1491 struct int64_float_s f_ret_int64_float_s(void) {
1492 return (struct int64_float_s){1, 2.0};
1495 struct char_char_float_s { char a; char b; float c; };
1497 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_float_s_arg
1498 // ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1499 // ILP32-ILP32F-ILP32D: entry:
1501 void f_char_char_float_s_arg(struct char_char_float_s a) {}
1503 // ILP32-ILP32F-ILP32D-LABEL: define dso_local [2 x i32] @f_ret_char_char_float_s
1504 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1505 // ILP32-ILP32F-ILP32D: entry:
1507 struct char_char_float_s f_ret_char_char_float_s(void) {
1508 return (struct char_char_float_s){1, 2, 3.0};
1511 // Unions are always passed according to the integer calling convention, even
1512 // if they can only contain a float.
1514 union float_u { float a; };
1516 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_u_arg
1517 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1518 // ILP32-ILP32F-ILP32D: entry:
1520 void f_float_u_arg(union float_u a) {}
1522 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float_u
1523 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1524 // ILP32-ILP32F-ILP32D: entry:
1526 union float_u f_ret_float_u(void) {
1527 return (union float_u){1.0};
1530 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
1531 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
1532 // available the widths are <= XLEN and FLEN, and should be expanded to
1533 // separate arguments in IR. They are passed by the same rules for returns,
1534 // but will be lowered to simple two-element structs if necessary (as LLVM IR
1535 // functions cannot return multiple values).
1537 struct float16_s { _Float16 f; };
1539 // A struct containing just one floating-point real is passed as though it
1540 // were a standalone floating-point real.
1542 // ILP32-LABEL: define dso_local void @f_float16_s_arg
1543 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1544 // ILP32: entry:
1546 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_s_arg
1547 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1548 // ILP32F-ILP32D: entry:
1550 void f_float16_s_arg(struct float16_s a) {}
1552 // ILP32-LABEL: define dso_local i32 @f_ret_float16_s
1553 // ILP32-SAME: () #[[ATTR0]] {
1554 // ILP32: entry:
1556 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16_s
1557 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1558 // ILP32F-ILP32D: entry:
1560 struct float16_s f_ret_float16_s(void) {
1561 return (struct float16_s){1.0};
1564 // A struct containing a double and any number of zero-width bitfields is
1565 // passed as though it were a standalone floating-point real.
1567 struct zbf_float16_s { int : 0; _Float16 f; };
1568 struct zbf_float16_zbf_s { int : 0; _Float16 f; int : 0; };
1570 // ILP32-LABEL: define dso_local void @f_zbf_float16_s_arg
1571 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1572 // ILP32: entry:
1574 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_s_arg
1575 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1576 // ILP32F-ILP32D: entry:
1578 void f_zbf_float16_s_arg(struct zbf_float16_s a) {}
1580 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float16_s
1581 // ILP32-SAME: () #[[ATTR0]] {
1582 // ILP32: entry:
1584 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_s
1585 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1586 // ILP32F-ILP32D: entry:
1588 struct zbf_float16_s f_ret_zbf_float16_s(void) {
1589 return (struct zbf_float16_s){1.0};
1592 // ILP32-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1593 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1594 // ILP32: entry:
1596 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1597 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1598 // ILP32F-ILP32D: entry:
1600 void f_zbf_float16_zbf_s_arg(struct zbf_float16_zbf_s a) {}
1602 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float16_zbf_s
1603 // ILP32-SAME: () #[[ATTR0]] {
1604 // ILP32: entry:
1606 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_zbf_s
1607 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1608 // ILP32F-ILP32D: entry:
1610 struct zbf_float16_zbf_s f_ret_zbf_float16_zbf_s(void) {
1611 return (struct zbf_float16_zbf_s){1.0};
1614 // Check that structs containing two floating point values (FLEN <= width) are
1615 // expanded provided sufficient FPRs are available.
1617 struct double_float16_s { double f; _Float16 g; };
1619 // ILP32-ILP32F-LABEL: define dso_local void @f_double_float16_s_arg
1620 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1621 // ILP32-ILP32F: entry:
1623 // ILP32D-LABEL: define dso_local void @f_double_float16_s_arg
1624 // ILP32D-SAME: (double [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1625 // ILP32D: entry:
1627 void f_double_float16_s_arg(struct double_float16_s a) {}
1629 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float16_s
1630 // ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1631 // ILP32-ILP32F: entry:
1633 // ILP32D-LABEL: define dso_local { double, half } @f_ret_double_float16_s
1634 // ILP32D-SAME: () #[[ATTR0]] {
1635 // ILP32D: entry:
1637 struct double_float16_s f_ret_double_float16_s(void) {
1638 return (struct double_float16_s){1.0, 2.0};
1641 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_float16_s_arg_insufficient_fprs
1642 // ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] {
1643 // ILP32-ILP32F-ILP32D: entry:
1645 void f_double_float16_s_arg_insufficient_fprs(float a, double b, double c, double d,
1646 double e, double f, double g, struct double_float16_s h) {}
1648 // Check that structs containing int+_Float16 values are expanded, provided
1649 // sufficient FPRs and GPRs are available. The integer components are neither
1650 // sign or zero-extended.
1652 struct float16_int8_s { _Float16 f; int8_t i; };
1653 struct float16_uint8_s { _Float16 f; uint8_t i; };
1654 struct float16_int32_s { _Float16 f; int32_t i; };
1655 struct float16_int64_s { _Float16 f; int64_t i; };
1656 struct float16_int64bf_s { _Float16 f; int64_t i : 32; };
1657 struct float16_int8_zbf_s { _Float16 f; int8_t i; int : 0; };
1659 // ILP32-LABEL: define dso_local void @f_float16_int8_s_arg
1660 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1661 // ILP32: entry:
1663 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_s_arg
1664 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1665 // ILP32F-ILP32D: entry:
1667 void f_float16_int8_s_arg(struct float16_int8_s a) {}
1669 // ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_s
1670 // ILP32-SAME: () #[[ATTR0]] {
1671 // ILP32: entry:
1673 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_s
1674 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1675 // ILP32F-ILP32D: entry:
1677 struct float16_int8_s f_ret_float16_int8_s(void) {
1678 return (struct float16_int8_s){1.0, 2};
1681 // ILP32-LABEL: define dso_local void @f_float16_uint8_s_arg
1682 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1683 // ILP32: entry:
1685 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_uint8_s_arg
1686 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1687 // ILP32F-ILP32D: entry:
1689 void f_float16_uint8_s_arg(struct float16_uint8_s a) {}
1691 // ILP32-LABEL: define dso_local i32 @f_ret_float16_uint8_s
1692 // ILP32-SAME: () #[[ATTR0]] {
1693 // ILP32: entry:
1695 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_uint8_s
1696 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1697 // ILP32F-ILP32D: entry:
1699 struct float16_uint8_s f_ret_float16_uint8_s(void) {
1700 return (struct float16_uint8_s){1.0, 2};
1703 // ILP32-LABEL: define dso_local void @f_float16_int32_s_arg
1704 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1705 // ILP32: entry:
1707 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int32_s_arg
1708 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1709 // ILP32F-ILP32D: entry:
1711 void f_float16_int32_s_arg(struct float16_int32_s a) {}
1713 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float16_int32_s
1714 // ILP32-SAME: () #[[ATTR0]] {
1715 // ILP32: entry:
1717 // ILP32F-ILP32D-LABEL: define dso_local { half, i32 } @f_ret_float16_int32_s
1718 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1719 // ILP32F-ILP32D: entry:
1721 struct float16_int32_s f_ret_float16_int32_s(void) {
1722 return (struct float16_int32_s){1.0, 2};
1725 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64_s_arg
1726 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1727 // ILP32-ILP32F-ILP32D: entry:
1729 void f_float16_int64_s_arg(struct float16_int64_s a) {}
1731 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float16_int64_s
1732 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_FLOAT16_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1733 // ILP32-ILP32F-ILP32D: entry:
1735 struct float16_int64_s f_ret_float16_int64_s(void) {
1736 return (struct float16_int64_s){1.0, 2};
1739 // ILP32-LABEL: define dso_local void @f_float16_int64bf_s_arg
1740 // ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1741 // ILP32: entry:
1743 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64bf_s_arg
1744 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1745 // ILP32F-ILP32D: entry:
1747 void f_float16_int64bf_s_arg(struct float16_int64bf_s a) {}
1749 // ILP32-LABEL: define dso_local i64 @f_ret_float16_int64bf_s
1750 // ILP32-SAME: () #[[ATTR0]] {
1751 // ILP32: entry:
1753 // ILP32F-ILP32D-LABEL: define dso_local <{ half, i32 }> @f_ret_float16_int64bf_s
1754 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1755 // ILP32F-ILP32D: entry:
1757 struct float16_int64bf_s f_ret_float16_int64bf_s(void) {
1758 return (struct float16_int64bf_s){1.0, 2};
1761 // The zero-width bitfield means the struct can't be passed according to the
1762 // floating point calling convention.
1764 // ILP32-LABEL: define dso_local void @f_float16_int8_zbf_s
1765 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1766 // ILP32: entry:
1768 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_zbf_s
1769 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1770 // ILP32F-ILP32D: entry:
1772 void f_float16_int8_zbf_s(struct float16_int8_zbf_s a) {}
1774 // ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_zbf_s
1775 // ILP32-SAME: () #[[ATTR0]] {
1776 // ILP32: entry:
1778 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_zbf_s
1779 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1780 // ILP32F-ILP32D: entry:
1782 struct float16_int8_zbf_s f_ret_float16_int8_zbf_s(void) {
1783 return (struct float16_int8_zbf_s){1.0, 2};
1786 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_s_arg_insufficient_gprs
1787 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], i32 noundef [[H:%.*]], i32 [[I_COERCE:%.*]]) #[[ATTR0]] {
1788 // ILP32-ILP32F-ILP32D: entry:
1790 void f_float16_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
1791 int f, int g, int h, struct float16_int8_s i) {}
1793 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs
1794 // ILP32-ILP32F-ILP32D-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:%.*]], i32 [[I_COERCE:%.*]]) #[[ATTR0]] {
1795 // ILP32-ILP32F-ILP32D: entry:
1797 void f_struct_float16_int8_insufficient_fprs(float a, double b, double c, double d,
1798 double e, double f, double g, double h, struct float16_int8_s i) {}
1800 // Complex floating-point values or structs containing a single complex
1801 // floating-point value should be passed as if it were an fp+fp struct.
1803 // ILP32-LABEL: define dso_local void @f_float16complex
1804 // ILP32-SAME: (i32 noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
1805 // ILP32: entry:
1807 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex
1808 // ILP32F-ILP32D-SAME: (half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1809 // ILP32F-ILP32D: entry:
1811 void f_float16complex(_Float16 __complex__ a) {}
1813 // ILP32-LABEL: define dso_local i32 @f_ret_float16complex
1814 // ILP32-SAME: () #[[ATTR0]] {
1815 // ILP32: entry:
1817 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex
1818 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1819 // ILP32F-ILP32D: entry:
1821 _Float16 __complex__ f_ret_float16complex(void) {
1822 return 1.0;
1825 struct float16complex_s { _Float16 __complex__ c; };
1827 // ILP32-LABEL: define dso_local void @f_float16complex_s_arg
1828 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1829 // ILP32: entry:
1831 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex_s_arg
1832 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1833 // ILP32F-ILP32D: entry:
1835 void f_float16complex_s_arg(struct float16complex_s a) {}
1837 // ILP32-LABEL: define dso_local i32 @f_ret_float16complex_s
1838 // ILP32-SAME: () #[[ATTR0]] {
1839 // ILP32: entry:
1841 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex_s
1842 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1843 // ILP32F-ILP32D: entry:
1845 struct float16complex_s f_ret_float16complex_s(void) {
1846 return (struct float16complex_s){1.0};
1849 // Test single or two-element structs that need flattening. e.g. those
1850 // containing nested structs, _Float16 in small arrays, zero-length structs etc.
1852 struct float16arr1_s { _Float16 a[1]; };
1854 // ILP32-LABEL: define dso_local void @f_float16arr1_s_arg
1855 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1856 // ILP32: entry:
1858 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr1_s_arg
1859 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1860 // ILP32F-ILP32D: entry:
1862 void f_float16arr1_s_arg(struct float16arr1_s a) {}
1864 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr1_s
1865 // ILP32-SAME: () #[[ATTR0]] {
1866 // ILP32: entry:
1868 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16arr1_s
1869 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1870 // ILP32F-ILP32D: entry:
1872 struct float16arr1_s f_ret_float16arr1_s(void) {
1873 return (struct float16arr1_s){{1.0}};
1876 struct float16arr2_s { _Float16 a[2]; };
1878 // ILP32-LABEL: define dso_local void @f_float16arr2_s_arg
1879 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1880 // ILP32: entry:
1882 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_s_arg
1883 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1884 // ILP32F-ILP32D: entry:
1886 void f_float16arr2_s_arg(struct float16arr2_s a) {}
1888 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_s
1889 // ILP32-SAME: () #[[ATTR0]] {
1890 // ILP32: entry:
1892 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_s
1893 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1894 // ILP32F-ILP32D: entry:
1896 struct float16arr2_s f_ret_float16arr2_s(void) {
1897 return (struct float16arr2_s){{1.0, 2.0}};
1900 struct float16arr2_tricky1_s { struct { _Float16 f[1]; } g[2]; };
1902 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1903 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1904 // ILP32: entry:
1906 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1907 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1908 // ILP32F-ILP32D: entry:
1910 void f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a) {}
1912 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky1_s
1913 // ILP32-SAME: () #[[ATTR0]] {
1914 // ILP32: entry:
1916 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky1_s
1917 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1918 // ILP32F-ILP32D: entry:
1920 struct float16arr2_tricky1_s f_ret_float16arr2_tricky1_s(void) {
1921 return (struct float16arr2_tricky1_s){{{{1.0}}, {{2.0}}}};
1924 struct float16arr2_tricky2_s { struct {}; struct { _Float16 f[1]; } g[2]; };
1926 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1927 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1928 // ILP32: entry:
1930 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1931 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1932 // ILP32F-ILP32D: entry:
1934 void f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a) {}
1936 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky2_s
1937 // ILP32-SAME: () #[[ATTR0]] {
1938 // ILP32: entry:
1940 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky2_s
1941 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1942 // ILP32F-ILP32D: entry:
1944 struct float16arr2_tricky2_s f_ret_float16arr2_tricky2_s(void) {
1945 return (struct float16arr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
1948 struct float16arr2_tricky3_s { union {}; struct { _Float16 f[1]; } g[2]; };
1950 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1951 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1952 // ILP32: entry:
1954 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1955 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1956 // ILP32F-ILP32D: entry:
1958 void f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a) {}
1960 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky3_s
1961 // ILP32-SAME: () #[[ATTR0]] {
1962 // ILP32: entry:
1964 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky3_s
1965 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1966 // ILP32F-ILP32D: entry:
1968 struct float16arr2_tricky3_s f_ret_float16arr2_tricky3_s(void) {
1969 return (struct float16arr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
1972 struct float16arr2_tricky4_s { union {}; struct { struct {}; _Float16 f[1]; } g[2]; };
1974 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1975 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1976 // ILP32: entry:
1978 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1979 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1980 // ILP32F-ILP32D: entry:
1982 void f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a) {}
1984 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky4_s
1985 // ILP32-SAME: () #[[ATTR0]] {
1986 // ILP32: entry:
1988 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky4_s
1989 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1990 // ILP32F-ILP32D: entry:
1992 struct float16arr2_tricky4_s f_ret_float16arr2_tricky4_s(void) {
1993 return (struct float16arr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1996 // Test structs that should be passed according to the normal integer calling
1997 // convention.
1999 struct int_float16_int_s { int a; _Float16 b; int c; };
2001 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float16_int_s_arg
2002 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
2003 // ILP32-ILP32F-ILP32D: entry:
2005 void f_int_float16_int_s_arg(struct int_float16_int_s a) {}
2007 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float16_int_s
2008 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_FLOAT16_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
2009 // ILP32-ILP32F-ILP32D: entry:
2011 struct int_float16_int_s f_ret_int_float16_int_s(void) {
2012 return (struct int_float16_int_s){1, 2.0, 3};
2015 struct int64_float16_s { int64_t a; _Float16 b; };
2017 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float16_s_arg
2018 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
2019 // ILP32-ILP32F-ILP32D: entry:
2021 void f_int64_float16_s_arg(struct int64_float16_s a) {}
2023 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float16_s
2024 // ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
2025 // ILP32-ILP32F-ILP32D: entry:
2027 struct int64_float16_s f_ret_int64_float16_s(void) {
2028 return (struct int64_float16_s){1, 2.0};
2031 struct char_char_float16_s { char a; char b; _Float16 c; };
2033 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_float16_s_arg
2034 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
2035 // ILP32-ILP32F-ILP32D: entry:
2037 void f_char_char_float16_s_arg(struct char_char_float16_s a) {}
2039 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_char_char_float16_s
2040 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
2041 // ILP32-ILP32F-ILP32D: entry:
2043 struct char_char_float16_s f_ret_char_char_float16_s(void) {
2044 return (struct char_char_float16_s){1, 2, 3.0};
2047 // Unions are always passed according to the integer calling convention, even
2048 // if they can only contain a double.
2050 union float16_u { _Float16 a; };
2052 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_u_arg
2053 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
2054 // ILP32-ILP32F-ILP32D: entry:
2056 void f_float16_u_arg(union float16_u a) {}
2058 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float16_u
2059 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
2060 // ILP32-ILP32F-ILP32D: entry:
2062 union float16_u f_ret_float16_u(void) {
2063 return (union float16_u){1.0};
2066 //// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
2067 // ILP32F: {{.*}}