xref: /llvm-project/clang/test/CodeGen/RISCV/riscv32-abi.c (revision 3ac9fe69f70a2b3541266daedbaaa7dc9c007a2a)
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
8 // RUN: %clang_cc1 -triple riscv32 -emit-llvm -target-abi ilp32e %s -o - \
9 // RUN:     | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32-ILP32F,ILP32,ILP32E %s
10 
11 #include <stddef.h>
12 #include <stdint.h>
13 
14 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_void
15 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0:[0-9]+]] {
16 // ILP32-ILP32F-ILP32D:  entry:
17 //
f_void(void)18 void f_void(void) {}
19 
20 // Scalar arguments and return values smaller than the word size are extended
21 // according to the sign of their type, up to 32 bits
22 
23 // ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i1 @f_scalar_0
24 // ILP32-ILP32F-ILP32D-SAME: (i1 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
25 // ILP32-ILP32F-ILP32D:  entry:
26 //
f_scalar_0(_Bool x)27 _Bool f_scalar_0(_Bool x) { return x; }
28 
29 // ILP32-ILP32F-ILP32D-LABEL: define dso_local signext i8 @f_scalar_1
30 // ILP32-ILP32F-ILP32D-SAME: (i8 noundef signext [[X:%.*]]) #[[ATTR0]] {
31 // ILP32-ILP32F-ILP32D:  entry:
32 //
f_scalar_1(int8_t x)33 int8_t f_scalar_1(int8_t x) { return x; }
34 
35 // ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i8 @f_scalar_2
36 // ILP32-ILP32F-ILP32D-SAME: (i8 noundef zeroext [[X:%.*]]) #[[ATTR0]] {
37 // ILP32-ILP32F-ILP32D:  entry:
38 //
f_scalar_2(uint8_t x)39 uint8_t f_scalar_2(uint8_t x) { return x; }
40 
41 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_3
42 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] {
43 // ILP32-ILP32F-ILP32D:  entry:
44 //
f_scalar_3(int32_t x)45 int32_t f_scalar_3(int32_t x) { return x; }
46 
47 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_scalar_4
48 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X:%.*]]) #[[ATTR0]] {
49 // ILP32-ILP32F-ILP32D:  entry:
50 //
f_scalar_4(int64_t x)51 int64_t f_scalar_4(int64_t x) { return x; }
52 
53 // ILP32-ILP32F-ILP32D-LABEL: define dso_local float @f_fp_scalar_1
54 // ILP32-ILP32F-ILP32D-SAME: (float noundef [[X:%.*]]) #[[ATTR0]] {
55 // ILP32-ILP32F-ILP32D:  entry:
56 //
f_fp_scalar_1(float x)57 float f_fp_scalar_1(float x) { return x; }
58 
59 // ILP32-ILP32F-ILP32D-LABEL: define dso_local double @f_fp_scalar_2
60 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[X:%.*]]) #[[ATTR0]] {
61 // ILP32-ILP32F-ILP32D:  entry:
62 //
f_fp_scalar_2(double x)63 double f_fp_scalar_2(double x) { return x; }
64 
65 // Scalars larger than 2*xlen are passed/returned indirect. However, the
66 // RISC-V LLVM backend can handle this fine, so the function doesn't need to
67 // be modified.
68 
69 // ILP32-ILP32F-ILP32D-LABEL: define dso_local fp128 @f_fp_scalar_3
70 // ILP32-ILP32F-ILP32D-SAME: (fp128 noundef [[X:%.*]]) #[[ATTR0]] {
71 // ILP32-ILP32F-ILP32D:  entry:
72 //
f_fp_scalar_3(long double x)73 long double f_fp_scalar_3(long double x) { return x; }
74 
75 // ILP32-ILP32F-ILP32D-LABEL: define dso_local half @f_fp_scalar_4
76 // ILP32-ILP32F-ILP32D-SAME: (half noundef [[X:%.*]]) #[[ATTR0]] {
77 // ILP32-ILP32F-ILP32D:  entry:
78 //
f_fp_scalar_4(_Float16 x)79 _Float16 f_fp_scalar_4(_Float16 x) { return x; }
80 
81 // Empty structs or unions are ignored.
82 
83 struct empty_s {};
84 
85 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_struct
86 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
87 // ILP32-ILP32F-ILP32D:  entry:
88 //
f_agg_empty_struct(struct empty_s x)89 struct empty_s f_agg_empty_struct(struct empty_s x) {
90   return x;
91 }
92 
93 union empty_u {};
94 
95 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_union
96 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
97 // ILP32-ILP32F-ILP32D:  entry:
98 //
f_agg_empty_union(union empty_u x)99 union empty_u f_agg_empty_union(union empty_u x) {
100   return x;
101 }
102 
103 // Aggregates <= 2*xlen may be passed in registers, so will be coerced to
104 // integer arguments. The rules for return are the same.
105 
106 struct tiny {
107   uint8_t a, b, c, d;
108 };
109 
110 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_tiny
111 // ILP32-ILP32F-ILP32D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] {
112 // ILP32-ILP32F-ILP32D:  entry:
113 //
f_agg_tiny(struct tiny x)114 void f_agg_tiny(struct tiny x) {
115   x.a += x.b;
116   x.c += x.d;
117 }
118 
119 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_agg_tiny_ret
120 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
121 // ILP32-ILP32F-ILP32D:  entry:
122 //
f_agg_tiny_ret(void)123 struct tiny f_agg_tiny_ret(void) {
124   return (struct tiny){1, 2, 3, 4};
125 }
126 
127 typedef uint8_t v4i8 __attribute__((vector_size(4)));
128 typedef int32_t v1i32 __attribute__((vector_size(4)));
129 
130 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_tiny_v4i8
131 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
132 // ILP32-ILP32F-ILP32D:  entry:
133 //
f_vec_tiny_v4i8(v4i8 x)134 void f_vec_tiny_v4i8(v4i8 x) {
135   x[0] = x[1];
136   x[2] = x[3];
137 }
138 
139 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_vec_tiny_v4i8_ret
140 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
141 // ILP32-ILP32F-ILP32D:  entry:
142 //
f_vec_tiny_v4i8_ret(void)143 v4i8 f_vec_tiny_v4i8_ret(void) {
144   return (v4i8){1, 2, 3, 4};
145 }
146 
147 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_tiny_v1i32
148 // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
149 // ILP32-ILP32F-ILP32D:  entry:
150 //
f_vec_tiny_v1i32(v1i32 x)151 void f_vec_tiny_v1i32(v1i32 x) {
152   x[0] = 114;
153 }
154 
155 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_vec_tiny_v1i32_ret
156 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
157 // ILP32-ILP32F-ILP32D:  entry:
158 //
f_vec_tiny_v1i32_ret(void)159 v1i32 f_vec_tiny_v1i32_ret(void) {
160   return (v1i32){1};
161 }
162 
163 struct small {
164   int32_t a, *b;
165 };
166 
167 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small
168 // ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[X_COERCE:%.*]]) #[[ATTR0]] {
169 // ILP32-ILP32F-ILP32D:  entry:
170 //
f_agg_small(struct small x)171 void f_agg_small(struct small x) {
172   x.a += *x.b;
173   x.b = &x.a;
174 }
175 
176 // ILP32-ILP32F-ILP32D-LABEL: define dso_local [2 x i32] @f_agg_small_ret
177 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
178 // ILP32-ILP32F-ILP32D:  entry:
179 //
f_agg_small_ret(void)180 struct small f_agg_small_ret(void) {
181   return (struct small){1, 0};
182 }
183 
184 typedef uint8_t v8i8 __attribute__((vector_size(8)));
185 typedef int64_t v1i64 __attribute__((vector_size(8)));
186 
187 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_small_v8i8
188 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
189 // ILP32-ILP32F-ILP32D:  entry:
190 //
f_vec_small_v8i8(v8i8 x)191 void f_vec_small_v8i8(v8i8 x) {
192   x[0] = x[7];
193 }
194 
195 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_vec_small_v8i8_ret
196 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
197 // ILP32-ILP32F-ILP32D:  entry:
198 //
f_vec_small_v8i8_ret(void)199 v8i8 f_vec_small_v8i8_ret(void) {
200   return (v8i8){1, 2, 3, 4, 5, 6, 7, 8};
201 }
202 
203 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_small_v1i64
204 // ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {
205 // ILP32-ILP32F-ILP32D:  entry:
206 //
f_vec_small_v1i64(v1i64 x)207 void f_vec_small_v1i64(v1i64 x) {
208   x[0] = 114;
209 }
210 
211 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_vec_small_v1i64_ret
212 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
213 // ILP32-ILP32F-ILP32D:  entry:
214 //
f_vec_small_v1i64_ret(void)215 v1i64 f_vec_small_v1i64_ret(void) {
216   return (v1i64){1};
217 }
218 
219 // Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a
220 // single 2*xlen-sized argument, to ensure that alignment can be maintained if
221 // passed on the stack.
222 
223 struct small_aligned {
224   int64_t a;
225 };
226 
227 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small_aligned
228 // ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {
229 // ILP32-ILP32F-ILP32D:  entry:
230 //
f_agg_small_aligned(struct small_aligned x)231 void f_agg_small_aligned(struct small_aligned x) {
232   x.a += x.a;
233 }
234 
235 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_agg_small_aligned_ret
236 // ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {
237 // ILP32-ILP32F-ILP32D:  entry:
238 //
f_agg_small_aligned_ret(struct small_aligned x)239 struct small_aligned f_agg_small_aligned_ret(struct small_aligned x) {
240   return (struct small_aligned){10};
241 }
242 
243 // Aggregates greater > 2*xlen will be passed and returned indirectly
244 struct large {
245   int32_t a, b, c, d;
246 };
247 
248 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large
249 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[X:%.*]]) #[[ATTR0]] {
250 // ILP32-ILP32F-ILP32D:  entry:
251 //
f_agg_large(struct large x)252 void f_agg_large(struct large x) {
253   x.a = x.b + x.c + x.d;
254 }
255 
256 // The address where the struct should be written to will be the first
257 // argument
258 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large_ret
259 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] {
260 // ILP32-ILP32F-ILP32D:  entry:
261 //
f_agg_large_ret(int32_t i,int8_t j)262 struct large f_agg_large_ret(int32_t i, int8_t j) {
263   return (struct large){1, 2, 3, 4};
264 }
265 
266 typedef unsigned char v16i8 __attribute__((vector_size(16)));
267 
268 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8
269 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] {
270 // ILP32-ILP32F-ILP32D:  entry:
271 //
f_vec_large_v16i8(v16i8 x)272 void f_vec_large_v16i8(v16i8 x) {
273   x[0] = x[7];
274 }
275 
276 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8_ret
277 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
278 // ILP32-ILP32F-ILP32D:  entry:
279 //
f_vec_large_v16i8_ret(void)280 v16i8 f_vec_large_v16i8_ret(void) {
281   return (v16i8){1, 2, 3, 4, 5, 6, 7, 8};
282 }
283 
284 // Scalars passed on the stack should have signext/zeroext attributes, just as
285 // if they were passed in registers.
286 
287 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_1
288 // 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]] {
289 // ILP32-ILP32F-ILP32D:  entry:
290 //
f_scalar_stack_1(struct tiny a,struct small b,struct small_aligned c,struct large d,uint8_t e,int8_t f,uint8_t g,int8_t h)291 int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,
292                      struct large d, uint8_t e, int8_t f, uint8_t g, int8_t h) {
293   return g + h;
294 }
295 
296 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_2
297 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable 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]] {
298 // ILP32-ILP32F-ILP32D:  entry:
299 //
f_scalar_stack_2(int32_t a,int64_t b,int64_t c,long double d,uint8_t e,int8_t f,uint8_t g)300 struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d,
301                               uint8_t e, int8_t f, uint8_t g) {
302   return (struct large){a, e, f, g};
303 }
304 
305 // ILP32-ILP32F-ILP32D-LABEL: define dso_local fp128 @f_scalar_stack_3
306 // 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]] {
307 // ILP32-ILP32F-ILP32D:  entry:
308 //
f_scalar_stack_3(int32_t a,int64_t b,int64_t c,long double d,uint8_t e,int8_t f,uint8_t g)309 long double f_scalar_stack_3(int32_t a, int64_t b, int64_t c, long double d,
310                              uint8_t e, int8_t f, uint8_t g) {
311   return d;
312 }
313 
314 // Aggregates and >=XLen scalars passed on the stack should be lowered just as
315 // they would be if passed via registers.
316 
317 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_4
318 // 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]] {
319 // ILP32-ILP32F-ILP32D:  entry:
320 //
f_scalar_stack_4(double a,int64_t b,double c,int64_t d,int e,int64_t f,float g,double h,long double i)321 void f_scalar_stack_4(double a, int64_t b, double c, int64_t d, int e,
322                       int64_t f, float g, double h, long double i) {}
323 
324 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_5
325 // 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]] {
326 // ILP32-ILP32F-ILP32D:  entry:
327 //
f_scalar_stack_5(int32_t a,int64_t b,float c,double d,long double e,uint8_t f,int8_t g,uint8_t h,_Float16 i)328 int f_scalar_stack_5(int32_t a, int64_t b, float c, double d, long double e,
329                      uint8_t f, int8_t g, uint8_t h, _Float16 i) {
330   return g + h;
331 }
332 
333 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_6
334 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable 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]] {
335 // ILP32-ILP32F-ILP32D:  entry:
336 //
f_scalar_stack_6(float a,int64_t b,double c,long double d,uint8_t e,int8_t f,uint8_t g)337 struct large f_scalar_stack_6(float a, int64_t b, double c, long double d,
338                               uint8_t e, int8_t f, uint8_t g) {
339   return (struct large){a, e, f, g};
340 }
341 
342 // Aggregates and >=XLen scalars passed on the stack should be lowered just as
343 // they would be if passed via registers.
344 
345 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_stack
346 // 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]] {
347 // ILP32-ILP32F-ILP32D:  entry:
348 //
f_agg_stack(double a,int64_t b,double c,int64_t d,struct tiny e,struct small f,struct small_aligned g,struct large h)349 void f_agg_stack(double a, int64_t b, double c, int64_t d, struct tiny e,
350                  struct small f, struct small_aligned g, struct large h) {}
351 
352 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking
353 // ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], i8 noundef signext [[E:%.*]]) #[[ATTR0]] {
354 // ILP32-ILP32F-ILP32D:  entry:
355 //
f_fpr_tracking(double a,double b,double c,double d,int8_t e)356 void f_fpr_tracking(double a, double b, double c, double d, int8_t e) {}
357 
358 // Lowering for doubles is unnmodified, as 64 > FLEN.
359 
360 struct double_s { double d; };
361 
362 struct double_double_s { double d; double e; };
363 
364 struct double_int8_s { double d; int64_t i; };
365 
366 struct int_double_s { int a; double b; };
367 
368 // ILP32-ILP32F-LABEL: define dso_local void @f_int_double_s_arg
369 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
370 // ILP32-ILP32F:  entry:
371 //
372 // ILP32D-LABEL: define dso_local void @f_int_double_s_arg
373 // ILP32D-SAME: (i32 [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
374 // ILP32D:  entry:
375 //
f_int_double_s_arg(struct int_double_s a)376 void f_int_double_s_arg(struct int_double_s a) {}
377 
378 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_int_double_s
379 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
380 // ILP32-ILP32F:  entry:
381 //
382 // ILP32D-LABEL: define dso_local { i32, double } @f_ret_int_double_s
383 // ILP32D-SAME: () #[[ATTR0]] {
384 // ILP32D:  entry:
385 //
f_ret_int_double_s(void)386 struct int_double_s f_ret_int_double_s(void) {
387   return (struct int_double_s){1, 2.0};
388 }
389 
390 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking2
391 // 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]] {
392 // ILP32-ILP32F-ILP32D:  entry:
393 //
f_fpr_tracking2(double a,double b,double c,double d,double e,double f,double g,double h,uint8_t i)394 void f_fpr_tracking2(double a, double b, double c, double d, double e, double f,
395                      double g, double h, uint8_t i) {}
396 
397 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
398 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
399 // available the widths are <= XLEN and FLEN, and should be expanded to
400 // separate arguments in IR. They are passed by the same rules for returns,
401 // but will be lowered to simple two-element structs if necessary (as LLVM IR
402 // functions cannot return multiple values).
403 
404 // A struct containing just one floating-point real is passed as though it
405 // were a standalone floating-point real.
406 
407 // ILP32-ILP32F-LABEL: define dso_local void @f_double_s_arg
408 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
409 // ILP32-ILP32F:  entry:
410 //
411 // ILP32D-LABEL: define dso_local void @f_double_s_arg
412 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
413 // ILP32D:  entry:
414 //
f_double_s_arg(struct double_s a)415 void f_double_s_arg(struct double_s a) {}
416 
417 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_double_s
418 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
419 // ILP32-ILP32F:  entry:
420 //
421 // ILP32D-LABEL: define dso_local double @f_ret_double_s
422 // ILP32D-SAME: () #[[ATTR0]] {
423 // ILP32D:  entry:
424 //
f_ret_double_s(void)425 struct double_s f_ret_double_s(void) {
426   return (struct double_s){1.0};
427 }
428 
429 // A struct containing a double and any number of zero-width bitfields is
430 // passed as though it were a standalone floating-point real.
431 
432 struct zbf_double_s { int : 0; double f; };
433 struct zbf_double_zbf_s { int : 0; double f; int : 0; };
434 
435 // ILP32-ILP32F-LABEL: define dso_local void @f_zbf_double_s_arg
436 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
437 // ILP32-ILP32F:  entry:
438 //
439 // ILP32D-LABEL: define dso_local void @f_zbf_double_s_arg
440 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
441 // ILP32D:  entry:
442 //
f_zbf_double_s_arg(struct zbf_double_s a)443 void f_zbf_double_s_arg(struct zbf_double_s a) {}
444 
445 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_zbf_double_s
446 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
447 // ILP32-ILP32F:  entry:
448 //
449 // ILP32D-LABEL: define dso_local double @f_ret_zbf_double_s
450 // ILP32D-SAME: () #[[ATTR0]] {
451 // ILP32D:  entry:
452 //
f_ret_zbf_double_s(void)453 struct zbf_double_s f_ret_zbf_double_s(void) {
454   return (struct zbf_double_s){1.0};
455 }
456 
457 // ILP32-ILP32F-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
458 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
459 // ILP32-ILP32F:  entry:
460 //
461 // ILP32D-LABEL: define dso_local void @f_zbf_double_zbf_s_arg
462 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
463 // ILP32D:  entry:
464 //
f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a)465 void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {}
466 
467 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_zbf_double_zbf_s
468 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
469 // ILP32-ILP32F:  entry:
470 //
471 // ILP32D-LABEL: define dso_local double @f_ret_zbf_double_zbf_s
472 // ILP32D-SAME: () #[[ATTR0]] {
473 // ILP32D:  entry:
474 //
f_ret_zbf_double_zbf_s(void)475 struct zbf_double_zbf_s f_ret_zbf_double_zbf_s(void) {
476   return (struct zbf_double_zbf_s){1.0};
477 }
478 
479 // Check that structs containing two floating point values (FLEN <= width) are
480 // expanded provided sufficient FPRs are available.
481 
482 struct double_float_s { double f; float g; };
483 
484 // ILP32-ILP32F-LABEL: define dso_local void @f_double_double_s_arg
485 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
486 // ILP32-ILP32F:  entry:
487 //
488 // ILP32D-LABEL: define dso_local void @f_double_double_s_arg
489 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
490 // ILP32D:  entry:
491 //
f_double_double_s_arg(struct double_double_s a)492 void f_double_double_s_arg(struct double_double_s a) {}
493 
494 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s
495 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
496 // ILP32-ILP32F:  entry:
497 //
498 // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s
499 // ILP32D-SAME: () #[[ATTR0]] {
500 // ILP32D:  entry:
501 //
f_ret_double_double_s(void)502 struct double_double_s f_ret_double_double_s(void) {
503   return (struct double_double_s){1.0, 2.0};
504 }
505 
506 // ILP32-ILP32F-LABEL: define dso_local void @f_double_float_s_arg
507 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
508 // ILP32-ILP32F:  entry:
509 //
510 // ILP32D-LABEL: define dso_local void @f_double_float_s_arg
511 // ILP32D-SAME: (double [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
512 // ILP32D:  entry:
513 //
f_double_float_s_arg(struct double_float_s a)514 void f_double_float_s_arg(struct double_float_s a) {}
515 
516 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float_s
517 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
518 // ILP32-ILP32F:  entry:
519 //
520 // ILP32D-LABEL: define dso_local { double, float } @f_ret_double_float_s
521 // ILP32D-SAME: () #[[ATTR0]] {
522 // ILP32D:  entry:
523 //
f_ret_double_float_s(void)524 struct double_float_s f_ret_double_float_s(void) {
525   return (struct double_float_s){1.0, 2.0};
526 }
527 
528 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_double_s_arg_insufficient_fprs
529 // 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]] {
530 // ILP32-ILP32F-ILP32D:  entry:
531 //
f_double_double_s_arg_insufficient_fprs(float a,double b,double c,double d,double e,double f,double g,struct double_double_s h)532 void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d,
533     double e, double f, double g, struct double_double_s h) {}
534 
535 // Check that structs containing int+double values are expanded, provided
536 // sufficient FPRs and GPRs are available. The integer components are neither
537 // sign or zero-extended.
538 
539 struct double_uint8_s { double d; uint8_t i; };
540 struct double_int32_s { double d; int32_t i; };
541 struct double_int64_s { double d; int64_t i; };
542 struct double_int64bf_s { double d; int64_t i : 32; };
543 struct double_int8_zbf_s { double d; int8_t i; int : 0; };
544 
545 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg
546 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
547 // ILP32-ILP32F-ILP32D:  entry:
548 //
f_double_int8_s_arg(struct double_int8_s a)549 void f_double_int8_s_arg(struct double_int8_s a) {}
550 
551 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int8_s
552 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
553 // ILP32-ILP32F-ILP32D:  entry:
554 //
f_ret_double_int8_s(void)555 struct double_int8_s f_ret_double_int8_s(void) {
556   return (struct double_int8_s){1.0, 2};
557 }
558 
559 // ILP32-ILP32F-LABEL: define dso_local void @f_double_uint8_s_arg
560 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
561 // ILP32-ILP32F:  entry:
562 //
563 // ILP32D-LABEL: define dso_local void @f_double_uint8_s_arg
564 // ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
565 // ILP32D:  entry:
566 //
f_double_uint8_s_arg(struct double_uint8_s a)567 void f_double_uint8_s_arg(struct double_uint8_s a) {}
568 
569 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_uint8_s
570 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_UINT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
571 // ILP32-ILP32F:  entry:
572 //
573 // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_uint8_s
574 // ILP32D-SAME: () #[[ATTR0]] {
575 // ILP32D:  entry:
576 //
f_ret_double_uint8_s(void)577 struct double_uint8_s f_ret_double_uint8_s(void) {
578   return (struct double_uint8_s){1.0, 2};
579 }
580 
581 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int32_s_arg
582 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
583 // ILP32-ILP32F:  entry:
584 //
585 // ILP32D-LABEL: define dso_local void @f_double_int32_s_arg
586 // ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
587 // ILP32D:  entry:
588 //
f_double_int32_s_arg(struct double_int32_s a)589 void f_double_int32_s_arg(struct double_int32_s a) {}
590 
591 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s
592 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
593 // ILP32-ILP32F:  entry:
594 //
595 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s
596 // ILP32D-SAME: () #[[ATTR0]] {
597 // ILP32D:  entry:
598 //
f_ret_double_int32_s(void)599 struct double_int32_s f_ret_double_int32_s(void) {
600   return (struct double_int32_s){1.0, 2};
601 }
602 
603 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int64_s_arg
604 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
605 // ILP32-ILP32F-ILP32D:  entry:
606 //
f_double_int64_s_arg(struct double_int64_s a)607 void f_double_int64_s_arg(struct double_int64_s a) {}
608 
609 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int64_s
610 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
611 // ILP32-ILP32F-ILP32D:  entry:
612 //
f_ret_double_int64_s(void)613 struct double_int64_s f_ret_double_int64_s(void) {
614   return (struct double_int64_s){1.0, 2};
615 }
616 
617 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int64bf_s_arg
618 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
619 // ILP32-ILP32F:  entry:
620 //
621 // ILP32D-LABEL: define dso_local void @f_double_int64bf_s_arg
622 // ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
623 // ILP32D:  entry:
624 //
f_double_int64bf_s_arg(struct double_int64bf_s a)625 void f_double_int64bf_s_arg(struct double_int64bf_s a) {}
626 
627 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int64bf_s
628 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT64BF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
629 // ILP32-ILP32F:  entry:
630 //
631 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int64bf_s
632 // ILP32D-SAME: () #[[ATTR0]] {
633 // ILP32D:  entry:
634 //
f_ret_double_int64bf_s(void)635 struct double_int64bf_s f_ret_double_int64bf_s(void) {
636   return (struct double_int64bf_s){1.0, 2};
637 }
638 
639 // The zero-width bitfield means the struct can't be passed according to the
640 // floating point calling convention.
641 
642 // ILP32-ILP32F-LABEL: define dso_local void @f_double_int8_zbf_s
643 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
644 // ILP32-ILP32F:  entry:
645 //
646 // ILP32D-LABEL: define dso_local void @f_double_int8_zbf_s
647 // ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
648 // ILP32D:  entry:
649 //
f_double_int8_zbf_s(struct double_int8_zbf_s a)650 void f_double_int8_zbf_s(struct double_int8_zbf_s a) {}
651 
652 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int8_zbf_s
653 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT8_ZBF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
654 // ILP32-ILP32F:  entry:
655 //
656 // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_zbf_s
657 // ILP32D-SAME: () #[[ATTR0]] {
658 // ILP32D:  entry:
659 //
f_ret_double_int8_zbf_s(void)660 struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) {
661   return (struct double_int8_zbf_s){1.0, 2};
662 }
663 
664 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg_insufficient_gprs
665 // 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]] {
666 // ILP32-ILP32F-ILP32D:  entry:
667 //
f_double_int8_s_arg_insufficient_gprs(int a,int b,int c,int d,int e,int f,int g,int h,struct double_int8_s i)668 void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
669                                           int f, int g, int h, struct double_int8_s i) {}
670 
671 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_double_int8_insufficient_fprs
672 // 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]] {
673 // ILP32-ILP32F-ILP32D:  entry:
674 //
f_struct_double_int8_insufficient_fprs(float a,double b,double c,double d,double e,double f,double g,double h,struct double_int8_s i)675 void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d,
676                                            double e, double f, double g, double h, struct double_int8_s i) {}
677 
678 // Complex floating-point values or structs containing a single complex
679 // floating-point value should be passed as if it were an fp+fp struct.
680 
681 // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex
682 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
683 // ILP32-ILP32F:  entry:
684 //
685 // ILP32D-LABEL: define dso_local void @f_doublecomplex
686 // ILP32D-SAME: (double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
687 // ILP32D:  entry:
688 //
f_doublecomplex(double __complex__ a)689 void f_doublecomplex(double __complex__ a) {}
690 
691 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex
692 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
693 // ILP32-ILP32F:  entry:
694 //
695 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex
696 // ILP32D-SAME: () #[[ATTR0]] {
697 // ILP32D:  entry:
698 //
f_ret_doublecomplex(void)699 double __complex__ f_ret_doublecomplex(void) {
700   return 1.0;
701 }
702 
703 struct doublecomplex_s { double __complex__ c; };
704 
705 // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex_s_arg
706 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
707 // ILP32-ILP32F:  entry:
708 //
709 // ILP32D-LABEL: define dso_local void @f_doublecomplex_s_arg
710 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
711 // ILP32D:  entry:
712 //
f_doublecomplex_s_arg(struct doublecomplex_s a)713 void f_doublecomplex_s_arg(struct doublecomplex_s a) {}
714 
715 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_s
716 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLECOMPLEX_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
717 // ILP32-ILP32F:  entry:
718 //
719 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_s
720 // ILP32D-SAME: () #[[ATTR0]] {
721 // ILP32D:  entry:
722 //
f_ret_doublecomplex_s(void)723 struct doublecomplex_s f_ret_doublecomplex_s(void) {
724   return (struct doublecomplex_s){1.0};
725 }
726 
727 // Test single or two-element structs that need flattening. e.g. those
728 // containing nested structs, doubles in small arrays, zero-length structs etc.
729 
730 struct doublearr1_s { double a[1]; };
731 
732 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr1_s_arg
733 // ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
734 // ILP32-ILP32F:  entry:
735 //
736 // ILP32D-LABEL: define dso_local void @f_doublearr1_s_arg
737 // ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {
738 // ILP32D:  entry:
739 //
f_doublearr1_s_arg(struct doublearr1_s a)740 void f_doublearr1_s_arg(struct doublearr1_s a) {}
741 
742 // ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_doublearr1_s
743 // ILP32-ILP32F-SAME: () #[[ATTR0]] {
744 // ILP32-ILP32F:  entry:
745 //
746 // ILP32D-LABEL: define dso_local double @f_ret_doublearr1_s
747 // ILP32D-SAME: () #[[ATTR0]] {
748 // ILP32D:  entry:
749 //
f_ret_doublearr1_s(void)750 struct doublearr1_s f_ret_doublearr1_s(void) {
751   return (struct doublearr1_s){{1.0}};
752 }
753 
754 struct doublearr2_s { double a[2]; };
755 
756 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_s_arg
757 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
758 // ILP32-ILP32F:  entry:
759 //
760 // ILP32D-LABEL: define dso_local void @f_doublearr2_s_arg
761 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
762 // ILP32D:  entry:
763 //
f_doublearr2_s_arg(struct doublearr2_s a)764 void f_doublearr2_s_arg(struct doublearr2_s a) {}
765 
766 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_s
767 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
768 // ILP32-ILP32F:  entry:
769 //
770 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_s
771 // ILP32D-SAME: () #[[ATTR0]] {
772 // ILP32D:  entry:
773 //
f_ret_doublearr2_s(void)774 struct doublearr2_s f_ret_doublearr2_s(void) {
775   return (struct doublearr2_s){{1.0, 2.0}};
776 }
777 
778 struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; };
779 
780 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
781 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
782 // ILP32-ILP32F:  entry:
783 //
784 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg
785 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
786 // ILP32D:  entry:
787 //
f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a)788 void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}
789 
790 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky1_s
791 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY1_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
792 // ILP32-ILP32F:  entry:
793 //
794 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky1_s
795 // ILP32D-SAME: () #[[ATTR0]] {
796 // ILP32D:  entry:
797 //
f_ret_doublearr2_tricky1_s(void)798 struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {
799   return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};
800 }
801 
802 struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; };
803 
804 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
805 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
806 // ILP32-ILP32F:  entry:
807 //
808 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg
809 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
810 // ILP32D:  entry:
811 //
f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a)812 void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}
813 
814 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky2_s
815 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
816 // ILP32-ILP32F:  entry:
817 //
818 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky2_s
819 // ILP32D-SAME: () #[[ATTR0]] {
820 // ILP32D:  entry:
821 //
f_ret_doublearr2_tricky2_s(void)822 struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {
823   return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
824 }
825 
826 struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; };
827 
828 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
829 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
830 // ILP32-ILP32F:  entry:
831 //
832 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg
833 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
834 // ILP32D:  entry:
835 //
f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a)836 void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}
837 
838 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky3_s
839 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY3_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
840 // ILP32-ILP32F:  entry:
841 //
842 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky3_s
843 // ILP32D-SAME: () #[[ATTR0]] {
844 // ILP32D:  entry:
845 //
f_ret_doublearr2_tricky3_s(void)846 struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {
847   return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
848 }
849 
850 struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; };
851 
852 // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
853 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
854 // ILP32-ILP32F:  entry:
855 //
856 // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg
857 // ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {
858 // ILP32D:  entry:
859 //
f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a)860 void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}
861 
862 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky4_s
863 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY4_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
864 // ILP32-ILP32F:  entry:
865 //
866 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky4_s
867 // ILP32D-SAME: () #[[ATTR0]] {
868 // ILP32D:  entry:
869 //
f_ret_doublearr2_tricky4_s(void)870 struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) {
871   return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
872 }
873 
874 // Test structs that should be passed according to the normal integer calling
875 // convention.
876 
877 struct int_double_int_s { int a; double b; int c; };
878 
879 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_double_int_s_arg
880 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
881 // ILP32-ILP32F-ILP32D:  entry:
882 //
f_int_double_int_s_arg(struct int_double_int_s a)883 void f_int_double_int_s_arg(struct int_double_int_s a) {}
884 
885 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_double_int_s
886 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
887 // ILP32-ILP32F-ILP32D:  entry:
888 //
f_ret_int_double_int_s(void)889 struct int_double_int_s f_ret_int_double_int_s(void) {
890   return (struct int_double_int_s){1, 2.0, 3};
891 }
892 
893 struct int64_double_s { int64_t a; double b; };
894 
895 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_double_s_arg
896 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
897 // ILP32-ILP32F-ILP32D:  entry:
898 //
f_int64_double_s_arg(struct int64_double_s a)899 void f_int64_double_s_arg(struct int64_double_s a) {}
900 
901 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_double_s
902 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
903 // ILP32-ILP32F-ILP32D:  entry:
904 //
f_ret_int64_double_s(void)905 struct int64_double_s f_ret_int64_double_s(void) {
906   return (struct int64_double_s){1, 2.0};
907 }
908 
909 struct char_char_double_s { char a; char b; double c; };
910 
911 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_double_s_arg
912 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
913 // ILP32-ILP32F-ILP32D:  entry:
914 //
f_char_char_double_s_arg(struct char_char_double_s a)915 void f_char_char_double_s_arg(struct char_char_double_s a) {}
916 
917 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_char_char_double_s
918 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHAR_CHAR_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
919 // ILP32-ILP32F-ILP32D:  entry:
920 //
f_ret_char_char_double_s(void)921 struct char_char_double_s f_ret_char_char_double_s(void) {
922   return (struct char_char_double_s){1, 2, 3.0};
923 }
924 
925 // Unions are always passed according to the integer calling convention, even
926 // if they can only contain a double.
927 
928 union double_u { double a; };
929 
930 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_u_arg
931 // ILP32-ILP32F-ILP32D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
932 // ILP32-ILP32F-ILP32D:  entry:
933 //
f_double_u_arg(union double_u a)934 void f_double_u_arg(union double_u a) {}
935 
936 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_ret_double_u
937 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
938 // ILP32-ILP32F-ILP32D:  entry:
939 //
f_ret_double_u(void)940 union double_u f_ret_double_u(void) {
941   return (union double_u){1.0};
942 }
943 
944 // Test that we don't incorrectly think double+int/double+double structs will
945 // be returned indirectly and thus have an off-by-one error for the number of
946 // GPRs available (this is an edge case when structs > 2*XLEN are still
947 // returned in registers). This includes complex doubles, which are treated as
948 // double+double structs by the ABI.
949 
950 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs
951 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable 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]] {
952 // ILP32-ILP32F:  entry:
953 //
954 // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs
955 // 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]] {
956 // ILP32D:  entry:
957 //
f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(int a,int b,int c,int d,int e,int f,int g,struct double_int32_s h)958 struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(
959     int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
960   return (struct double_int32_s){1.0, 2};
961 }
962 
963 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs
964 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable 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]] {
965 // ILP32-ILP32F:  entry:
966 //
967 // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s_double_int32_s_just_sufficient_gprs
968 // 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]] {
969 // ILP32D:  entry:
970 //
f_ret_double_double_s_double_int32_s_just_sufficient_gprs(int a,int b,int c,int d,int e,int f,int g,struct double_int32_s h)971 struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs(
972     int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
973   return (struct double_double_s){1.0, 2.0};
974 }
975 
976 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs
977 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable 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]] {
978 // ILP32-ILP32F:  entry:
979 //
980 // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs
981 // 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]] {
982 // ILP32D:  entry:
983 //
f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(int a,int b,int c,int d,int e,int f,int g,struct double_int32_s h)984 double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(
985     int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
986   return 1.0;
987 }
988 
989 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_fpr_tracking_3
990 // 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]] {
991 // ILP32-ILP32F-ILP32D:  entry:
992 //
f_fpr_tracking_3(float a,float b,float c,float d,float e,float f,float g,float h,uint8_t i)993 void f_fpr_tracking_3(float a, float b, float c, float d, float e, float f,
994                       float g, float h, uint8_t i) {}
995 
996 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
997 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
998 // available the widths are <= XLEN and FLEN, and should be expanded to
999 // separate arguments in IR. They are passed by the same rules for returns,
1000 // but will be lowered to simple two-element structs if necessary (as LLVM IR
1001 // functions cannot return multiple values).
1002 
1003 // A struct containing just one floating-point real is passed as though it
1004 // were a standalone floating-point real.
1005 
1006 struct float_s { float f; };
1007 
1008 // ILP32-LABEL: define dso_local void @f_float_s_arg
1009 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1010 // ILP32:  entry:
1011 //
1012 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_s_arg
1013 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1014 // ILP32F-ILP32D:  entry:
1015 //
f_float_s_arg(struct float_s a)1016 void f_float_s_arg(struct float_s a) {}
1017 
1018 // ILP32-LABEL: define dso_local i32 @f_ret_float_s
1019 // ILP32-SAME: () #[[ATTR0]] {
1020 // ILP32:  entry:
1021 //
1022 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_float_s
1023 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1024 // ILP32F-ILP32D:  entry:
1025 //
f_ret_float_s(void)1026 struct float_s f_ret_float_s(void) {
1027   return (struct float_s){1.0};
1028 }
1029 
1030 // A struct containing a float and any number of zero-width bitfields is
1031 // passed as though it were a standalone floating-point real.
1032 
1033 struct zbf_float_s { int : 0; float f; };
1034 struct zbf_float_zbf_s { int : 0; float f; int : 0; };
1035 
1036 // ILP32-LABEL: define dso_local void @f_zbf_float_s_arg
1037 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1038 // ILP32:  entry:
1039 //
1040 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_s_arg
1041 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1042 // ILP32F-ILP32D:  entry:
1043 //
f_zbf_float_s_arg(struct zbf_float_s a)1044 void f_zbf_float_s_arg(struct zbf_float_s a) {}
1045 
1046 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float_s
1047 // ILP32-SAME: () #[[ATTR0]] {
1048 // ILP32:  entry:
1049 //
1050 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_s
1051 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1052 // ILP32F-ILP32D:  entry:
1053 //
f_ret_zbf_float_s(void)1054 struct zbf_float_s f_ret_zbf_float_s(void) {
1055   return (struct zbf_float_s){1.0};
1056 }
1057 
1058 // ILP32-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
1059 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1060 // ILP32:  entry:
1061 //
1062 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_zbf_s_arg
1063 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1064 // ILP32F-ILP32D:  entry:
1065 //
f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a)1066 void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {}
1067 
1068 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float_zbf_s
1069 // ILP32-SAME: () #[[ATTR0]] {
1070 // ILP32:  entry:
1071 //
1072 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_zbf_s
1073 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1074 // ILP32F-ILP32D:  entry:
1075 //
f_ret_zbf_float_zbf_s(void)1076 struct zbf_float_zbf_s f_ret_zbf_float_zbf_s(void) {
1077   return (struct zbf_float_zbf_s){1.0};
1078 }
1079 
1080 // Check that structs containing two float values (FLEN <= width) are expanded
1081 // provided sufficient FPRs are available.
1082 
1083 struct float_float_s { float f; float g; };
1084 
1085 // ILP32-LABEL: define dso_local void @f_float_float_s_arg
1086 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1087 // ILP32:  entry:
1088 //
1089 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_float_s_arg
1090 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1091 // ILP32F-ILP32D:  entry:
1092 //
f_float_float_s_arg(struct float_float_s a)1093 void f_float_float_s_arg(struct float_float_s a) {}
1094 
1095 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_float_s
1096 // ILP32-SAME: () #[[ATTR0]] {
1097 // ILP32:  entry:
1098 //
1099 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_float_float_s
1100 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1101 // ILP32F-ILP32D:  entry:
1102 //
f_ret_float_float_s(void)1103 struct float_float_s f_ret_float_float_s(void) {
1104   return (struct float_float_s){1.0, 2.0};
1105 }
1106 
1107 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_float_s_arg_insufficient_fprs
1108 // 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]] {
1109 // ILP32-ILP32F-ILP32D:  entry:
1110 //
f_float_float_s_arg_insufficient_fprs(float a,float b,float c,float d,float e,float f,float g,struct float_float_s h)1111 void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d,
1112     float e, float f, float g, struct float_float_s h) {}
1113 
1114 // Check that structs containing int+float values are expanded, provided
1115 // sufficient FPRs and GPRs are available. The integer components are neither
1116 // sign or zero-extended.
1117 
1118 struct float_int8_s { float f; int8_t i; };
1119 struct float_uint8_s { float f; uint8_t i; };
1120 struct float_int32_s { float f; int32_t i; };
1121 struct float_int64_s { float f; int64_t i; };
1122 struct float_int64bf_s { float f; int64_t i : 32; };
1123 struct float_int8_zbf_s { float f; int8_t i; int : 0; };
1124 
1125 // ILP32-LABEL: define dso_local void @f_float_int8_s_arg
1126 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1127 // ILP32:  entry:
1128 //
1129 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_s_arg
1130 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1131 // ILP32F-ILP32D:  entry:
1132 //
f_float_int8_s_arg(struct float_int8_s a)1133 void f_float_int8_s_arg(struct float_int8_s a) {}
1134 
1135 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int8_s
1136 // ILP32-SAME: () #[[ATTR0]] {
1137 // ILP32:  entry:
1138 //
1139 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_s
1140 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1141 // ILP32F-ILP32D:  entry:
1142 //
f_ret_float_int8_s(void)1143 struct float_int8_s f_ret_float_int8_s(void) {
1144   return (struct float_int8_s){1.0, 2};
1145 }
1146 
1147 // ILP32-LABEL: define dso_local void @f_float_uint8_s_arg
1148 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1149 // ILP32:  entry:
1150 //
1151 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_uint8_s_arg
1152 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1153 // ILP32F-ILP32D:  entry:
1154 //
f_float_uint8_s_arg(struct float_uint8_s a)1155 void f_float_uint8_s_arg(struct float_uint8_s a) {}
1156 
1157 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_uint8_s
1158 // ILP32-SAME: () #[[ATTR0]] {
1159 // ILP32:  entry:
1160 //
1161 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_uint8_s
1162 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1163 // ILP32F-ILP32D:  entry:
1164 //
f_ret_float_uint8_s(void)1165 struct float_uint8_s f_ret_float_uint8_s(void) {
1166   return (struct float_uint8_s){1.0, 2};
1167 }
1168 
1169 // ILP32-LABEL: define dso_local void @f_float_int32_s_arg
1170 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1171 // ILP32:  entry:
1172 //
1173 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int32_s_arg
1174 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1175 // ILP32F-ILP32D:  entry:
1176 //
f_float_int32_s_arg(struct float_int32_s a)1177 void f_float_int32_s_arg(struct float_int32_s a) {}
1178 
1179 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int32_s
1180 // ILP32-SAME: () #[[ATTR0]] {
1181 // ILP32:  entry:
1182 //
1183 // ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int32_s
1184 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1185 // ILP32F-ILP32D:  entry:
1186 //
f_ret_float_int32_s(void)1187 struct float_int32_s f_ret_float_int32_s(void) {
1188   return (struct float_int32_s){1.0, 2};
1189 }
1190 
1191 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64_s_arg
1192 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1193 // ILP32-ILP32F-ILP32D:  entry:
1194 //
f_float_int64_s_arg(struct float_int64_s a)1195 void f_float_int64_s_arg(struct float_int64_s a) {}
1196 
1197 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float_int64_s
1198 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1199 // ILP32-ILP32F-ILP32D:  entry:
1200 //
f_ret_float_int64_s(void)1201 struct float_int64_s f_ret_float_int64_s(void) {
1202   return (struct float_int64_s){1.0, 2};
1203 }
1204 
1205 // ILP32-LABEL: define dso_local void @f_float_int64bf_s_arg
1206 // ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1207 // ILP32:  entry:
1208 //
1209 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64bf_s_arg
1210 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1211 // ILP32F-ILP32D:  entry:
1212 //
f_float_int64bf_s_arg(struct float_int64bf_s a)1213 void f_float_int64bf_s_arg(struct float_int64bf_s a) {}
1214 
1215 // ILP32-LABEL: define dso_local i64 @f_ret_float_int64bf_s
1216 // ILP32-SAME: () #[[ATTR0]] {
1217 // ILP32:  entry:
1218 //
1219 // ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int64bf_s
1220 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1221 // ILP32F-ILP32D:  entry:
1222 //
f_ret_float_int64bf_s(void)1223 struct float_int64bf_s f_ret_float_int64bf_s(void) {
1224   return (struct float_int64bf_s){1.0, 2};
1225 }
1226 
1227 // The zero-width bitfield means the struct can't be passed according to the
1228 // floating point calling convention.
1229 
1230 // ILP32-LABEL: define dso_local void @f_float_int8_zbf_s
1231 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1232 // ILP32:  entry:
1233 //
1234 // ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_zbf_s
1235 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1236 // ILP32F-ILP32D:  entry:
1237 //
f_float_int8_zbf_s(struct float_int8_zbf_s a)1238 void f_float_int8_zbf_s(struct float_int8_zbf_s a) {}
1239 
1240 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int8_zbf_s
1241 // ILP32-SAME: () #[[ATTR0]] {
1242 // ILP32:  entry:
1243 //
1244 // ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_zbf_s
1245 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1246 // ILP32F-ILP32D:  entry:
1247 //
f_ret_float_int8_zbf_s(void)1248 struct float_int8_zbf_s f_ret_float_int8_zbf_s(void) {
1249   return (struct float_int8_zbf_s){1.0, 2};
1250 }
1251 
1252 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_s_arg_insufficient_gprs
1253 // 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]] {
1254 // ILP32-ILP32F-ILP32D:  entry:
1255 //
f_float_int8_s_arg_insufficient_gprs(int a,int b,int c,int d,int e,int f,int g,int h,struct float_int8_s i)1256 void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
1257                                           int f, int g, int h, struct float_int8_s i) {}
1258 
1259 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_float_int8_insufficient_fprs
1260 // 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]] {
1261 // ILP32-ILP32F-ILP32D:  entry:
1262 //
f_struct_float_int8_insufficient_fprs(float a,float b,float c,float d,float e,float f,float g,float h,struct float_int8_s i)1263 void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d,
1264                                            float e, float f, float g, float h, struct float_int8_s i) {}
1265 
1266 // Complex floating-point values or structs containing a single complex
1267 // floating-point value should be passed as if it were an fp+fp struct.
1268 
1269 // ILP32-LABEL: define dso_local void @f_floatcomplex
1270 // ILP32-SAME: ([2 x i32] noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
1271 // ILP32:  entry:
1272 //
1273 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex
1274 // ILP32F-ILP32D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1275 // ILP32F-ILP32D:  entry:
1276 //
f_floatcomplex(float __complex__ a)1277 void f_floatcomplex(float __complex__ a) {}
1278 
1279 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex
1280 // ILP32-SAME: () #[[ATTR0]] {
1281 // ILP32:  entry:
1282 //
1283 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex
1284 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1285 // ILP32F-ILP32D:  entry:
1286 //
f_ret_floatcomplex(void)1287 float __complex__ f_ret_floatcomplex(void) {
1288   return 1.0;
1289 }
1290 
1291 struct floatcomplex_s { float __complex__ c; };
1292 
1293 // ILP32-LABEL: define dso_local void @f_floatcomplex_s_arg
1294 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1295 // ILP32:  entry:
1296 //
1297 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex_s_arg
1298 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1299 // ILP32F-ILP32D:  entry:
1300 //
f_floatcomplex_s_arg(struct floatcomplex_s a)1301 void f_floatcomplex_s_arg(struct floatcomplex_s a) {}
1302 
1303 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex_s
1304 // ILP32-SAME: () #[[ATTR0]] {
1305 // ILP32:  entry:
1306 //
1307 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex_s
1308 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1309 // ILP32F-ILP32D:  entry:
1310 //
f_ret_floatcomplex_s(void)1311 struct floatcomplex_s f_ret_floatcomplex_s(void) {
1312   return (struct floatcomplex_s){1.0};
1313 }
1314 
1315 // Test single or two-element structs that need flattening. e.g. those
1316 // containing nested structs, floats in small arrays, zero-length structs etc.
1317 
1318 struct floatarr1_s { float a[1]; };
1319 
1320 // ILP32-LABEL: define dso_local void @f_floatarr1_s_arg
1321 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1322 // ILP32:  entry:
1323 //
1324 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr1_s_arg
1325 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
1326 // ILP32F-ILP32D:  entry:
1327 //
f_floatarr1_s_arg(struct floatarr1_s a)1328 void f_floatarr1_s_arg(struct floatarr1_s a) {}
1329 
1330 // ILP32-LABEL: define dso_local i32 @f_ret_floatarr1_s
1331 // ILP32-SAME: () #[[ATTR0]] {
1332 // ILP32:  entry:
1333 //
1334 // ILP32F-ILP32D-LABEL: define dso_local float @f_ret_floatarr1_s
1335 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1336 // ILP32F-ILP32D:  entry:
1337 //
f_ret_floatarr1_s(void)1338 struct floatarr1_s f_ret_floatarr1_s(void) {
1339   return (struct floatarr1_s){{1.0}};
1340 }
1341 
1342 struct floatarr2_s { float a[2]; };
1343 
1344 // ILP32-LABEL: define dso_local void @f_floatarr2_s_arg
1345 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1346 // ILP32:  entry:
1347 //
1348 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_s_arg
1349 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1350 // ILP32F-ILP32D:  entry:
1351 //
f_floatarr2_s_arg(struct floatarr2_s a)1352 void f_floatarr2_s_arg(struct floatarr2_s a) {}
1353 
1354 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_s
1355 // ILP32-SAME: () #[[ATTR0]] {
1356 // ILP32:  entry:
1357 //
1358 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_s
1359 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1360 // ILP32F-ILP32D:  entry:
1361 //
f_ret_floatarr2_s(void)1362 struct floatarr2_s f_ret_floatarr2_s(void) {
1363   return (struct floatarr2_s){{1.0, 2.0}};
1364 }
1365 
1366 struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; };
1367 
1368 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
1369 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1370 // ILP32:  entry:
1371 //
1372 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg
1373 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1374 // ILP32F-ILP32D:  entry:
1375 //
f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a)1376 void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {}
1377 
1378 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky1_s
1379 // ILP32-SAME: () #[[ATTR0]] {
1380 // ILP32:  entry:
1381 //
1382 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky1_s
1383 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1384 // ILP32F-ILP32D:  entry:
1385 //
f_ret_floatarr2_tricky1_s(void)1386 struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s(void) {
1387   return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}};
1388 }
1389 
1390 struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; };
1391 
1392 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
1393 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1394 // ILP32:  entry:
1395 //
1396 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg
1397 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1398 // ILP32F-ILP32D:  entry:
1399 //
f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a)1400 void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {}
1401 
1402 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky2_s
1403 // ILP32-SAME: () #[[ATTR0]] {
1404 // ILP32:  entry:
1405 //
1406 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky2_s
1407 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1408 // ILP32F-ILP32D:  entry:
1409 //
f_ret_floatarr2_tricky2_s(void)1410 struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s(void) {
1411   return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
1412 }
1413 
1414 struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; };
1415 
1416 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
1417 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1418 // ILP32:  entry:
1419 //
1420 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg
1421 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1422 // ILP32F-ILP32D:  entry:
1423 //
f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a)1424 void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {}
1425 
1426 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky3_s
1427 // ILP32-SAME: () #[[ATTR0]] {
1428 // ILP32:  entry:
1429 //
1430 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky3_s
1431 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1432 // ILP32F-ILP32D:  entry:
1433 //
f_ret_floatarr2_tricky3_s(void)1434 struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s(void) {
1435   return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
1436 }
1437 
1438 struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; };
1439 
1440 // ILP32-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
1441 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1442 // ILP32:  entry:
1443 //
1444 // ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg
1445 // ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
1446 // ILP32F-ILP32D:  entry:
1447 //
f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a)1448 void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {}
1449 
1450 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky4_s
1451 // ILP32-SAME: () #[[ATTR0]] {
1452 // ILP32:  entry:
1453 //
1454 // ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky4_s
1455 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1456 // ILP32F-ILP32D:  entry:
1457 //
f_ret_floatarr2_tricky4_s(void)1458 struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s(void) {
1459   return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1460 }
1461 
1462 // Test structs that should be passed according to the normal integer calling
1463 // convention.
1464 
1465 struct int_float_int_s { int a; float b; int c; };
1466 
1467 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float_int_s_arg
1468 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1469 // ILP32-ILP32F-ILP32D:  entry:
1470 //
f_int_float_int_s_arg(struct int_float_int_s a)1471 void f_int_float_int_s_arg(struct int_float_int_s a) {}
1472 
1473 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float_int_s
1474 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_FLOAT_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1475 // ILP32-ILP32F-ILP32D:  entry:
1476 //
f_ret_int_float_int_s(void)1477 struct int_float_int_s f_ret_int_float_int_s(void) {
1478   return (struct int_float_int_s){1, 2.0, 3};
1479 }
1480 
1481 struct int64_float_s { int64_t a; float b; };
1482 
1483 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float_s_arg
1484 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1485 // ILP32-ILP32F-ILP32D:  entry:
1486 //
f_int64_float_s_arg(struct int64_float_s a)1487 void f_int64_float_s_arg(struct int64_float_s a) {}
1488 
1489 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float_s
1490 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1491 // ILP32-ILP32F-ILP32D:  entry:
1492 //
f_ret_int64_float_s(void)1493 struct int64_float_s f_ret_int64_float_s(void) {
1494   return (struct int64_float_s){1, 2.0};
1495 }
1496 
1497 struct char_char_float_s { char a; char b; float c; };
1498 
1499 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_float_s_arg
1500 // ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1501 // ILP32-ILP32F-ILP32D:  entry:
1502 //
f_char_char_float_s_arg(struct char_char_float_s a)1503 void f_char_char_float_s_arg(struct char_char_float_s a) {}
1504 
1505 // ILP32-ILP32F-ILP32D-LABEL: define dso_local [2 x i32] @f_ret_char_char_float_s
1506 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1507 // ILP32-ILP32F-ILP32D:  entry:
1508 //
f_ret_char_char_float_s(void)1509 struct char_char_float_s f_ret_char_char_float_s(void) {
1510   return (struct char_char_float_s){1, 2, 3.0};
1511 }
1512 
1513 // Unions are always passed according to the integer calling convention, even
1514 // if they can only contain a float.
1515 
1516 union float_u { float a; };
1517 
1518 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_u_arg
1519 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1520 // ILP32-ILP32F-ILP32D:  entry:
1521 //
f_float_u_arg(union float_u a)1522 void f_float_u_arg(union float_u a) {}
1523 
1524 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float_u
1525 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1526 // ILP32-ILP32F-ILP32D:  entry:
1527 //
f_ret_float_u(void)1528 union float_u f_ret_float_u(void) {
1529   return (union float_u){1.0};
1530 }
1531 
1532 // Check that fp, fp+fp, and int+fp structs are lowered correctly. These will
1533 // be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are
1534 // available the widths are <= XLEN and FLEN, and should be expanded to
1535 // separate arguments in IR. They are passed by the same rules for returns,
1536 // but will be lowered to simple two-element structs if necessary (as LLVM IR
1537 // functions cannot return multiple values).
1538 
1539 struct float16_s { _Float16 f; };
1540 
1541 // A struct containing just one floating-point real is passed as though it
1542 // were a standalone floating-point real.
1543 
1544 // ILP32-LABEL: define dso_local void @f_float16_s_arg
1545 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1546 // ILP32:  entry:
1547 //
1548 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_s_arg
1549 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1550 // ILP32F-ILP32D:  entry:
1551 //
f_float16_s_arg(struct float16_s a)1552 void f_float16_s_arg(struct float16_s a) {}
1553 
1554 // ILP32-LABEL: define dso_local i32 @f_ret_float16_s
1555 // ILP32-SAME: () #[[ATTR0]] {
1556 // ILP32:  entry:
1557 //
1558 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16_s
1559 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1560 // ILP32F-ILP32D:  entry:
1561 //
f_ret_float16_s(void)1562 struct float16_s f_ret_float16_s(void) {
1563   return (struct float16_s){1.0};
1564 }
1565 
1566 // A struct containing a double and any number of zero-width bitfields is
1567 // passed as though it were a standalone floating-point real.
1568 
1569 struct zbf_float16_s { int : 0; _Float16 f; };
1570 struct zbf_float16_zbf_s { int : 0; _Float16 f; int : 0; };
1571 
1572 // ILP32-LABEL: define dso_local void @f_zbf_float16_s_arg
1573 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1574 // ILP32:  entry:
1575 //
1576 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_s_arg
1577 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1578 // ILP32F-ILP32D:  entry:
1579 //
f_zbf_float16_s_arg(struct zbf_float16_s a)1580 void f_zbf_float16_s_arg(struct zbf_float16_s a) {}
1581 
1582 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float16_s
1583 // ILP32-SAME: () #[[ATTR0]] {
1584 // ILP32:  entry:
1585 //
1586 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_s
1587 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1588 // ILP32F-ILP32D:  entry:
1589 //
f_ret_zbf_float16_s(void)1590 struct zbf_float16_s f_ret_zbf_float16_s(void) {
1591   return (struct zbf_float16_s){1.0};
1592 }
1593 
1594 // ILP32-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1595 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1596 // ILP32:  entry:
1597 //
1598 // ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg
1599 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1600 // ILP32F-ILP32D:  entry:
1601 //
f_zbf_float16_zbf_s_arg(struct zbf_float16_zbf_s a)1602 void f_zbf_float16_zbf_s_arg(struct zbf_float16_zbf_s a) {}
1603 
1604 // ILP32-LABEL: define dso_local i32 @f_ret_zbf_float16_zbf_s
1605 // ILP32-SAME: () #[[ATTR0]] {
1606 // ILP32:  entry:
1607 //
1608 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_zbf_s
1609 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1610 // ILP32F-ILP32D:  entry:
1611 //
f_ret_zbf_float16_zbf_s(void)1612 struct zbf_float16_zbf_s f_ret_zbf_float16_zbf_s(void) {
1613   return (struct zbf_float16_zbf_s){1.0};
1614 }
1615 
1616 // Check that structs containing two floating point values (FLEN <= width) are
1617 // expanded provided sufficient FPRs are available.
1618 
1619 struct double_float16_s { double f; _Float16 g; };
1620 
1621 // ILP32-ILP32F-LABEL: define dso_local void @f_double_float16_s_arg
1622 // ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1623 // ILP32-ILP32F:  entry:
1624 //
1625 // ILP32D-LABEL: define dso_local void @f_double_float16_s_arg
1626 // ILP32D-SAME: (double [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1627 // ILP32D:  entry:
1628 //
f_double_float16_s_arg(struct double_float16_s a)1629 void f_double_float16_s_arg(struct double_float16_s a) {}
1630 
1631 // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float16_s
1632 // ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1633 // ILP32-ILP32F:  entry:
1634 //
1635 // ILP32D-LABEL: define dso_local { double, half } @f_ret_double_float16_s
1636 // ILP32D-SAME: () #[[ATTR0]] {
1637 // ILP32D:  entry:
1638 //
f_ret_double_float16_s(void)1639 struct double_float16_s f_ret_double_float16_s(void) {
1640   return (struct double_float16_s){1.0, 2.0};
1641 }
1642 
1643 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_float16_s_arg_insufficient_fprs
1644 // 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]] {
1645 // ILP32-ILP32F-ILP32D:  entry:
1646 //
f_double_float16_s_arg_insufficient_fprs(float a,double b,double c,double d,double e,double f,double g,struct double_float16_s h)1647 void f_double_float16_s_arg_insufficient_fprs(float a, double b, double c, double d,
1648     double e, double f, double g, struct double_float16_s h) {}
1649 
1650 // Check that structs containing int+_Float16 values are expanded, provided
1651 // sufficient FPRs and GPRs are available. The integer components are neither
1652 // sign or zero-extended.
1653 
1654 struct float16_int8_s { _Float16 f; int8_t i; };
1655 struct float16_uint8_s { _Float16 f; uint8_t i; };
1656 struct float16_int32_s { _Float16 f; int32_t i; };
1657 struct float16_int64_s { _Float16 f; int64_t i; };
1658 struct float16_int64bf_s { _Float16 f; int64_t i : 32; };
1659 struct float16_int8_zbf_s { _Float16 f; int8_t i; int : 0; };
1660 
1661 // ILP32-LABEL: define dso_local void @f_float16_int8_s_arg
1662 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1663 // ILP32:  entry:
1664 //
1665 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_s_arg
1666 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1667 // ILP32F-ILP32D:  entry:
1668 //
f_float16_int8_s_arg(struct float16_int8_s a)1669 void f_float16_int8_s_arg(struct float16_int8_s a) {}
1670 
1671 // ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_s
1672 // ILP32-SAME: () #[[ATTR0]] {
1673 // ILP32:  entry:
1674 //
1675 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_s
1676 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1677 // ILP32F-ILP32D:  entry:
1678 //
f_ret_float16_int8_s(void)1679 struct float16_int8_s f_ret_float16_int8_s(void) {
1680   return (struct float16_int8_s){1.0, 2};
1681 }
1682 
1683 // ILP32-LABEL: define dso_local void @f_float16_uint8_s_arg
1684 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1685 // ILP32:  entry:
1686 //
1687 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_uint8_s_arg
1688 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1689 // ILP32F-ILP32D:  entry:
1690 //
f_float16_uint8_s_arg(struct float16_uint8_s a)1691 void f_float16_uint8_s_arg(struct float16_uint8_s a) {}
1692 
1693 // ILP32-LABEL: define dso_local i32 @f_ret_float16_uint8_s
1694 // ILP32-SAME: () #[[ATTR0]] {
1695 // ILP32:  entry:
1696 //
1697 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_uint8_s
1698 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1699 // ILP32F-ILP32D:  entry:
1700 //
f_ret_float16_uint8_s(void)1701 struct float16_uint8_s f_ret_float16_uint8_s(void) {
1702   return (struct float16_uint8_s){1.0, 2};
1703 }
1704 
1705 // ILP32-LABEL: define dso_local void @f_float16_int32_s_arg
1706 // ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
1707 // ILP32:  entry:
1708 //
1709 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int32_s_arg
1710 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1711 // ILP32F-ILP32D:  entry:
1712 //
f_float16_int32_s_arg(struct float16_int32_s a)1713 void f_float16_int32_s_arg(struct float16_int32_s a) {}
1714 
1715 // ILP32-LABEL: define dso_local [2 x i32] @f_ret_float16_int32_s
1716 // ILP32-SAME: () #[[ATTR0]] {
1717 // ILP32:  entry:
1718 //
1719 // ILP32F-ILP32D-LABEL: define dso_local { half, i32 } @f_ret_float16_int32_s
1720 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1721 // ILP32F-ILP32D:  entry:
1722 //
f_ret_float16_int32_s(void)1723 struct float16_int32_s f_ret_float16_int32_s(void) {
1724   return (struct float16_int32_s){1.0, 2};
1725 }
1726 
1727 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64_s_arg
1728 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
1729 // ILP32-ILP32F-ILP32D:  entry:
1730 //
f_float16_int64_s_arg(struct float16_int64_s a)1731 void f_float16_int64_s_arg(struct float16_int64_s a) {}
1732 
1733 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float16_int64_s
1734 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
1735 // ILP32-ILP32F-ILP32D:  entry:
1736 //
f_ret_float16_int64_s(void)1737 struct float16_int64_s f_ret_float16_int64_s(void) {
1738   return (struct float16_int64_s){1.0, 2};
1739 }
1740 
1741 // ILP32-LABEL: define dso_local void @f_float16_int64bf_s_arg
1742 // ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
1743 // ILP32:  entry:
1744 //
1745 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64bf_s_arg
1746 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
1747 // ILP32F-ILP32D:  entry:
1748 //
f_float16_int64bf_s_arg(struct float16_int64bf_s a)1749 void f_float16_int64bf_s_arg(struct float16_int64bf_s a) {}
1750 
1751 // ILP32-LABEL: define dso_local i64 @f_ret_float16_int64bf_s
1752 // ILP32-SAME: () #[[ATTR0]] {
1753 // ILP32:  entry:
1754 //
1755 // ILP32F-ILP32D-LABEL: define dso_local <{ half, i32 }> @f_ret_float16_int64bf_s
1756 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1757 // ILP32F-ILP32D:  entry:
1758 //
f_ret_float16_int64bf_s(void)1759 struct float16_int64bf_s f_ret_float16_int64bf_s(void) {
1760   return (struct float16_int64bf_s){1.0, 2};
1761 }
1762 
1763 // The zero-width bitfield means the struct can't be passed according to the
1764 // floating point calling convention.
1765 
1766 // ILP32-LABEL: define dso_local void @f_float16_int8_zbf_s
1767 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1768 // ILP32:  entry:
1769 //
1770 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_zbf_s
1771 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {
1772 // ILP32F-ILP32D:  entry:
1773 //
f_float16_int8_zbf_s(struct float16_int8_zbf_s a)1774 void f_float16_int8_zbf_s(struct float16_int8_zbf_s a) {}
1775 
1776 // ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_zbf_s
1777 // ILP32-SAME: () #[[ATTR0]] {
1778 // ILP32:  entry:
1779 //
1780 // ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_zbf_s
1781 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1782 // ILP32F-ILP32D:  entry:
1783 //
f_ret_float16_int8_zbf_s(void)1784 struct float16_int8_zbf_s f_ret_float16_int8_zbf_s(void) {
1785   return (struct float16_int8_zbf_s){1.0, 2};
1786 }
1787 
1788 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_s_arg_insufficient_gprs
1789 // 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]] {
1790 // ILP32-ILP32F-ILP32D:  entry:
1791 //
f_float16_int8_s_arg_insufficient_gprs(int a,int b,int c,int d,int e,int f,int g,int h,struct float16_int8_s i)1792 void f_float16_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,
1793                                             int f, int g, int h, struct float16_int8_s i) {}
1794 
1795 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs
1796 // 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]] {
1797 // ILP32-ILP32F-ILP32D:  entry:
1798 //
f_struct_float16_int8_insufficient_fprs(float a,double b,double c,double d,double e,double f,double g,double h,struct float16_int8_s i)1799 void f_struct_float16_int8_insufficient_fprs(float a, double b, double c, double d,
1800                                              double e, double f, double g, double h, struct float16_int8_s i) {}
1801 
1802 // Complex floating-point values or structs containing a single complex
1803 // floating-point value should be passed as if it were an fp+fp struct.
1804 
1805 // ILP32-LABEL: define dso_local void @f_float16complex
1806 // ILP32-SAME: (i32 noundef [[A_COERCE:%.*]]) #[[ATTR0]] {
1807 // ILP32:  entry:
1808 //
1809 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex
1810 // ILP32F-ILP32D-SAME: (half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {
1811 // ILP32F-ILP32D:  entry:
1812 //
f_float16complex(_Float16 __complex__ a)1813 void f_float16complex(_Float16 __complex__ a) {}
1814 
1815 // ILP32-LABEL: define dso_local i32 @f_ret_float16complex
1816 // ILP32-SAME: () #[[ATTR0]] {
1817 // ILP32:  entry:
1818 //
1819 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex
1820 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1821 // ILP32F-ILP32D:  entry:
1822 //
f_ret_float16complex(void)1823 _Float16 __complex__ f_ret_float16complex(void) {
1824   return 1.0;
1825 }
1826 
1827 struct float16complex_s { _Float16 __complex__ c; };
1828 
1829 // ILP32-LABEL: define dso_local void @f_float16complex_s_arg
1830 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1831 // ILP32:  entry:
1832 //
1833 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex_s_arg
1834 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1835 // ILP32F-ILP32D:  entry:
1836 //
f_float16complex_s_arg(struct float16complex_s a)1837 void f_float16complex_s_arg(struct float16complex_s a) {}
1838 
1839 // ILP32-LABEL: define dso_local i32 @f_ret_float16complex_s
1840 // ILP32-SAME: () #[[ATTR0]] {
1841 // ILP32:  entry:
1842 //
1843 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex_s
1844 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1845 // ILP32F-ILP32D:  entry:
1846 //
f_ret_float16complex_s(void)1847 struct float16complex_s f_ret_float16complex_s(void) {
1848   return (struct float16complex_s){1.0};
1849 }
1850 
1851 // Test single or two-element structs that need flattening. e.g. those
1852 // containing nested structs, _Float16 in small arrays, zero-length structs etc.
1853 
1854 struct float16arr1_s { _Float16 a[1]; };
1855 
1856 // ILP32-LABEL: define dso_local void @f_float16arr1_s_arg
1857 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1858 // ILP32:  entry:
1859 //
1860 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr1_s_arg
1861 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {
1862 // ILP32F-ILP32D:  entry:
1863 //
f_float16arr1_s_arg(struct float16arr1_s a)1864 void f_float16arr1_s_arg(struct float16arr1_s a) {}
1865 
1866 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr1_s
1867 // ILP32-SAME: () #[[ATTR0]] {
1868 // ILP32:  entry:
1869 //
1870 // ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16arr1_s
1871 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1872 // ILP32F-ILP32D:  entry:
1873 //
f_ret_float16arr1_s(void)1874 struct float16arr1_s f_ret_float16arr1_s(void) {
1875   return (struct float16arr1_s){{1.0}};
1876 }
1877 
1878 struct float16arr2_s { _Float16 a[2]; };
1879 
1880 // ILP32-LABEL: define dso_local void @f_float16arr2_s_arg
1881 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1882 // ILP32:  entry:
1883 //
1884 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_s_arg
1885 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1886 // ILP32F-ILP32D:  entry:
1887 //
f_float16arr2_s_arg(struct float16arr2_s a)1888 void f_float16arr2_s_arg(struct float16arr2_s a) {}
1889 
1890 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_s
1891 // ILP32-SAME: () #[[ATTR0]] {
1892 // ILP32:  entry:
1893 //
1894 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_s
1895 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1896 // ILP32F-ILP32D:  entry:
1897 //
f_ret_float16arr2_s(void)1898 struct float16arr2_s f_ret_float16arr2_s(void) {
1899   return (struct float16arr2_s){{1.0, 2.0}};
1900 }
1901 
1902 struct float16arr2_tricky1_s { struct { _Float16 f[1]; } g[2]; };
1903 
1904 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1905 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1906 // ILP32:  entry:
1907 //
1908 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg
1909 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1910 // ILP32F-ILP32D:  entry:
1911 //
f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a)1912 void f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a) {}
1913 
1914 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky1_s
1915 // ILP32-SAME: () #[[ATTR0]] {
1916 // ILP32:  entry:
1917 //
1918 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky1_s
1919 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1920 // ILP32F-ILP32D:  entry:
1921 //
f_ret_float16arr2_tricky1_s(void)1922 struct float16arr2_tricky1_s f_ret_float16arr2_tricky1_s(void) {
1923   return (struct float16arr2_tricky1_s){{{{1.0}}, {{2.0}}}};
1924 }
1925 
1926 struct float16arr2_tricky2_s { struct {}; struct { _Float16 f[1]; } g[2]; };
1927 
1928 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1929 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1930 // ILP32:  entry:
1931 //
1932 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg
1933 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1934 // ILP32F-ILP32D:  entry:
1935 //
f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a)1936 void f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a) {}
1937 
1938 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky2_s
1939 // ILP32-SAME: () #[[ATTR0]] {
1940 // ILP32:  entry:
1941 //
1942 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky2_s
1943 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1944 // ILP32F-ILP32D:  entry:
1945 //
f_ret_float16arr2_tricky2_s(void)1946 struct float16arr2_tricky2_s f_ret_float16arr2_tricky2_s(void) {
1947   return (struct float16arr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
1948 }
1949 
1950 struct float16arr2_tricky3_s { union {}; struct { _Float16 f[1]; } g[2]; };
1951 
1952 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1953 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1954 // ILP32:  entry:
1955 //
1956 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg
1957 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1958 // ILP32F-ILP32D:  entry:
1959 //
f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a)1960 void f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a) {}
1961 
1962 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky3_s
1963 // ILP32-SAME: () #[[ATTR0]] {
1964 // ILP32:  entry:
1965 //
1966 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky3_s
1967 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1968 // ILP32F-ILP32D:  entry:
1969 //
f_ret_float16arr2_tricky3_s(void)1970 struct float16arr2_tricky3_s f_ret_float16arr2_tricky3_s(void) {
1971   return (struct float16arr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
1972 }
1973 
1974 struct float16arr2_tricky4_s { union {}; struct { struct {}; _Float16 f[1]; } g[2]; };
1975 
1976 // ILP32-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1977 // ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
1978 // ILP32:  entry:
1979 //
1980 // ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg
1981 // ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {
1982 // ILP32F-ILP32D:  entry:
1983 //
f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a)1984 void f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a) {}
1985 
1986 // ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky4_s
1987 // ILP32-SAME: () #[[ATTR0]] {
1988 // ILP32:  entry:
1989 //
1990 // ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky4_s
1991 // ILP32F-ILP32D-SAME: () #[[ATTR0]] {
1992 // ILP32F-ILP32D:  entry:
1993 //
f_ret_float16arr2_tricky4_s(void)1994 struct float16arr2_tricky4_s f_ret_float16arr2_tricky4_s(void) {
1995   return (struct float16arr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
1996 }
1997 
1998 // Test structs that should be passed according to the normal integer calling
1999 // convention.
2000 
2001 struct int_float16_int_s { int a; _Float16 b; int c; };
2002 
2003 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float16_int_s_arg
2004 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
2005 // ILP32-ILP32F-ILP32D:  entry:
2006 //
f_int_float16_int_s_arg(struct int_float16_int_s a)2007 void f_int_float16_int_s_arg(struct int_float16_int_s a) {}
2008 
2009 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float16_int_s
2010 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_FLOAT16_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
2011 // ILP32-ILP32F-ILP32D:  entry:
2012 //
f_ret_int_float16_int_s(void)2013 struct int_float16_int_s f_ret_int_float16_int_s(void) {
2014   return (struct int_float16_int_s){1, 2.0, 3};
2015 }
2016 
2017 struct int64_float16_s { int64_t a; _Float16 b; };
2018 
2019 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float16_s_arg
2020 // ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] {
2021 // ILP32-ILP32F-ILP32D:  entry:
2022 //
f_int64_float16_s_arg(struct int64_float16_s a)2023 void f_int64_float16_s_arg(struct int64_float16_s a) {}
2024 
2025 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float16_s
2026 // ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
2027 // ILP32-ILP32F-ILP32D:  entry:
2028 //
f_ret_int64_float16_s(void)2029 struct int64_float16_s f_ret_int64_float16_s(void) {
2030   return (struct int64_float16_s){1, 2.0};
2031 }
2032 
2033 struct char_char_float16_s { char a; char b; _Float16 c; };
2034 
2035 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_float16_s_arg
2036 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
2037 // ILP32-ILP32F-ILP32D:  entry:
2038 //
f_char_char_float16_s_arg(struct char_char_float16_s a)2039 void f_char_char_float16_s_arg(struct char_char_float16_s a) {}
2040 
2041 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_char_char_float16_s
2042 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
2043 // ILP32-ILP32F-ILP32D:  entry:
2044 //
f_ret_char_char_float16_s(void)2045 struct char_char_float16_s f_ret_char_char_float16_s(void) {
2046   return (struct char_char_float16_s){1, 2, 3.0};
2047 }
2048 
2049 // Unions are always passed according to the integer calling convention, even
2050 // if they can only contain a double.
2051 
2052 union float16_u { _Float16 a; };
2053 
2054 // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_u_arg
2055 // ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
2056 // ILP32-ILP32F-ILP32D:  entry:
2057 //
f_float16_u_arg(union float16_u a)2058 void f_float16_u_arg(union float16_u a) {}
2059 
2060 // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float16_u
2061 // ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {
2062 // ILP32-ILP32F-ILP32D:  entry:
2063 //
f_ret_float16_u(void)2064 union float16_u f_ret_float16_u(void) {
2065   return (union float16_u){1.0};
2066 }
2067 
2068 //// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
2069 // ILP32E: {{.*}}
2070 // ILP32F: {{.*}}
2071