2071 lines · c
1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 22// RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - \3// RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32-ILP32F,ILP32 %s4// 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 %s6// 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 %s8// RUN: %clang_cc1 -triple riscv32 -emit-llvm -target-abi ilp32e %s -o - \9// RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32-ILP32F,ILP32,ILP32E %s10 11#include <stddef.h>12#include <stdint.h>13 14// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_void15// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0:[0-9]+]] {16// ILP32-ILP32F-ILP32D: entry:17//18void f_void(void) {}19 20// Scalar arguments and return values smaller than the word size are extended21// according to the sign of their type, up to 32 bits22 23// ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i1 @f_scalar_024// ILP32-ILP32F-ILP32D-SAME: (i1 noundef zeroext [[X:%.*]]) #[[ATTR0]] {25// ILP32-ILP32F-ILP32D: entry:26//27_Bool f_scalar_0(_Bool x) { return x; }28 29// ILP32-ILP32F-ILP32D-LABEL: define dso_local signext i8 @f_scalar_130// ILP32-ILP32F-ILP32D-SAME: (i8 noundef signext [[X:%.*]]) #[[ATTR0]] {31// ILP32-ILP32F-ILP32D: entry:32//33int8_t f_scalar_1(int8_t x) { return x; }34 35// ILP32-ILP32F-ILP32D-LABEL: define dso_local zeroext i8 @f_scalar_236// ILP32-ILP32F-ILP32D-SAME: (i8 noundef zeroext [[X:%.*]]) #[[ATTR0]] {37// ILP32-ILP32F-ILP32D: entry:38//39uint8_t f_scalar_2(uint8_t x) { return x; }40 41// ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_342// ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X:%.*]]) #[[ATTR0]] {43// ILP32-ILP32F-ILP32D: entry:44//45int32_t f_scalar_3(int32_t x) { return x; }46 47// ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_scalar_448// ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X:%.*]]) #[[ATTR0]] {49// ILP32-ILP32F-ILP32D: entry:50//51int64_t f_scalar_4(int64_t x) { return x; }52 53// ILP32-ILP32F-ILP32D-LABEL: define dso_local float @f_fp_scalar_154// ILP32-ILP32F-ILP32D-SAME: (float noundef [[X:%.*]]) #[[ATTR0]] {55// ILP32-ILP32F-ILP32D: entry:56//57float f_fp_scalar_1(float x) { return x; }58 59// ILP32-ILP32F-ILP32D-LABEL: define dso_local double @f_fp_scalar_260// ILP32-ILP32F-ILP32D-SAME: (double noundef [[X:%.*]]) #[[ATTR0]] {61// ILP32-ILP32F-ILP32D: entry:62//63double f_fp_scalar_2(double x) { return x; }64 65// Scalars larger than 2*xlen are passed/returned indirect. However, the66// RISC-V LLVM backend can handle this fine, so the function doesn't need to67// be modified.68 69// ILP32-ILP32F-ILP32D-LABEL: define dso_local fp128 @f_fp_scalar_370// ILP32-ILP32F-ILP32D-SAME: (fp128 noundef [[X:%.*]]) #[[ATTR0]] {71// ILP32-ILP32F-ILP32D: entry:72//73long double f_fp_scalar_3(long double x) { return x; }74 75// ILP32-ILP32F-ILP32D-LABEL: define dso_local half @f_fp_scalar_476// ILP32-ILP32F-ILP32D-SAME: (half noundef [[X:%.*]]) #[[ATTR0]] {77// ILP32-ILP32F-ILP32D: entry:78//79_Float16 f_fp_scalar_4(_Float16 x) { return x; }80 81// Empty structs or unions are ignored.82 83struct empty_s {};84 85// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_struct86// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {87// ILP32-ILP32F-ILP32D: entry:88//89struct empty_s f_agg_empty_struct(struct empty_s x) {90 return x;91}92 93union empty_u {};94 95// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_empty_union96// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {97// ILP32-ILP32F-ILP32D: entry:98//99union 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 to104// integer arguments. The rules for return are the same.105 106struct tiny {107 uint8_t a, b, c, d;108};109 110// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_tiny111// ILP32-ILP32F-ILP32D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] {112// ILP32-ILP32F-ILP32D: entry:113//114void 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_ret120// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {121// ILP32-ILP32F-ILP32D: entry:122//123struct tiny f_agg_tiny_ret(void) {124 return (struct tiny){1, 2, 3, 4};125}126 127typedef uint8_t v4i8 __attribute__((vector_size(4)));128typedef int32_t v1i32 __attribute__((vector_size(4)));129 130// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_tiny_v4i8131// ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {132// ILP32-ILP32F-ILP32D: entry:133//134void 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_ret140// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {141// ILP32-ILP32F-ILP32D: entry:142//143v4i8 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_v1i32148// ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {149// ILP32-ILP32F-ILP32D: entry:150//151void 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_ret156// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {157// ILP32-ILP32F-ILP32D: entry:158//159v1i32 f_vec_tiny_v1i32_ret(void) {160 return (v1i32){1};161}162 163struct small {164 int32_t a, *b;165};166 167// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small168// ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[X_COERCE:%.*]]) #[[ATTR0]] {169// ILP32-ILP32F-ILP32D: entry:170//171void 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_ret177// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {178// ILP32-ILP32F-ILP32D: entry:179//180struct small f_agg_small_ret(void) {181 return (struct small){1, 0};182}183 184typedef uint8_t v8i8 __attribute__((vector_size(8)));185typedef int64_t v1i64 __attribute__((vector_size(8)));186 187// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_small_v8i8188// ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {189// ILP32-ILP32F-ILP32D: entry:190//191void 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_ret196// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {197// ILP32-ILP32F-ILP32D: entry:198//199v8i8 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_v1i64204// ILP32-ILP32F-ILP32D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {205// ILP32-ILP32F-ILP32D: entry:206//207void 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_ret212// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {213// ILP32-ILP32F-ILP32D: entry:214//215v1i64 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 a220// single 2*xlen-sized argument, to ensure that alignment can be maintained if221// passed on the stack.222 223struct small_aligned {224 int64_t a;225};226 227// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_small_aligned228// ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {229// ILP32-ILP32F-ILP32D: entry:230//231void 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_ret236// ILP32-ILP32F-ILP32D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {237// ILP32-ILP32F-ILP32D: entry:238//239struct 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 indirectly244struct large {245 int32_t a, b, c, d;246};247 248// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large249// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[X:%.*]]) #[[ATTR0]] {250// ILP32-ILP32F-ILP32D: entry:251//252void 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 first257// argument258// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large_ret259// 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//262struct large f_agg_large_ret(int32_t i, int8_t j) {263 return (struct large){1, 2, 3, 4};264}265 266typedef unsigned char v16i8 __attribute__((vector_size(16)));267 268// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8269// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[TMP0:%.*]]) #[[ATTR0]] {270// ILP32-ILP32F-ILP32D: entry:271//272void 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_ret277// 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//280v16i8 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 as285// if they were passed in registers.286 287// ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_1288// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]], [2 x i32] [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], ptr dead_on_return 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//291int 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_2297// 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//300struct 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_3306// 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//309long 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 as315// they would be if passed via registers.316 317// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_4318// 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//321void 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_5325// 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//328int 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_6334// 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//337struct 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 as343// they would be if passed via registers.344 345// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_stack346// 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 dead_on_return noundef [[H:%.*]]) #[[ATTR0]] {347// ILP32-ILP32F-ILP32D: entry:348//349void 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_tracking353// 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//356void 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 360struct double_s { double d; };361 362struct double_double_s { double d; double e; };363 364struct double_int8_s { double d; int64_t i; };365 366struct int_double_s { int a; double b; };367 368// ILP32-ILP32F-LABEL: define dso_local void @f_int_double_s_arg369// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {370// ILP32-ILP32F: entry:371//372// ILP32D-LABEL: define dso_local void @f_int_double_s_arg373// ILP32D-SAME: (i32 [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {374// ILP32D: entry:375//376void f_int_double_s_arg(struct int_double_s a) {}377 378// ILP32-ILP32F-LABEL: define dso_local void @f_ret_int_double_s379// 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_s383// ILP32D-SAME: () #[[ATTR0]] {384// ILP32D: entry:385//386struct 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_tracking2391// 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//394void 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 will398// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are399// available the widths are <= XLEN and FLEN, and should be expanded to400// 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 IR402// functions cannot return multiple values).403 404// A struct containing just one floating-point real is passed as though it405// were a standalone floating-point real.406 407// ILP32-ILP32F-LABEL: define dso_local void @f_double_s_arg408// ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {409// ILP32-ILP32F: entry:410//411// ILP32D-LABEL: define dso_local void @f_double_s_arg412// ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {413// ILP32D: entry:414//415void f_double_s_arg(struct double_s a) {}416 417// ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_double_s418// ILP32-ILP32F-SAME: () #[[ATTR0]] {419// ILP32-ILP32F: entry:420//421// ILP32D-LABEL: define dso_local double @f_ret_double_s422// ILP32D-SAME: () #[[ATTR0]] {423// ILP32D: entry:424//425struct 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 is430// passed as though it were a standalone floating-point real.431 432struct zbf_double_s { int : 0; double f; };433struct zbf_double_zbf_s { int : 0; double f; int : 0; };434 435// ILP32-ILP32F-LABEL: define dso_local void @f_zbf_double_s_arg436// ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {437// ILP32-ILP32F: entry:438//439// ILP32D-LABEL: define dso_local void @f_zbf_double_s_arg440// ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {441// ILP32D: entry:442//443void f_zbf_double_s_arg(struct zbf_double_s a) {}444 445// ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_zbf_double_s446// ILP32-ILP32F-SAME: () #[[ATTR0]] {447// ILP32-ILP32F: entry:448//449// ILP32D-LABEL: define dso_local double @f_ret_zbf_double_s450// ILP32D-SAME: () #[[ATTR0]] {451// ILP32D: entry:452//453struct 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_arg458// ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {459// ILP32-ILP32F: entry:460//461// ILP32D-LABEL: define dso_local void @f_zbf_double_zbf_s_arg462// ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {463// ILP32D: entry:464//465void 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_s468// ILP32-ILP32F-SAME: () #[[ATTR0]] {469// ILP32-ILP32F: entry:470//471// ILP32D-LABEL: define dso_local double @f_ret_zbf_double_zbf_s472// ILP32D-SAME: () #[[ATTR0]] {473// ILP32D: entry:474//475struct 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) are480// expanded provided sufficient FPRs are available.481 482struct double_float_s { double f; float g; };483 484// ILP32-ILP32F-LABEL: define dso_local void @f_double_double_s_arg485// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {486// ILP32-ILP32F: entry:487//488// ILP32D-LABEL: define dso_local void @f_double_double_s_arg489// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {490// ILP32D: entry:491//492void f_double_double_s_arg(struct double_double_s a) {}493 494// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s495// 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_s499// ILP32D-SAME: () #[[ATTR0]] {500// ILP32D: entry:501//502struct 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_arg507// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {508// ILP32-ILP32F: entry:509//510// ILP32D-LABEL: define dso_local void @f_double_float_s_arg511// ILP32D-SAME: (double [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {512// ILP32D: entry:513//514void f_double_float_s_arg(struct double_float_s a) {}515 516// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float_s517// 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_s521// ILP32D-SAME: () #[[ATTR0]] {522// ILP32D: entry:523//524struct 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_fprs529// 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 dead_on_return noundef [[H:%.*]]) #[[ATTR0]] {530// ILP32-ILP32F-ILP32D: entry:531//532void 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, provided536// sufficient FPRs and GPRs are available. The integer components are neither537// sign or zero-extended.538 539struct double_uint8_s { double d; uint8_t i; };540struct double_int32_s { double d; int32_t i; };541struct double_int64_s { double d; int64_t i; };542struct double_int64bf_s { double d; int64_t i : 32; };543struct 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_arg546// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {547// ILP32-ILP32F-ILP32D: entry:548//549void f_double_int8_s_arg(struct double_int8_s a) {}550 551// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int8_s552// 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//555struct 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_arg560// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {561// ILP32-ILP32F: entry:562//563// ILP32D-LABEL: define dso_local void @f_double_uint8_s_arg564// ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {565// ILP32D: entry:566//567void f_double_uint8_s_arg(struct double_uint8_s a) {}568 569// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_uint8_s570// 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_s574// ILP32D-SAME: () #[[ATTR0]] {575// ILP32D: entry:576//577struct 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_arg582// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {583// ILP32-ILP32F: entry:584//585// ILP32D-LABEL: define dso_local void @f_double_int32_s_arg586// ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {587// ILP32D: entry:588//589void f_double_int32_s_arg(struct double_int32_s a) {}590 591// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s592// 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_s596// ILP32D-SAME: () #[[ATTR0]] {597// ILP32D: entry:598//599struct 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_arg604// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {605// ILP32-ILP32F-ILP32D: entry:606//607void f_double_int64_s_arg(struct double_int64_s a) {}608 609// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int64_s610// 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//613struct 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_arg618// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {619// ILP32-ILP32F: entry:620//621// ILP32D-LABEL: define dso_local void @f_double_int64bf_s_arg622// ILP32D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {623// ILP32D: entry:624//625void f_double_int64bf_s_arg(struct double_int64bf_s a) {}626 627// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int64bf_s628// 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_s632// ILP32D-SAME: () #[[ATTR0]] {633// ILP32D: entry:634//635struct 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 the640// floating point calling convention.641 642// ILP32-ILP32F-LABEL: define dso_local void @f_double_int8_zbf_s643// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {644// ILP32-ILP32F: entry:645//646// ILP32D-LABEL: define dso_local void @f_double_int8_zbf_s647// ILP32D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {648// ILP32D: entry:649//650void 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_s653// 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_s657// ILP32D-SAME: () #[[ATTR0]] {658// ILP32D: entry:659//660struct 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_gprs665// 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 dead_on_return noundef [[I:%.*]]) #[[ATTR0]] {666// ILP32-ILP32F-ILP32D: entry:667//668void 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_fprs672// 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 dead_on_return noundef [[I:%.*]]) #[[ATTR0]] {673// ILP32-ILP32F-ILP32D: entry:674//675void 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 complex679// floating-point value should be passed as if it were an fp+fp struct.680 681// ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex682// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {683// ILP32-ILP32F: entry:684//685// ILP32D-LABEL: define dso_local void @f_doublecomplex686// ILP32D-SAME: (double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {687// ILP32D: entry:688//689void f_doublecomplex(double __complex__ a) {}690 691// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex692// 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_doublecomplex696// ILP32D-SAME: () #[[ATTR0]] {697// ILP32D: entry:698//699double __complex__ f_ret_doublecomplex(void) {700 return 1.0;701}702 703struct doublecomplex_s { double __complex__ c; };704 705// ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex_s_arg706// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {707// ILP32-ILP32F: entry:708//709// ILP32D-LABEL: define dso_local void @f_doublecomplex_s_arg710// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {711// ILP32D: entry:712//713void f_doublecomplex_s_arg(struct doublecomplex_s a) {}714 715// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_s716// 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_s720// ILP32D-SAME: () #[[ATTR0]] {721// ILP32D: entry:722//723struct 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. those728// containing nested structs, doubles in small arrays, zero-length structs etc.729 730struct doublearr1_s { double a[1]; };731 732// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr1_s_arg733// ILP32-ILP32F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {734// ILP32-ILP32F: entry:735//736// ILP32D-LABEL: define dso_local void @f_doublearr1_s_arg737// ILP32D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {738// ILP32D: entry:739//740void f_doublearr1_s_arg(struct doublearr1_s a) {}741 742// ILP32-ILP32F-LABEL: define dso_local i64 @f_ret_doublearr1_s743// ILP32-ILP32F-SAME: () #[[ATTR0]] {744// ILP32-ILP32F: entry:745//746// ILP32D-LABEL: define dso_local double @f_ret_doublearr1_s747// ILP32D-SAME: () #[[ATTR0]] {748// ILP32D: entry:749//750struct doublearr1_s f_ret_doublearr1_s(void) {751 return (struct doublearr1_s){{1.0}};752}753 754struct doublearr2_s { double a[2]; };755 756// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_s_arg757// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {758// ILP32-ILP32F: entry:759//760// ILP32D-LABEL: define dso_local void @f_doublearr2_s_arg761// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {762// ILP32D: entry:763//764void f_doublearr2_s_arg(struct doublearr2_s a) {}765 766// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_s767// 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_s771// ILP32D-SAME: () #[[ATTR0]] {772// ILP32D: entry:773//774struct doublearr2_s f_ret_doublearr2_s(void) {775 return (struct doublearr2_s){{1.0, 2.0}};776}777 778struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; };779 780// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg781// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {782// ILP32-ILP32F: entry:783//784// ILP32D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg785// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {786// ILP32D: entry:787//788void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}789 790// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky1_s791// 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_s795// ILP32D-SAME: () #[[ATTR0]] {796// ILP32D: entry:797//798struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {799 return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};800}801 802struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; };803 804// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg805// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {806// ILP32-ILP32F: entry:807//808// ILP32D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg809// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {810// ILP32D: entry:811//812void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}813 814// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky2_s815// 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_s819// ILP32D-SAME: () #[[ATTR0]] {820// ILP32D: entry:821//822struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {823 return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};824}825 826struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; };827 828// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg829// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {830// ILP32-ILP32F: entry:831//832// ILP32D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg833// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {834// ILP32D: entry:835//836void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}837 838// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky3_s839// 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_s843// ILP32D-SAME: () #[[ATTR0]] {844// ILP32D: entry:845//846struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {847 return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};848}849 850struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; };851 852// ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg853// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {854// ILP32-ILP32F: entry:855//856// ILP32D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg857// ILP32D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {858// ILP32D: entry:859//860void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}861 862// ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky4_s863// 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_s867// ILP32D-SAME: () #[[ATTR0]] {868// ILP32D: entry:869//870struct 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 calling875// convention.876 877struct 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_arg880// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {881// ILP32-ILP32F-ILP32D: entry:882//883void 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_s886// 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//889struct int_double_int_s f_ret_int_double_int_s(void) {890 return (struct int_double_int_s){1, 2.0, 3};891}892 893struct int64_double_s { int64_t a; double b; };894 895// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_double_s_arg896// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {897// ILP32-ILP32F-ILP32D: entry:898//899void f_int64_double_s_arg(struct int64_double_s a) {}900 901// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_double_s902// 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//905struct int64_double_s f_ret_int64_double_s(void) {906 return (struct int64_double_s){1, 2.0};907}908 909struct 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_arg912// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {913// ILP32-ILP32F-ILP32D: entry:914//915void 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_s918// 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//921struct 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, even926// if they can only contain a double.927 928union double_u { double a; };929 930// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_u_arg931// ILP32-ILP32F-ILP32D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {932// ILP32-ILP32F-ILP32D: entry:933//934void f_double_u_arg(union double_u a) {}935 936// ILP32-ILP32F-ILP32D-LABEL: define dso_local i64 @f_ret_double_u937// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {938// ILP32-ILP32F-ILP32D: entry:939//940union 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 will945// be returned indirectly and thus have an off-by-one error for the number of946// GPRs available (this is an edge case when structs > 2*XLEN are still947// returned in registers). This includes complex doubles, which are treated as948// 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_gprs951// 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 dead_on_return 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_gprs955// 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//958struct 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_gprs964// 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 dead_on_return 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_gprs968// 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//971struct 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_gprs977// 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 dead_on_return noundef [[H:%.*]]) #[[ATTR0]] {978// ILP32-ILP32F: entry:979//980// ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs981// 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//984double __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_3990// 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//993void 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 will997// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are998// available the widths are <= XLEN and FLEN, and should be expanded to999// 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 IR1001// functions cannot return multiple values).1002 1003// A struct containing just one floating-point real is passed as though it1004// were a standalone floating-point real.1005 1006struct float_s { float f; };1007 1008// ILP32-LABEL: define dso_local void @f_float_s_arg1009// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1010// ILP32: entry:1011//1012// ILP32F-ILP32D-LABEL: define dso_local void @f_float_s_arg1013// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {1014// ILP32F-ILP32D: entry:1015//1016void f_float_s_arg(struct float_s a) {}1017 1018// ILP32-LABEL: define dso_local i32 @f_ret_float_s1019// ILP32-SAME: () #[[ATTR0]] {1020// ILP32: entry:1021//1022// ILP32F-ILP32D-LABEL: define dso_local float @f_ret_float_s1023// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1024// ILP32F-ILP32D: entry:1025//1026struct 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 is1031// passed as though it were a standalone floating-point real.1032 1033struct zbf_float_s { int : 0; float f; };1034struct zbf_float_zbf_s { int : 0; float f; int : 0; };1035 1036// ILP32-LABEL: define dso_local void @f_zbf_float_s_arg1037// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1038// ILP32: entry:1039//1040// ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_s_arg1041// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {1042// ILP32F-ILP32D: entry:1043//1044void f_zbf_float_s_arg(struct zbf_float_s a) {}1045 1046// ILP32-LABEL: define dso_local i32 @f_ret_zbf_float_s1047// ILP32-SAME: () #[[ATTR0]] {1048// ILP32: entry:1049//1050// ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_s1051// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1052// ILP32F-ILP32D: entry:1053//1054struct 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_arg1059// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1060// ILP32: entry:1061//1062// ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float_zbf_s_arg1063// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {1064// ILP32F-ILP32D: entry:1065//1066void 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_s1069// ILP32-SAME: () #[[ATTR0]] {1070// ILP32: entry:1071//1072// ILP32F-ILP32D-LABEL: define dso_local float @f_ret_zbf_float_zbf_s1073// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1074// ILP32F-ILP32D: entry:1075//1076struct 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 expanded1081// provided sufficient FPRs are available.1082 1083struct float_float_s { float f; float g; };1084 1085// ILP32-LABEL: define dso_local void @f_float_float_s_arg1086// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1087// ILP32: entry:1088//1089// ILP32F-ILP32D-LABEL: define dso_local void @f_float_float_s_arg1090// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1091// ILP32F-ILP32D: entry:1092//1093void f_float_float_s_arg(struct float_float_s a) {}1094 1095// ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_float_s1096// ILP32-SAME: () #[[ATTR0]] {1097// ILP32: entry:1098//1099// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_float_float_s1100// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1101// ILP32F-ILP32D: entry:1102//1103struct 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_fprs1108// 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//1111void 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, provided1115// sufficient FPRs and GPRs are available. The integer components are neither1116// sign or zero-extended.1117 1118struct float_int8_s { float f; int8_t i; };1119struct float_uint8_s { float f; uint8_t i; };1120struct float_int32_s { float f; int32_t i; };1121struct float_int64_s { float f; int64_t i; };1122struct float_int64bf_s { float f; int64_t i : 32; };1123struct float_int8_zbf_s { float f; int8_t i; int : 0; };1124 1125// ILP32-LABEL: define dso_local void @f_float_int8_s_arg1126// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1127// ILP32: entry:1128//1129// ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_s_arg1130// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1131// ILP32F-ILP32D: entry:1132//1133void f_float_int8_s_arg(struct float_int8_s a) {}1134 1135// ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int8_s1136// ILP32-SAME: () #[[ATTR0]] {1137// ILP32: entry:1138//1139// ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_s1140// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1141// ILP32F-ILP32D: entry:1142//1143struct 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_arg1148// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1149// ILP32: entry:1150//1151// ILP32F-ILP32D-LABEL: define dso_local void @f_float_uint8_s_arg1152// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1153// ILP32F-ILP32D: entry:1154//1155void f_float_uint8_s_arg(struct float_uint8_s a) {}1156 1157// ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_uint8_s1158// ILP32-SAME: () #[[ATTR0]] {1159// ILP32: entry:1160//1161// ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_uint8_s1162// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1163// ILP32F-ILP32D: entry:1164//1165struct 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_arg1170// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1171// ILP32: entry:1172//1173// ILP32F-ILP32D-LABEL: define dso_local void @f_float_int32_s_arg1174// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1175// ILP32F-ILP32D: entry:1176//1177void f_float_int32_s_arg(struct float_int32_s a) {}1178 1179// ILP32-LABEL: define dso_local [2 x i32] @f_ret_float_int32_s1180// ILP32-SAME: () #[[ATTR0]] {1181// ILP32: entry:1182//1183// ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int32_s1184// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1185// ILP32F-ILP32D: entry:1186//1187struct 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_arg1192// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1193// ILP32-ILP32F-ILP32D: entry:1194//1195void f_float_int64_s_arg(struct float_int64_s a) {}1196 1197// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float_int64_s1198// 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//1201struct 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_arg1206// ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1207// ILP32: entry:1208//1209// ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64bf_s_arg1210// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1211// ILP32F-ILP32D: entry:1212//1213void f_float_int64bf_s_arg(struct float_int64bf_s a) {}1214 1215// ILP32-LABEL: define dso_local i64 @f_ret_float_int64bf_s1216// ILP32-SAME: () #[[ATTR0]] {1217// ILP32: entry:1218//1219// ILP32F-ILP32D-LABEL: define dso_local { float, i32 } @f_ret_float_int64bf_s1220// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1221// ILP32F-ILP32D: entry:1222//1223struct 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 the1228// floating point calling convention.1229 1230// ILP32-LABEL: define dso_local void @f_float_int8_zbf_s1231// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1232// ILP32: entry:1233//1234// ILP32F-ILP32D-LABEL: define dso_local void @f_float_int8_zbf_s1235// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1236// ILP32F-ILP32D: entry:1237//1238void 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_s1241// ILP32-SAME: () #[[ATTR0]] {1242// ILP32: entry:1243//1244// ILP32F-ILP32D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_zbf_s1245// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1246// ILP32F-ILP32D: entry:1247//1248struct 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_gprs1253// 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//1256void 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_fprs1260// 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//1263void 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 complex1267// floating-point value should be passed as if it were an fp+fp struct.1268 1269// ILP32-LABEL: define dso_local void @f_floatcomplex1270// ILP32-SAME: ([2 x i32] noundef [[A_COERCE:%.*]]) #[[ATTR0]] {1271// ILP32: entry:1272//1273// ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex1274// ILP32F-ILP32D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {1275// ILP32F-ILP32D: entry:1276//1277void f_floatcomplex(float __complex__ a) {}1278 1279// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex1280// ILP32-SAME: () #[[ATTR0]] {1281// ILP32: entry:1282//1283// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex1284// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1285// ILP32F-ILP32D: entry:1286//1287float __complex__ f_ret_floatcomplex(void) {1288 return 1.0;1289}1290 1291struct floatcomplex_s { float __complex__ c; };1292 1293// ILP32-LABEL: define dso_local void @f_floatcomplex_s_arg1294// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1295// ILP32: entry:1296//1297// ILP32F-ILP32D-LABEL: define dso_local void @f_floatcomplex_s_arg1298// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1299// ILP32F-ILP32D: entry:1300//1301void f_floatcomplex_s_arg(struct floatcomplex_s a) {}1302 1303// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatcomplex_s1304// ILP32-SAME: () #[[ATTR0]] {1305// ILP32: entry:1306//1307// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatcomplex_s1308// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1309// ILP32F-ILP32D: entry:1310//1311struct 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. those1316// containing nested structs, floats in small arrays, zero-length structs etc.1317 1318struct floatarr1_s { float a[1]; };1319 1320// ILP32-LABEL: define dso_local void @f_floatarr1_s_arg1321// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1322// ILP32: entry:1323//1324// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr1_s_arg1325// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {1326// ILP32F-ILP32D: entry:1327//1328void f_floatarr1_s_arg(struct floatarr1_s a) {}1329 1330// ILP32-LABEL: define dso_local i32 @f_ret_floatarr1_s1331// ILP32-SAME: () #[[ATTR0]] {1332// ILP32: entry:1333//1334// ILP32F-ILP32D-LABEL: define dso_local float @f_ret_floatarr1_s1335// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1336// ILP32F-ILP32D: entry:1337//1338struct floatarr1_s f_ret_floatarr1_s(void) {1339 return (struct floatarr1_s){{1.0}};1340}1341 1342struct floatarr2_s { float a[2]; };1343 1344// ILP32-LABEL: define dso_local void @f_floatarr2_s_arg1345// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1346// ILP32: entry:1347//1348// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_s_arg1349// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1350// ILP32F-ILP32D: entry:1351//1352void f_floatarr2_s_arg(struct floatarr2_s a) {}1353 1354// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_s1355// ILP32-SAME: () #[[ATTR0]] {1356// ILP32: entry:1357//1358// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_s1359// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1360// ILP32F-ILP32D: entry:1361//1362struct floatarr2_s f_ret_floatarr2_s(void) {1363 return (struct floatarr2_s){{1.0, 2.0}};1364}1365 1366struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; };1367 1368// ILP32-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg1369// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1370// ILP32: entry:1371//1372// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg1373// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1374// ILP32F-ILP32D: entry:1375//1376void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {}1377 1378// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky1_s1379// ILP32-SAME: () #[[ATTR0]] {1380// ILP32: entry:1381//1382// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky1_s1383// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1384// ILP32F-ILP32D: entry:1385//1386struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s(void) {1387 return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}};1388}1389 1390struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; };1391 1392// ILP32-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg1393// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1394// ILP32: entry:1395//1396// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg1397// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1398// ILP32F-ILP32D: entry:1399//1400void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {}1401 1402// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky2_s1403// ILP32-SAME: () #[[ATTR0]] {1404// ILP32: entry:1405//1406// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky2_s1407// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1408// ILP32F-ILP32D: entry:1409//1410struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s(void) {1411 return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};1412}1413 1414struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; };1415 1416// ILP32-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg1417// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1418// ILP32: entry:1419//1420// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg1421// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1422// ILP32F-ILP32D: entry:1423//1424void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {}1425 1426// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky3_s1427// ILP32-SAME: () #[[ATTR0]] {1428// ILP32: entry:1429//1430// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky3_s1431// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1432// ILP32F-ILP32D: entry:1433//1434struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s(void) {1435 return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};1436}1437 1438struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; };1439 1440// ILP32-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg1441// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1442// ILP32: entry:1443//1444// ILP32F-ILP32D-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg1445// ILP32F-ILP32D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1446// ILP32F-ILP32D: entry:1447//1448void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {}1449 1450// ILP32-LABEL: define dso_local [2 x i32] @f_ret_floatarr2_tricky4_s1451// ILP32-SAME: () #[[ATTR0]] {1452// ILP32: entry:1453//1454// ILP32F-ILP32D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky4_s1455// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1456// ILP32F-ILP32D: entry:1457//1458struct 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 calling1463// convention.1464 1465struct 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_arg1468// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1469// ILP32-ILP32F-ILP32D: entry:1470//1471void 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_s1474// 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//1477struct int_float_int_s f_ret_int_float_int_s(void) {1478 return (struct int_float_int_s){1, 2.0, 3};1479}1480 1481struct int64_float_s { int64_t a; float b; };1482 1483// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float_s_arg1484// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1485// ILP32-ILP32F-ILP32D: entry:1486//1487void f_int64_float_s_arg(struct int64_float_s a) {}1488 1489// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float_s1490// 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//1493struct int64_float_s f_ret_int64_float_s(void) {1494 return (struct int64_float_s){1, 2.0};1495}1496 1497struct 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_arg1500// ILP32-ILP32F-ILP32D-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1501// ILP32-ILP32F-ILP32D: entry:1502//1503void 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_s1506// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {1507// ILP32-ILP32F-ILP32D: entry:1508//1509struct 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, even1514// if they can only contain a float.1515 1516union float_u { float a; };1517 1518// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_u_arg1519// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1520// ILP32-ILP32F-ILP32D: entry:1521//1522void f_float_u_arg(union float_u a) {}1523 1524// ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float_u1525// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {1526// ILP32-ILP32F-ILP32D: entry:1527//1528union 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 will1533// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are1534// available the widths are <= XLEN and FLEN, and should be expanded to1535// 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 IR1537// functions cannot return multiple values).1538 1539struct float16_s { _Float16 f; };1540 1541// A struct containing just one floating-point real is passed as though it1542// were a standalone floating-point real.1543 1544// ILP32-LABEL: define dso_local void @f_float16_s_arg1545// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1546// ILP32: entry:1547//1548// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_s_arg1549// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1550// ILP32F-ILP32D: entry:1551//1552void f_float16_s_arg(struct float16_s a) {}1553 1554// ILP32-LABEL: define dso_local i32 @f_ret_float16_s1555// ILP32-SAME: () #[[ATTR0]] {1556// ILP32: entry:1557//1558// ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16_s1559// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1560// ILP32F-ILP32D: entry:1561//1562struct 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 is1567// passed as though it were a standalone floating-point real.1568 1569struct zbf_float16_s { int : 0; _Float16 f; };1570struct zbf_float16_zbf_s { int : 0; _Float16 f; int : 0; };1571 1572// ILP32-LABEL: define dso_local void @f_zbf_float16_s_arg1573// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1574// ILP32: entry:1575//1576// ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_s_arg1577// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1578// ILP32F-ILP32D: entry:1579//1580void f_zbf_float16_s_arg(struct zbf_float16_s a) {}1581 1582// ILP32-LABEL: define dso_local i32 @f_ret_zbf_float16_s1583// ILP32-SAME: () #[[ATTR0]] {1584// ILP32: entry:1585//1586// ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_s1587// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1588// ILP32F-ILP32D: entry:1589//1590struct 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_arg1595// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1596// ILP32: entry:1597//1598// ILP32F-ILP32D-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg1599// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1600// ILP32F-ILP32D: entry:1601//1602void 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_s1605// ILP32-SAME: () #[[ATTR0]] {1606// ILP32: entry:1607//1608// ILP32F-ILP32D-LABEL: define dso_local half @f_ret_zbf_float16_zbf_s1609// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1610// ILP32F-ILP32D: entry:1611//1612struct 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) are1617// expanded provided sufficient FPRs are available.1618 1619struct double_float16_s { double f; _Float16 g; };1620 1621// ILP32-ILP32F-LABEL: define dso_local void @f_double_float16_s_arg1622// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1623// ILP32-ILP32F: entry:1624//1625// ILP32D-LABEL: define dso_local void @f_double_float16_s_arg1626// ILP32D-SAME: (double [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1627// ILP32D: entry:1628//1629void f_double_float16_s_arg(struct double_float16_s a) {}1630 1631// ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float16_s1632// 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_s1636// ILP32D-SAME: () #[[ATTR0]] {1637// ILP32D: entry:1638//1639struct 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_fprs1644// 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 dead_on_return noundef [[H:%.*]]) #[[ATTR0]] {1645// ILP32-ILP32F-ILP32D: entry:1646//1647void 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, provided1651// sufficient FPRs and GPRs are available. The integer components are neither1652// sign or zero-extended.1653 1654struct float16_int8_s { _Float16 f; int8_t i; };1655struct float16_uint8_s { _Float16 f; uint8_t i; };1656struct float16_int32_s { _Float16 f; int32_t i; };1657struct float16_int64_s { _Float16 f; int64_t i; };1658struct float16_int64bf_s { _Float16 f; int64_t i : 32; };1659struct float16_int8_zbf_s { _Float16 f; int8_t i; int : 0; };1660 1661// ILP32-LABEL: define dso_local void @f_float16_int8_s_arg1662// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1663// ILP32: entry:1664//1665// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_s_arg1666// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1667// ILP32F-ILP32D: entry:1668//1669void f_float16_int8_s_arg(struct float16_int8_s a) {}1670 1671// ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_s1672// ILP32-SAME: () #[[ATTR0]] {1673// ILP32: entry:1674//1675// ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_s1676// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1677// ILP32F-ILP32D: entry:1678//1679struct 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_arg1684// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1685// ILP32: entry:1686//1687// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_uint8_s_arg1688// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1689// ILP32F-ILP32D: entry:1690//1691void f_float16_uint8_s_arg(struct float16_uint8_s a) {}1692 1693// ILP32-LABEL: define dso_local i32 @f_ret_float16_uint8_s1694// ILP32-SAME: () #[[ATTR0]] {1695// ILP32: entry:1696//1697// ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_uint8_s1698// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1699// ILP32F-ILP32D: entry:1700//1701struct 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_arg1706// ILP32-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {1707// ILP32: entry:1708//1709// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int32_s_arg1710// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1711// ILP32F-ILP32D: entry:1712//1713void f_float16_int32_s_arg(struct float16_int32_s a) {}1714 1715// ILP32-LABEL: define dso_local [2 x i32] @f_ret_float16_int32_s1716// ILP32-SAME: () #[[ATTR0]] {1717// ILP32: entry:1718//1719// ILP32F-ILP32D-LABEL: define dso_local { half, i32 } @f_ret_float16_int32_s1720// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1721// ILP32F-ILP32D: entry:1722//1723struct 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_arg1728// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1729// ILP32-ILP32F-ILP32D: entry:1730//1731void f_float16_int64_s_arg(struct float16_int64_s a) {}1732 1733// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float16_int64_s1734// 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//1737struct 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_arg1742// ILP32-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1743// ILP32: entry:1744//1745// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64bf_s_arg1746// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1747// ILP32F-ILP32D: entry:1748//1749void f_float16_int64bf_s_arg(struct float16_int64bf_s a) {}1750 1751// ILP32-LABEL: define dso_local i64 @f_ret_float16_int64bf_s1752// ILP32-SAME: () #[[ATTR0]] {1753// ILP32: entry:1754//1755// ILP32F-ILP32D-LABEL: define dso_local <{ half, i32 }> @f_ret_float16_int64bf_s1756// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1757// ILP32F-ILP32D: entry:1758//1759struct 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 the1764// floating point calling convention.1765 1766// ILP32-LABEL: define dso_local void @f_float16_int8_zbf_s1767// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1768// ILP32: entry:1769//1770// ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int8_zbf_s1771// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1772// ILP32F-ILP32D: entry:1773//1774void f_float16_int8_zbf_s(struct float16_int8_zbf_s a) {}1775 1776// ILP32-LABEL: define dso_local i32 @f_ret_float16_int8_zbf_s1777// ILP32-SAME: () #[[ATTR0]] {1778// ILP32: entry:1779//1780// ILP32F-ILP32D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_zbf_s1781// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1782// ILP32F-ILP32D: entry:1783//1784struct 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_gprs1789// 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//1792void 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_fprs1796// 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//1799void 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 complex1803// floating-point value should be passed as if it were an fp+fp struct.1804 1805// ILP32-LABEL: define dso_local void @f_float16complex1806// ILP32-SAME: (i32 noundef [[A_COERCE:%.*]]) #[[ATTR0]] {1807// ILP32: entry:1808//1809// ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex1810// ILP32F-ILP32D-SAME: (half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {1811// ILP32F-ILP32D: entry:1812//1813void f_float16complex(_Float16 __complex__ a) {}1814 1815// ILP32-LABEL: define dso_local i32 @f_ret_float16complex1816// ILP32-SAME: () #[[ATTR0]] {1817// ILP32: entry:1818//1819// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex1820// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1821// ILP32F-ILP32D: entry:1822//1823_Float16 __complex__ f_ret_float16complex(void) {1824 return 1.0;1825}1826 1827struct float16complex_s { _Float16 __complex__ c; };1828 1829// ILP32-LABEL: define dso_local void @f_float16complex_s_arg1830// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1831// ILP32: entry:1832//1833// ILP32F-ILP32D-LABEL: define dso_local void @f_float16complex_s_arg1834// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1835// ILP32F-ILP32D: entry:1836//1837void f_float16complex_s_arg(struct float16complex_s a) {}1838 1839// ILP32-LABEL: define dso_local i32 @f_ret_float16complex_s1840// ILP32-SAME: () #[[ATTR0]] {1841// ILP32: entry:1842//1843// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16complex_s1844// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1845// ILP32F-ILP32D: entry:1846//1847struct 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. those1852// containing nested structs, _Float16 in small arrays, zero-length structs etc.1853 1854struct float16arr1_s { _Float16 a[1]; };1855 1856// ILP32-LABEL: define dso_local void @f_float16arr1_s_arg1857// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1858// ILP32: entry:1859//1860// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr1_s_arg1861// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1862// ILP32F-ILP32D: entry:1863//1864void f_float16arr1_s_arg(struct float16arr1_s a) {}1865 1866// ILP32-LABEL: define dso_local i32 @f_ret_float16arr1_s1867// ILP32-SAME: () #[[ATTR0]] {1868// ILP32: entry:1869//1870// ILP32F-ILP32D-LABEL: define dso_local half @f_ret_float16arr1_s1871// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1872// ILP32F-ILP32D: entry:1873//1874struct float16arr1_s f_ret_float16arr1_s(void) {1875 return (struct float16arr1_s){{1.0}};1876}1877 1878struct float16arr2_s { _Float16 a[2]; };1879 1880// ILP32-LABEL: define dso_local void @f_float16arr2_s_arg1881// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1882// ILP32: entry:1883//1884// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_s_arg1885// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1886// ILP32F-ILP32D: entry:1887//1888void f_float16arr2_s_arg(struct float16arr2_s a) {}1889 1890// ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_s1891// ILP32-SAME: () #[[ATTR0]] {1892// ILP32: entry:1893//1894// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_s1895// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1896// ILP32F-ILP32D: entry:1897//1898struct float16arr2_s f_ret_float16arr2_s(void) {1899 return (struct float16arr2_s){{1.0, 2.0}};1900}1901 1902struct float16arr2_tricky1_s { struct { _Float16 f[1]; } g[2]; };1903 1904// ILP32-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg1905// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1906// ILP32: entry:1907//1908// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg1909// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1910// ILP32F-ILP32D: entry:1911//1912void f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a) {}1913 1914// ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky1_s1915// ILP32-SAME: () #[[ATTR0]] {1916// ILP32: entry:1917//1918// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky1_s1919// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1920// ILP32F-ILP32D: entry:1921//1922struct float16arr2_tricky1_s f_ret_float16arr2_tricky1_s(void) {1923 return (struct float16arr2_tricky1_s){{{{1.0}}, {{2.0}}}};1924}1925 1926struct float16arr2_tricky2_s { struct {}; struct { _Float16 f[1]; } g[2]; };1927 1928// ILP32-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg1929// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1930// ILP32: entry:1931//1932// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg1933// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1934// ILP32F-ILP32D: entry:1935//1936void f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a) {}1937 1938// ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky2_s1939// ILP32-SAME: () #[[ATTR0]] {1940// ILP32: entry:1941//1942// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky2_s1943// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1944// ILP32F-ILP32D: entry:1945//1946struct float16arr2_tricky2_s f_ret_float16arr2_tricky2_s(void) {1947 return (struct float16arr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};1948}1949 1950struct float16arr2_tricky3_s { union {}; struct { _Float16 f[1]; } g[2]; };1951 1952// ILP32-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg1953// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1954// ILP32: entry:1955//1956// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg1957// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1958// ILP32F-ILP32D: entry:1959//1960void f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a) {}1961 1962// ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky3_s1963// ILP32-SAME: () #[[ATTR0]] {1964// ILP32: entry:1965//1966// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky3_s1967// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1968// ILP32F-ILP32D: entry:1969//1970struct float16arr2_tricky3_s f_ret_float16arr2_tricky3_s(void) {1971 return (struct float16arr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};1972}1973 1974struct float16arr2_tricky4_s { union {}; struct { struct {}; _Float16 f[1]; } g[2]; };1975 1976// ILP32-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg1977// ILP32-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {1978// ILP32: entry:1979//1980// ILP32F-ILP32D-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg1981// ILP32F-ILP32D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1982// ILP32F-ILP32D: entry:1983//1984void f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a) {}1985 1986// ILP32-LABEL: define dso_local i32 @f_ret_float16arr2_tricky4_s1987// ILP32-SAME: () #[[ATTR0]] {1988// ILP32: entry:1989//1990// ILP32F-ILP32D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky4_s1991// ILP32F-ILP32D-SAME: () #[[ATTR0]] {1992// ILP32F-ILP32D: entry:1993//1994struct 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 calling1999// convention.2000 2001struct 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_arg2004// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {2005// ILP32-ILP32F-ILP32D: entry:2006//2007void 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_s2010// 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//2013struct int_float16_int_s f_ret_int_float16_int_s(void) {2014 return (struct int_float16_int_s){1, 2.0, 3};2015}2016 2017struct int64_float16_s { int64_t a; _Float16 b; };2018 2019// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float16_s_arg2020// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {2021// ILP32-ILP32F-ILP32D: entry:2022//2023void f_int64_float16_s_arg(struct int64_float16_s a) {}2024 2025// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float16_s2026// 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//2029struct int64_float16_s f_ret_int64_float16_s(void) {2030 return (struct int64_float16_s){1, 2.0};2031}2032 2033struct 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_arg2036// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {2037// ILP32-ILP32F-ILP32D: entry:2038//2039void 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_s2042// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {2043// ILP32-ILP32F-ILP32D: entry:2044//2045struct 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, even2050// if they can only contain a double.2051 2052union float16_u { _Float16 a; };2053 2054// ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_u_arg2055// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {2056// ILP32-ILP32F-ILP32D: entry:2057//2058void f_float16_u_arg(union float16_u a) {}2059 2060// ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ret_float16_u2061// ILP32-ILP32F-ILP32D-SAME: () #[[ATTR0]] {2062// ILP32-ILP32F-ILP32D: entry:2063//2064union 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