2053 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 riscv64 -emit-llvm %s -o - \3// RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64-LP64F,LP64 %s4// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \5// RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64F-LP64D,LP64-LP64F,LP64F %s6// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \7// RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64F-LP64D,LP64D %s8// RUN: %clang_cc1 -triple riscv64 -emit-llvm -target-abi lp64e %s -o - \9// RUN: | FileCheck -check-prefixes=LP64-LP64F-LP64D,LP64-LP64F,LP64,LP64E %s10 11#include <stddef.h>12#include <stdint.h>13 14// LP64-LP64F-LP64D-LABEL: define dso_local void @f_void15// LP64-LP64F-LP64D-SAME: () #[[ATTR0:[0-9]+]] {16// LP64-LP64F-LP64D: 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// LP64-LP64F-LP64D-LABEL: define dso_local zeroext i1 @f_scalar_024// LP64-LP64F-LP64D-SAME: (i1 noundef zeroext [[X:%.*]]) #[[ATTR0]] {25// LP64-LP64F-LP64D: entry:26//27_Bool f_scalar_0(_Bool x) { return x; }28 29// LP64-LP64F-LP64D-LABEL: define dso_local signext i8 @f_scalar_130// LP64-LP64F-LP64D-SAME: (i8 noundef signext [[X:%.*]]) #[[ATTR0]] {31// LP64-LP64F-LP64D: entry:32//33int8_t f_scalar_1(int8_t x) { return x; }34 35// LP64-LP64F-LP64D-LABEL: define dso_local zeroext i8 @f_scalar_236// LP64-LP64F-LP64D-SAME: (i8 noundef zeroext [[X:%.*]]) #[[ATTR0]] {37// LP64-LP64F-LP64D: entry:38//39uint8_t f_scalar_2(uint8_t x) { return x; }40 41// LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_342// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[X:%.*]]) #[[ATTR0]] {43// LP64-LP64F-LP64D: entry:44//45uint32_t f_scalar_3(int32_t x) { return x; }46 47// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_scalar_448// LP64-LP64F-LP64D-SAME: (i64 noundef [[X:%.*]]) #[[ATTR0]] {49// LP64-LP64F-LP64D: entry:50//51int64_t f_scalar_4(int64_t x) { return x; }52 53// LP64-LP64F-LP64D-LABEL: define dso_local float @f_fp_scalar_154// LP64-LP64F-LP64D-SAME: (float noundef [[X:%.*]]) #[[ATTR0]] {55// LP64-LP64F-LP64D: entry:56//57float f_fp_scalar_1(float x) { return x; }58 59// LP64-LP64F-LP64D-LABEL: define dso_local double @f_fp_scalar_260// LP64-LP64F-LP64D-SAME: (double noundef [[X:%.*]]) #[[ATTR0]] {61// LP64-LP64F-LP64D: entry:62//63double f_fp_scalar_2(double x) { return x; }64 65// LP64-LP64F-LP64D-LABEL: define dso_local fp128 @f_fp_scalar_366// LP64-LP64F-LP64D-SAME: (fp128 noundef [[X:%.*]]) #[[ATTR0]] {67// LP64-LP64F-LP64D: entry:68//69long double f_fp_scalar_3(long double x) { return x; }70 71// LP64-LP64F-LP64D-LABEL: define dso_local half @f_fp_scalar_472// LP64-LP64F-LP64D-SAME: (half noundef [[X:%.*]]) #[[ATTR0]] {73// LP64-LP64F-LP64D: entry:74//75_Float16 f_fp_scalar_4(_Float16 x) { return x; }76 77// Empty structs or unions are ignored.78 79struct empty_s {};80 81// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_empty_struct82// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {83// LP64-LP64F-LP64D: entry:84//85struct empty_s f_agg_empty_struct(struct empty_s x) {86 return x;87}88 89union empty_u {};90 91// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_empty_union92// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {93// LP64-LP64F-LP64D: entry:94//95union empty_u f_agg_empty_union(union empty_u x) {96 return x;97}98 99// Aggregates <= 2*xlen may be passed in registers, so will be coerced to100// integer arguments. The rules for return are the same.101 102struct tiny {103 uint16_t a, b, c, d;104};105 106// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_tiny107// LP64-LP64F-LP64D-SAME: (i64 [[X_COERCE:%.*]]) #[[ATTR0]] {108// LP64-LP64F-LP64D: entry:109//110void f_agg_tiny(struct tiny x) {111 x.a += x.b;112 x.c += x.d;113}114 115// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_agg_tiny_ret116// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {117// LP64-LP64F-LP64D: entry:118//119struct tiny f_agg_tiny_ret(void) {120 return (struct tiny){1, 2, 3, 4};121}122 123typedef uint16_t v4i16 __attribute__((vector_size(8)));124typedef int64_t v1i64 __attribute__((vector_size(8)));125 126// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_tiny_v4i16127// LP64-LP64F-LP64D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {128// LP64-LP64F-LP64D: entry:129//130void f_vec_tiny_v4i16(v4i16 x) {131 x[0] = x[1];132 x[2] = x[3];133}134 135// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_vec_tiny_v4i16_ret136// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {137// LP64-LP64F-LP64D: entry:138//139v4i16 f_vec_tiny_v4i16_ret(void) {140 return (v4i16){1, 2, 3, 4};141}142 143// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_tiny_v1i64144// LP64-LP64F-LP64D-SAME: (i64 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {145// LP64-LP64F-LP64D: entry:146//147void f_vec_tiny_v1i64(v1i64 x) {148 x[0] = 114;149}150 151// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_vec_tiny_v1i64_ret152// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {153// LP64-LP64F-LP64D: entry:154//155v1i64 f_vec_tiny_v1i64_ret(void) {156 return (v1i64){1};157}158 159struct small {160 int64_t a, *b;161};162 163// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_small164// LP64-LP64F-LP64D-SAME: ([2 x i64] [[X_COERCE:%.*]]) #[[ATTR0]] {165// LP64-LP64F-LP64D: entry:166//167void f_agg_small(struct small x) {168 x.a += *x.b;169 x.b = &x.a;170}171 172// LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_agg_small_ret173// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {174// LP64-LP64F-LP64D: entry:175//176struct small f_agg_small_ret(void) {177 return (struct small){1, 0};178}179 180typedef uint16_t v8i16 __attribute__((vector_size(16)));181typedef __int128_t v1i128 __attribute__((vector_size(16)));182 183// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_small_v8i16184// LP64-LP64F-LP64D-SAME: (i128 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {185// LP64-LP64F-LP64D: entry:186//187void f_vec_small_v8i16(v8i16 x) {188 x[0] = x[7];189}190 191// LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_vec_small_v8i16_ret192// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {193// LP64-LP64F-LP64D: entry:194//195v8i16 f_vec_small_v8i16_ret(void) {196 return (v8i16){1, 2, 3, 4, 5, 6, 7, 8};197}198 199// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_small_v1i128200// LP64-LP64F-LP64D-SAME: (i128 noundef [[X_COERCE:%.*]]) #[[ATTR0]] {201// LP64-LP64F-LP64D: entry:202//203void f_vec_small_v1i128(v1i128 x) {204 x[0] = 114;205}206 207// LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_vec_small_v1i128_ret208// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {209// LP64-LP64F-LP64D: entry:210//211v1i128 f_vec_small_v1i128_ret(void) {212 return (v1i128){1};213}214 215// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a216// single 2*xlen-sized argument, to ensure that alignment can be maintained if217// passed on the stack.218 219struct small_aligned {220 __int128_t a;221};222 223// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_small_aligned224// LP64-LP64F-LP64D-SAME: (i128 [[X_COERCE:%.*]]) #[[ATTR0]] {225// LP64-LP64F-LP64D: entry:226//227void f_agg_small_aligned(struct small_aligned x) {228 x.a += x.a;229}230 231// LP64-LP64F-LP64D-LABEL: define dso_local i128 @f_agg_small_aligned_ret232// LP64-LP64F-LP64D-SAME: (i128 [[X_COERCE:%.*]]) #[[ATTR0]] {233// LP64-LP64F-LP64D: entry:234//235struct small_aligned f_agg_small_aligned_ret(struct small_aligned x) {236 return (struct small_aligned){10};237}238 239// Aggregates greater > 2*xlen will be passed and returned indirectly240struct large {241 int64_t a, b, c, d;242};243 244// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large245// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[X:%.*]]) #[[ATTR0]] {246// LP64-LP64F-LP64D: entry:247//248void f_agg_large(struct large x) {249 x.a = x.b + x.c + x.d;250}251 252// The address where the struct should be written to will be the first253// argument254// LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large_ret255// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] {256// LP64-LP64F-LP64D: entry:257//258struct large f_agg_large_ret(int32_t i, int8_t j) {259 return (struct large){1, 2, 3, 4};260}261 262typedef unsigned char v32i8 __attribute__((vector_size(32)));263 264// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8265// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[TMP0:%.*]]) #[[ATTR0]] {266// LP64-LP64F-LP64D: entry:267//268void f_vec_large_v32i8(v32i8 x) {269 x[0] = x[7];270}271 272// LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8_ret273// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 [[AGG_RESULT:%.*]]) #[[ATTR0]] {274// LP64-LP64F-LP64D: entry:275//276v32i8 f_vec_large_v32i8_ret(void) {277 return (v32i8){1, 2, 3, 4, 5, 6, 7, 8};278}279 280// Scalars passed on the stack should have signext/zeroext attributes, just as281// if they were passed in registers.282 283// LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_1284// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]], [2 x i64] [[B_COERCE:%.*]], i128 [[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]] {285// LP64-LP64F-LP64D: entry:286//287int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,288 struct large d, uint8_t e, int8_t f, uint8_t g, int8_t h) {289 return g + h;290}291 292// LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_2293// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] {294// LP64-LP64F-LP64D: entry:295//296int f_scalar_stack_2(int32_t a, __int128_t b, int64_t c, long double d, v32i8 e,297 uint8_t f, int8_t g, uint8_t h) {298 return g + h;299}300 301// LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_3302// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] {303// LP64-LP64F-LP64D: entry:304//305int f_scalar_stack_3(int32_t a, __int128_t b, double c, long double d, v32i8 e,306 uint8_t f, int8_t g, uint8_t h) {307 return g + h;308}309 310// Ensure that scalars passed on the stack are still determined correctly in311// the presence of large return values that consume a register due to the need312// to pass a pointer.313 314// LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_4315// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {316// LP64-LP64F-LP64D: entry:317//318struct large f_scalar_stack_4(uint32_t a, __int128_t b, long double c, v32i8 d,319 uint8_t e, int8_t f, uint8_t g) {320 return (struct large){a, e, f, g};321}322 323// LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_5324// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] {325// LP64-LP64F-LP64D: entry:326//327struct large f_scalar_stack_5(double a, __int128_t b, long double c, v32i8 d,328 uint8_t e, int8_t f, uint8_t g) {329 return (struct large){a, e, f, g};330}331 332// LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_6333// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], float noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]], half noundef [[I:%.*]]) #[[ATTR0]] {334// LP64-LP64F-LP64D: entry:335//336int f_scalar_stack_6(int32_t a, __int128_t b, float c, long double d, v32i8 e,337 uint8_t f, int8_t g, uint8_t h, _Float16 i) {338 return g + h;339}340 341// LP64-LP64F-LP64D-LABEL: define dso_local void @f_fpr_tracking342// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], float noundef [[H:%.*]], i8 noundef zeroext [[I:%.*]]) #[[ATTR0]] {343// LP64-LP64F-LP64D: entry:344//345void f_fpr_tracking(float a, float b, float c, float d, float e, float f,346 float g, float h, uint8_t i) {}347 348// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will349// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are350// available the widths are <= XLEN and FLEN, and should be expanded to351// separate arguments in IR. They are passed by the same rules for returns,352// but will be lowered to simple two-element structs if necessary (as LLVM IR353// functions cannot return multiple values).354 355// A struct containing just one floating-point real is passed as though it356// were a standalone floating-point real.357 358struct float_s { float f; };359 360// LP64-LABEL: define dso_local void @f_float_s_arg361// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {362// LP64: entry:363//364// LP64F-LP64D-LABEL: define dso_local void @f_float_s_arg365// LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {366// LP64F-LP64D: entry:367//368void f_float_s_arg(struct float_s a) {}369 370// LP64-LABEL: define dso_local i64 @f_ret_float_s371// LP64-SAME: () #[[ATTR0]] {372// LP64: entry:373//374// LP64F-LP64D-LABEL: define dso_local float @f_ret_float_s375// LP64F-LP64D-SAME: () #[[ATTR0]] {376// LP64F-LP64D: entry:377//378struct float_s f_ret_float_s(void) {379 return (struct float_s){1.0};380}381 382// A struct containing a float and any number of zero-width bitfields is383// passed as though it were a standalone floating-point real.384 385struct zbf_float_s { int : 0; float f; };386struct zbf_float_zbf_s { int : 0; float f; int : 0; };387 388// LP64-LABEL: define dso_local void @f_zbf_float_s_arg389// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {390// LP64: entry:391//392// LP64F-LP64D-LABEL: define dso_local void @f_zbf_float_s_arg393// LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {394// LP64F-LP64D: entry:395//396void f_zbf_float_s_arg(struct zbf_float_s a) {}397 398// LP64-LABEL: define dso_local i64 @f_ret_zbf_float_s399// LP64-SAME: () #[[ATTR0]] {400// LP64: entry:401//402// LP64F-LP64D-LABEL: define dso_local float @f_ret_zbf_float_s403// LP64F-LP64D-SAME: () #[[ATTR0]] {404// LP64F-LP64D: entry:405//406struct zbf_float_s f_ret_zbf_float_s(void) {407 return (struct zbf_float_s){1.0};408}409 410// LP64-LABEL: define dso_local void @f_zbf_float_zbf_s_arg411// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {412// LP64: entry:413//414// LP64F-LP64D-LABEL: define dso_local void @f_zbf_float_zbf_s_arg415// LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {416// LP64F-LP64D: entry:417//418void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {}419 420// LP64-LABEL: define dso_local i64 @f_ret_zbf_float_zbf_s421// LP64-SAME: () #[[ATTR0]] {422// LP64: entry:423//424// LP64F-LP64D-LABEL: define dso_local float @f_ret_zbf_float_zbf_s425// LP64F-LP64D-SAME: () #[[ATTR0]] {426// LP64F-LP64D: entry:427//428struct zbf_float_zbf_s f_ret_zbf_float_zbf_s(void) {429 return (struct zbf_float_zbf_s){1.0};430}431 432// Check that structs containing two float values (FLEN <= width) are expanded433// provided sufficient FPRs are available.434 435struct float_float_s { float f; float g; };436 437// LP64-LABEL: define dso_local void @f_float_float_s_arg438// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {439// LP64: entry:440//441// LP64F-LP64D-LABEL: define dso_local void @f_float_float_s_arg442// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {443// LP64F-LP64D: entry:444//445void f_float_float_s_arg(struct float_float_s a) {}446 447// LP64-LABEL: define dso_local i64 @f_ret_float_float_s448// LP64-SAME: () #[[ATTR0]] {449// LP64: entry:450//451// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_float_float_s452// LP64F-LP64D-SAME: () #[[ATTR0]] {453// LP64F-LP64D: entry:454//455struct float_float_s f_ret_float_float_s(void) {456 return (struct float_float_s){1.0, 2.0};457}458 459// LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_float_s_arg_insufficient_fprs460// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], i64 [[H_COERCE:%.*]]) #[[ATTR0]] {461// LP64-LP64F-LP64D: entry:462//463void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d,464 float e, float f, float g, struct float_float_s h) {}465 466// Check that structs containing int+float values are expanded, provided467// sufficient FPRs and GPRs are available. The integer components are neither468// sign or zero-extended.469 470struct float_int8_s { float f; int8_t i; };471struct float_uint8_s { float f; uint8_t i; };472struct float_int32_s { float f; int32_t i; };473struct float_int64_s { float f; int64_t i; };474struct float_int128bf_s { float f; __int128_t i : 64; };475struct float_int8_zbf_s { float f; int8_t i; int : 0; };476 477// LP64-LABEL: define dso_local void @f_float_int8_s_arg478// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {479// LP64: entry:480//481// LP64F-LP64D-LABEL: define dso_local void @f_float_int8_s_arg482// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {483// LP64F-LP64D: entry:484//485void f_float_int8_s_arg(struct float_int8_s a) {}486 487// LP64-LABEL: define dso_local i64 @f_ret_float_int8_s488// LP64-SAME: () #[[ATTR0]] {489// LP64: entry:490//491// LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_s492// LP64F-LP64D-SAME: () #[[ATTR0]] {493// LP64F-LP64D: entry:494//495struct float_int8_s f_ret_float_int8_s(void) {496 return (struct float_int8_s){1.0, 2};497}498 499// LP64-LABEL: define dso_local void @f_float_uint8_s_arg500// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {501// LP64: entry:502//503// LP64F-LP64D-LABEL: define dso_local void @f_float_uint8_s_arg504// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {505// LP64F-LP64D: entry:506//507void f_float_uint8_s_arg(struct float_uint8_s a) {}508 509// LP64-LABEL: define dso_local i64 @f_ret_float_uint8_s510// LP64-SAME: () #[[ATTR0]] {511// LP64: entry:512//513// LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_uint8_s514// LP64F-LP64D-SAME: () #[[ATTR0]] {515// LP64F-LP64D: entry:516//517struct float_uint8_s f_ret_float_uint8_s(void) {518 return (struct float_uint8_s){1.0, 2};519}520 521// LP64-LABEL: define dso_local void @f_float_int32_s_arg522// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {523// LP64: entry:524//525// LP64F-LP64D-LABEL: define dso_local void @f_float_int32_s_arg526// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {527// LP64F-LP64D: entry:528//529void f_float_int32_s_arg(struct float_int32_s a) {}530 531// LP64-LABEL: define dso_local i64 @f_ret_float_int32_s532// LP64-SAME: () #[[ATTR0]] {533// LP64: entry:534//535// LP64F-LP64D-LABEL: define dso_local { float, i32 } @f_ret_float_int32_s536// LP64F-LP64D-SAME: () #[[ATTR0]] {537// LP64F-LP64D: entry:538//539struct float_int32_s f_ret_float_int32_s(void) {540 return (struct float_int32_s){1.0, 2};541}542 543// LP64-LABEL: define dso_local void @f_float_int64_s_arg544// LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {545// LP64: entry:546//547// LP64F-LP64D-LABEL: define dso_local void @f_float_int64_s_arg548// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {549// LP64F-LP64D: entry:550//551void f_float_int64_s_arg(struct float_int64_s a) {}552 553// LP64-LABEL: define dso_local [2 x i64] @f_ret_float_int64_s554// LP64-SAME: () #[[ATTR0]] {555// LP64: entry:556//557// LP64F-LP64D-LABEL: define dso_local { float, i64 } @f_ret_float_int64_s558// LP64F-LP64D-SAME: () #[[ATTR0]] {559// LP64F-LP64D: entry:560//561struct float_int64_s f_ret_float_int64_s(void) {562 return (struct float_int64_s){1.0, 2};563}564 565// LP64-LABEL: define dso_local void @f_float_int128bf_s_arg566// LP64-SAME: (i128 [[A_COERCE:%.*]]) #[[ATTR0]] {567// LP64: entry:568//569// LP64F-LP64D-LABEL: define dso_local void @f_float_int128bf_s_arg570// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {571// LP64F-LP64D: entry:572//573void f_float_int128bf_s_arg(struct float_int128bf_s a) {}574 575// LP64-LABEL: define dso_local i128 @f_ret_float_int128bf_s576// LP64-SAME: () #[[ATTR0]] {577// LP64: entry:578//579// LP64F-LP64D-LABEL: define dso_local <{ float, i64 }> @f_ret_float_int128bf_s580// LP64F-LP64D-SAME: () #[[ATTR0]] {581// LP64F-LP64D: entry:582//583struct float_int128bf_s f_ret_float_int128bf_s(void) {584 return (struct float_int128bf_s){1.0, 2};585}586 587// The zero-width bitfield means the struct can't be passed according to the588// floating point calling convention.589 590// LP64-LABEL: define dso_local void @f_float_int8_zbf_s591// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {592// LP64: entry:593//594// LP64F-LP64D-LABEL: define dso_local void @f_float_int8_zbf_s595// LP64F-LP64D-SAME: (float [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {596// LP64F-LP64D: entry:597//598void f_float_int8_zbf_s(struct float_int8_zbf_s a) {}599 600// LP64-LABEL: define dso_local i64 @f_ret_float_int8_zbf_s601// LP64-SAME: () #[[ATTR0]] {602// LP64: entry:603//604// LP64F-LP64D-LABEL: define dso_local { float, i8 } @f_ret_float_int8_zbf_s605// LP64F-LP64D-SAME: () #[[ATTR0]] {606// LP64F-LP64D: entry:607//608struct float_int8_zbf_s f_ret_float_int8_zbf_s(void) {609 return (struct float_int8_zbf_s){1.0, 2};610}611 612// LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_int8_s_arg_insufficient_gprs613// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {614// LP64-LP64F-LP64D: entry:615//616void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,617 int f, int g, int h, struct float_int8_s i) {}618 619// LP64-LP64F-LP64D-LABEL: define dso_local void @f_struct_float_int8_insufficient_fprs620// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]], float noundef [[D:%.*]], float noundef [[E:%.*]], float noundef [[F:%.*]], float noundef [[G:%.*]], float noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {621// LP64-LP64F-LP64D: entry:622//623void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d,624 float e, float f, float g, float h, struct float_int8_s i) {}625 626// Complex floating-point values or structs containing a single complex627// floating-point value should be passed as if it were an fp+fp struct.628 629// LP64-LABEL: define dso_local void @f_floatcomplex630// LP64-SAME: (i64 noundef [[A_COERCE:%.*]]) #[[ATTR0]] {631// LP64: entry:632//633// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex634// LP64F-LP64D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {635// LP64F-LP64D: entry:636//637void f_floatcomplex(float __complex__ a) {}638 639// LP64-LABEL: define dso_local i64 @f_ret_floatcomplex640// LP64-SAME: () #[[ATTR0]] {641// LP64: entry:642//643// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatcomplex644// LP64F-LP64D-SAME: () #[[ATTR0]] {645// LP64F-LP64D: entry:646//647float __complex__ f_ret_floatcomplex(void) {648 return 1.0;649}650 651struct floatcomplex_s { float __complex__ c; };652 653// LP64-LABEL: define dso_local void @f_floatcomplex_s_arg654// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {655// LP64: entry:656//657// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg658// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {659// LP64F-LP64D: entry:660//661void f_floatcomplex_s_arg(struct floatcomplex_s a) {}662 663// LP64-LABEL: define dso_local i64 @f_ret_floatcomplex_s664// LP64-SAME: () #[[ATTR0]] {665// LP64: entry:666//667// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatcomplex_s668// LP64F-LP64D-SAME: () #[[ATTR0]] {669// LP64F-LP64D: entry:670//671struct floatcomplex_s f_ret_floatcomplex_s(void) {672 return (struct floatcomplex_s){1.0};673}674 675// Complex floating-point values or structs containing a single complex676// floating-point value should be passed in GPRs if no two FPRs is available.677 678// LP64-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs1679// LP64-SAME: (i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]], i64 noundef [[C_COERCE:%.*]], i64 noundef [[D_COERCE:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {680// LP64: entry:681//682// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs1683// LP64F-LP64D-SAME: (float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]], float noundef [[D_COERCE0:%.*]], float noundef [[D_COERCE1:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {684// LP64F-LP64D: entry:685//686void f_floatcomplex_insufficient_fprs1(float __complex__ a, float __complex__ b,687 float __complex__ c, float __complex__ d,688 float __complex__ e) {}689 690 691// LP64-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs1692// LP64-SAME: (i64 [[A_COERCE:%.*]], i64 [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], i64 [[D_COERCE:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {693// LP64: entry:694//695// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs1696// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]], float [[TMP3:%.*]], float [[TMP4:%.*]], float [[TMP5:%.*]], float [[TMP6:%.*]], float [[TMP7:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {697// LP64F-LP64D: entry:698//699void f_floatcomplex_s_arg_insufficient_fprs1(struct floatcomplex_s a,700 struct floatcomplex_s b,701 struct floatcomplex_s c,702 struct floatcomplex_s d,703 struct floatcomplex_s e) {}704 705// LP64-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs2706// LP64-SAME: (float noundef [[A:%.*]], i64 noundef [[B_COERCE:%.*]], i64 noundef [[C_COERCE:%.*]], i64 noundef [[D_COERCE:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {707// LP64: entry:708//709// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_insufficient_fprs2710// LP64F-LP64D-SAME: (float noundef [[A:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]], float noundef [[D_COERCE0:%.*]], float noundef [[D_COERCE1:%.*]], i64 noundef [[E_COERCE:%.*]]) #[[ATTR0]] {711// LP64F-LP64D: entry:712//713void f_floatcomplex_insufficient_fprs2(float a,714 float __complex__ b, float __complex__ c,715 float __complex__ d, float __complex__ e) {}716 717 718// LP64-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs2719// LP64-SAME: (float noundef [[A:%.*]], i64 [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], i64 [[D_COERCE:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {720// LP64: entry:721//722// LP64F-LP64D-LABEL: define dso_local void @f_floatcomplex_s_arg_insufficient_fprs2723// LP64F-LP64D-SAME: (float noundef [[A:%.*]], float [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]], float [[TMP3:%.*]], float [[TMP4:%.*]], float [[TMP5:%.*]], i64 [[E_COERCE:%.*]]) #[[ATTR0]] {724// LP64F-LP64D: entry:725//726void f_floatcomplex_s_arg_insufficient_fprs2(float a,727 struct floatcomplex_s b,728 struct floatcomplex_s c,729 struct floatcomplex_s d,730 struct floatcomplex_s e) {}731 732// Test single or two-element structs that need flattening. e.g. those733// containing nested structs, floats in small arrays, zero-length structs etc.734 735struct floatarr1_s { float a[1]; };736 737// LP64-LABEL: define dso_local void @f_floatarr1_s_arg738// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {739// LP64: entry:740//741// LP64F-LP64D-LABEL: define dso_local void @f_floatarr1_s_arg742// LP64F-LP64D-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {743// LP64F-LP64D: entry:744//745void f_floatarr1_s_arg(struct floatarr1_s a) {}746 747// LP64-LABEL: define dso_local i64 @f_ret_floatarr1_s748// LP64-SAME: () #[[ATTR0]] {749// LP64: entry:750//751// LP64F-LP64D-LABEL: define dso_local float @f_ret_floatarr1_s752// LP64F-LP64D-SAME: () #[[ATTR0]] {753// LP64F-LP64D: entry:754//755struct floatarr1_s f_ret_floatarr1_s(void) {756 return (struct floatarr1_s){{1.0}};757}758 759struct floatarr2_s { float a[2]; };760 761// LP64-LABEL: define dso_local void @f_floatarr2_s_arg762// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {763// LP64: entry:764//765// LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_s_arg766// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {767// LP64F-LP64D: entry:768//769void f_floatarr2_s_arg(struct floatarr2_s a) {}770 771// LP64-LABEL: define dso_local i64 @f_ret_floatarr2_s772// LP64-SAME: () #[[ATTR0]] {773// LP64: entry:774//775// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_s776// LP64F-LP64D-SAME: () #[[ATTR0]] {777// LP64F-LP64D: entry:778//779struct floatarr2_s f_ret_floatarr2_s(void) {780 return (struct floatarr2_s){{1.0, 2.0}};781}782 783struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; };784 785// LP64-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg786// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {787// LP64: entry:788//789// LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky1_s_arg790// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {791// LP64F-LP64D: entry:792//793void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {}794 795// LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky1_s796// LP64-SAME: () #[[ATTR0]] {797// LP64: entry:798//799// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky1_s800// LP64F-LP64D-SAME: () #[[ATTR0]] {801// LP64F-LP64D: entry:802//803struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s(void) {804 return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}};805}806 807struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; };808 809// LP64-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg810// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {811// LP64: entry:812//813// LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky2_s_arg814// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {815// LP64F-LP64D: entry:816//817void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {}818 819// LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky2_s820// LP64-SAME: () #[[ATTR0]] {821// LP64: entry:822//823// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky2_s824// LP64F-LP64D-SAME: () #[[ATTR0]] {825// LP64F-LP64D: entry:826//827struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s(void) {828 return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};829}830 831struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; };832 833// LP64-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg834// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {835// LP64: entry:836//837// LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky3_s_arg838// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {839// LP64F-LP64D: entry:840//841void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {}842 843// LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky3_s844// LP64-SAME: () #[[ATTR0]] {845// LP64: entry:846//847// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky3_s848// LP64F-LP64D-SAME: () #[[ATTR0]] {849// LP64F-LP64D: entry:850//851struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s(void) {852 return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};853}854 855struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; };856 857// LP64-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg858// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {859// LP64: entry:860//861// LP64F-LP64D-LABEL: define dso_local void @f_floatarr2_tricky4_s_arg862// LP64F-LP64D-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {863// LP64F-LP64D: entry:864//865void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {}866 867// LP64-LABEL: define dso_local i64 @f_ret_floatarr2_tricky4_s868// LP64-SAME: () #[[ATTR0]] {869// LP64: entry:870//871// LP64F-LP64D-LABEL: define dso_local { float, float } @f_ret_floatarr2_tricky4_s872// LP64F-LP64D-SAME: () #[[ATTR0]] {873// LP64F-LP64D: entry:874//875struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s(void) {876 return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};877}878 879// Test structs that should be passed according to the normal integer calling880// convention.881 882struct int_float_int_s { int a; float b; int c; };883 884// LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_float_int_s_arg885// LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {886// LP64-LP64F-LP64D: entry:887//888void f_int_float_int_s_arg(struct int_float_int_s a) {}889 890// LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_int_float_int_s891// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {892// LP64-LP64F-LP64D: entry:893//894struct int_float_int_s f_ret_int_float_int_s(void) {895 return (struct int_float_int_s){1, 2.0, 3};896}897 898struct char_char_float_s { char a; char b; float c; };899 900// LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_float_s_arg901// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {902// LP64-LP64F-LP64D: entry:903//904void f_char_char_float_s_arg(struct char_char_float_s a) {}905 906// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_char_char_float_s907// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {908// LP64-LP64F-LP64D: entry:909//910struct char_char_float_s f_ret_char_char_float_s(void) {911 return (struct char_char_float_s){1, 2, 3.0};912}913 914// Unions are always passed according to the integer calling convention, even915// if they can only contain a float.916 917union float_u { float a; };918 919// LP64-LP64F-LP64D-LABEL: define dso_local void @f_float_u_arg920// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {921// LP64-LP64F-LP64D: entry:922//923void f_float_u_arg(union float_u a) {}924 925// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_float_u926// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {927// LP64-LP64F-LP64D: entry:928//929union float_u f_ret_float_u(void) {930 return (union float_u){1.0};931}932 933// LP64-LP64F-LP64D-LABEL: define dso_local void @f_fpr_tracking2934// LP64-LP64F-LP64D-SAME: (double noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i8 noundef zeroext [[I:%.*]]) #[[ATTR0]] {935// LP64-LP64F-LP64D: entry:936//937void f_fpr_tracking2(double a, double b, double c, double d, double e, double f,938 double g, double h, uint8_t i) {}939 940// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will941// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are942// available the widths are <= XLEN and FLEN, and should be expanded to943// separate arguments in IR. They are passed by the same rules for returns,944// but will be lowered to simple two-element structs if necessary (as LLVM IR945// functions cannot return multiple values).946 947// A struct containing just one floating-point real is passed as though it948// were a standalone floating-point real.949 950struct double_s { double f; };951 952// LP64-LP64F-LABEL: define dso_local void @f_double_s_arg953// LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {954// LP64-LP64F: entry:955//956// LP64D-LABEL: define dso_local void @f_double_s_arg957// LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {958// LP64D: entry:959//960void f_double_s_arg(struct double_s a) {}961 962// LP64-LP64F-LABEL: define dso_local i64 @f_ret_double_s963// LP64-LP64F-SAME: () #[[ATTR0]] {964// LP64-LP64F: entry:965//966// LP64D-LABEL: define dso_local double @f_ret_double_s967// LP64D-SAME: () #[[ATTR0]] {968// LP64D: entry:969//970struct double_s f_ret_double_s(void) {971 return (struct double_s){1.0};972}973 974// A struct containing a double and any number of zero-width bitfields is975// passed as though it were a standalone floating-point real.976 977struct zbf_double_s { int : 0; double f; };978struct zbf_double_zbf_s { int : 0; double f; int : 0; };979 980// LP64-LP64F-LABEL: define dso_local void @f_zbf_double_s_arg981// LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {982// LP64-LP64F: entry:983//984// LP64D-LABEL: define dso_local void @f_zbf_double_s_arg985// LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {986// LP64D: entry:987//988void f_zbf_double_s_arg(struct zbf_double_s a) {}989 990// LP64-LP64F-LABEL: define dso_local i64 @f_ret_zbf_double_s991// LP64-LP64F-SAME: () #[[ATTR0]] {992// LP64-LP64F: entry:993//994// LP64D-LABEL: define dso_local double @f_ret_zbf_double_s995// LP64D-SAME: () #[[ATTR0]] {996// LP64D: entry:997//998struct zbf_double_s f_ret_zbf_double_s(void) {999 return (struct zbf_double_s){1.0};1000}1001 1002// LP64-LP64F-LABEL: define dso_local void @f_zbf_double_zbf_s_arg1003// LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1004// LP64-LP64F: entry:1005//1006// LP64D-LABEL: define dso_local void @f_zbf_double_zbf_s_arg1007// LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {1008// LP64D: entry:1009//1010void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {}1011 1012// LP64-LP64F-LABEL: define dso_local i64 @f_ret_zbf_double_zbf_s1013// LP64-LP64F-SAME: () #[[ATTR0]] {1014// LP64-LP64F: entry:1015//1016// LP64D-LABEL: define dso_local double @f_ret_zbf_double_zbf_s1017// LP64D-SAME: () #[[ATTR0]] {1018// LP64D: entry:1019//1020struct zbf_double_zbf_s f_ret_zbf_double_zbf_s(void) {1021 return (struct zbf_double_zbf_s){1.0};1022}1023 1024// Check that structs containing two floating point values (FLEN <= width) are1025// expanded provided sufficient FPRs are available.1026 1027struct double_double_s { double f; double g; };1028struct double_float_s { double f; float g; };1029 1030// LP64-LP64F-LABEL: define dso_local void @f_double_double_s_arg1031// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1032// LP64-LP64F: entry:1033//1034// LP64D-LABEL: define dso_local void @f_double_double_s_arg1035// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1036// LP64D: entry:1037//1038void f_double_double_s_arg(struct double_double_s a) {}1039 1040// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_double_s1041// LP64-LP64F-SAME: () #[[ATTR0]] {1042// LP64-LP64F: entry:1043//1044// LP64D-LABEL: define dso_local { double, double } @f_ret_double_double_s1045// LP64D-SAME: () #[[ATTR0]] {1046// LP64D: entry:1047//1048struct double_double_s f_ret_double_double_s(void) {1049 return (struct double_double_s){1.0, 2.0};1050}1051 1052// LP64-LP64F-LABEL: define dso_local void @f_double_float_s_arg1053// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1054// LP64-LP64F: entry:1055//1056// LP64D-LABEL: define dso_local void @f_double_float_s_arg1057// LP64D-SAME: (double [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {1058// LP64D: entry:1059//1060void f_double_float_s_arg(struct double_float_s a) {}1061 1062// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_float_s1063// LP64-LP64F-SAME: () #[[ATTR0]] {1064// LP64-LP64F: entry:1065//1066// LP64D-LABEL: define dso_local { double, float } @f_ret_double_float_s1067// LP64D-SAME: () #[[ATTR0]] {1068// LP64D: entry:1069//1070struct double_float_s f_ret_double_float_s(void) {1071 return (struct double_float_s){1.0, 2.0};1072}1073 1074// LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_double_s_arg_insufficient_fprs1075// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], [2 x i64] [[H_COERCE:%.*]]) #[[ATTR0]] {1076// LP64-LP64F-LP64D: entry:1077//1078void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d,1079 double e, double f, double g, struct double_double_s h) {}1080 1081// Check that structs containing int+double values are expanded, provided1082// sufficient FPRs and GPRs are available. The integer components are neither1083// sign or zero-extended.1084 1085struct double_int8_s { double f; int8_t i; };1086struct double_uint8_s { double f; uint8_t i; };1087struct double_int32_s { double f; int32_t i; };1088struct double_int64_s { double f; int64_t i; };1089struct double_int128bf_s { double f; __int128_t i : 64; };1090struct double_int8_zbf_s { double f; int8_t i; int : 0; };1091 1092// LP64-LP64F-LABEL: define dso_local void @f_double_int8_s_arg1093// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1094// LP64-LP64F: entry:1095//1096// LP64D-LABEL: define dso_local void @f_double_int8_s_arg1097// LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1098// LP64D: entry:1099//1100void f_double_int8_s_arg(struct double_int8_s a) {}1101 1102// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int8_s1103// LP64-LP64F-SAME: () #[[ATTR0]] {1104// LP64-LP64F: entry:1105//1106// LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_s1107// LP64D-SAME: () #[[ATTR0]] {1108// LP64D: entry:1109//1110struct double_int8_s f_ret_double_int8_s(void) {1111 return (struct double_int8_s){1.0, 2};1112}1113 1114// LP64-LP64F-LABEL: define dso_local void @f_double_uint8_s_arg1115// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1116// LP64-LP64F: entry:1117//1118// LP64D-LABEL: define dso_local void @f_double_uint8_s_arg1119// LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1120// LP64D: entry:1121//1122void f_double_uint8_s_arg(struct double_uint8_s a) {}1123 1124// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_uint8_s1125// LP64-LP64F-SAME: () #[[ATTR0]] {1126// LP64-LP64F: entry:1127//1128// LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_uint8_s1129// LP64D-SAME: () #[[ATTR0]] {1130// LP64D: entry:1131//1132struct double_uint8_s f_ret_double_uint8_s(void) {1133 return (struct double_uint8_s){1.0, 2};1134}1135 1136// LP64-LP64F-LABEL: define dso_local void @f_double_int32_s_arg1137// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1138// LP64-LP64F: entry:1139//1140// LP64D-LABEL: define dso_local void @f_double_int32_s_arg1141// LP64D-SAME: (double [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1142// LP64D: entry:1143//1144void f_double_int32_s_arg(struct double_int32_s a) {}1145 1146// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int32_s1147// LP64-LP64F-SAME: () #[[ATTR0]] {1148// LP64-LP64F: entry:1149//1150// LP64D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s1151// LP64D-SAME: () #[[ATTR0]] {1152// LP64D: entry:1153//1154struct double_int32_s f_ret_double_int32_s(void) {1155 return (struct double_int32_s){1.0, 2};1156}1157 1158// LP64-LP64F-LABEL: define dso_local void @f_double_int64_s_arg1159// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1160// LP64-LP64F: entry:1161//1162// LP64D-LABEL: define dso_local void @f_double_int64_s_arg1163// LP64D-SAME: (double [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {1164// LP64D: entry:1165//1166void f_double_int64_s_arg(struct double_int64_s a) {}1167 1168// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int64_s1169// LP64-LP64F-SAME: () #[[ATTR0]] {1170// LP64-LP64F: entry:1171//1172// LP64D-LABEL: define dso_local { double, i64 } @f_ret_double_int64_s1173// LP64D-SAME: () #[[ATTR0]] {1174// LP64D: entry:1175//1176struct double_int64_s f_ret_double_int64_s(void) {1177 return (struct double_int64_s){1.0, 2};1178}1179 1180// LP64-LP64F-LABEL: define dso_local void @f_double_int128bf_s_arg1181// LP64-LP64F-SAME: (i128 [[A_COERCE:%.*]]) #[[ATTR0]] {1182// LP64-LP64F: entry:1183//1184// LP64D-LABEL: define dso_local void @f_double_int128bf_s_arg1185// LP64D-SAME: (double [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {1186// LP64D: entry:1187//1188void f_double_int128bf_s_arg(struct double_int128bf_s a) {}1189 1190// LP64-LP64F-LABEL: define dso_local i128 @f_ret_double_int128bf_s1191// LP64-LP64F-SAME: () #[[ATTR0]] {1192// LP64-LP64F: entry:1193//1194// LP64D-LABEL: define dso_local { double, i64 } @f_ret_double_int128bf_s1195// LP64D-SAME: () #[[ATTR0]] {1196// LP64D: entry:1197//1198struct double_int128bf_s f_ret_double_int128bf_s(void) {1199 return (struct double_int128bf_s){1.0, 2};1200}1201 1202// The zero-width bitfield means the struct can't be passed according to the1203// floating point calling convention.1204 1205// LP64-LP64F-LABEL: define dso_local void @f_double_int8_zbf_s1206// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1207// LP64-LP64F: entry:1208//1209// LP64D-LABEL: define dso_local void @f_double_int8_zbf_s1210// LP64D-SAME: (double [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1211// LP64D: entry:1212//1213void f_double_int8_zbf_s(struct double_int8_zbf_s a) {}1214 1215// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_int8_zbf_s1216// LP64-LP64F-SAME: () #[[ATTR0]] {1217// LP64-LP64F: entry:1218//1219// LP64D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_zbf_s1220// LP64D-SAME: () #[[ATTR0]] {1221// LP64D: entry:1222//1223struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) {1224 return (struct double_int8_zbf_s){1.0, 2};1225}1226 1227// LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_int8_s_arg_insufficient_gprs1228// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], [2 x i64] [[I_COERCE:%.*]]) #[[ATTR0]] {1229// LP64-LP64F-LP64D: entry:1230//1231void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,1232 int f, int g, int h, struct double_int8_s i) {}1233 1234// LP64-LP64F-LP64D-LABEL: define dso_local void @f_struct_double_int8_insufficient_fprs1235// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], [2 x i64] [[I_COERCE:%.*]]) #[[ATTR0]] {1236// LP64-LP64F-LP64D: entry:1237//1238void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d,1239 double e, double f, double g, double h, struct double_int8_s i) {}1240 1241// Complex floating-point values or structs containing a single complex1242// floating-point value should be passed as if it were an fp+fp struct.1243 1244// LP64-LP64F-LABEL: define dso_local void @f_doublecomplex1245// LP64-LP64F-SAME: ([2 x i64] noundef [[A_COERCE:%.*]]) #[[ATTR0]] {1246// LP64-LP64F: entry:1247//1248// LP64D-LABEL: define dso_local void @f_doublecomplex1249// LP64D-SAME: (double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {1250// LP64D: entry:1251//1252void f_doublecomplex(double __complex__ a) {}1253 1254// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublecomplex1255// LP64-LP64F-SAME: () #[[ATTR0]] {1256// LP64-LP64F: entry:1257//1258// LP64D-LABEL: define dso_local { double, double } @f_ret_doublecomplex1259// LP64D-SAME: () #[[ATTR0]] {1260// LP64D: entry:1261//1262double __complex__ f_ret_doublecomplex(void) {1263 return 1.0;1264}1265 1266struct doublecomplex_s { double __complex__ c; };1267 1268// LP64-LP64F-LABEL: define dso_local void @f_doublecomplex_s_arg1269// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1270// LP64-LP64F: entry:1271//1272// LP64D-LABEL: define dso_local void @f_doublecomplex_s_arg1273// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1274// LP64D: entry:1275//1276void f_doublecomplex_s_arg(struct doublecomplex_s a) {}1277 1278// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublecomplex_s1279// LP64-LP64F-SAME: () #[[ATTR0]] {1280// LP64-LP64F: entry:1281//1282// LP64D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_s1283// LP64D-SAME: () #[[ATTR0]] {1284// LP64D: entry:1285//1286struct doublecomplex_s f_ret_doublecomplex_s(void) {1287 return (struct doublecomplex_s){1.0};1288}1289 1290// Test single or two-element structs that need flattening. e.g. those1291// containing nested structs, doubles in small arrays, zero-length structs etc.1292 1293struct doublearr1_s { double a[1]; };1294 1295// LP64-LP64F-LABEL: define dso_local void @f_doublearr1_s_arg1296// LP64-LP64F-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1297// LP64-LP64F: entry:1298//1299// LP64D-LABEL: define dso_local void @f_doublearr1_s_arg1300// LP64D-SAME: (double [[TMP0:%.*]]) #[[ATTR0]] {1301// LP64D: entry:1302//1303void f_doublearr1_s_arg(struct doublearr1_s a) {}1304 1305// LP64-LP64F-LABEL: define dso_local i64 @f_ret_doublearr1_s1306// LP64-LP64F-SAME: () #[[ATTR0]] {1307// LP64-LP64F: entry:1308//1309// LP64D-LABEL: define dso_local double @f_ret_doublearr1_s1310// LP64D-SAME: () #[[ATTR0]] {1311// LP64D: entry:1312//1313struct doublearr1_s f_ret_doublearr1_s(void) {1314 return (struct doublearr1_s){{1.0}};1315}1316 1317struct doublearr2_s { double a[2]; };1318 1319// LP64-LP64F-LABEL: define dso_local void @f_doublearr2_s_arg1320// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1321// LP64-LP64F: entry:1322//1323// LP64D-LABEL: define dso_local void @f_doublearr2_s_arg1324// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1325// LP64D: entry:1326//1327void f_doublearr2_s_arg(struct doublearr2_s a) {}1328 1329// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_s1330// LP64-LP64F-SAME: () #[[ATTR0]] {1331// LP64-LP64F: entry:1332//1333// LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_s1334// LP64D-SAME: () #[[ATTR0]] {1335// LP64D: entry:1336//1337struct doublearr2_s f_ret_doublearr2_s(void) {1338 return (struct doublearr2_s){{1.0, 2.0}};1339}1340 1341struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; };1342 1343// LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg1344// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1345// LP64-LP64F: entry:1346//1347// LP64D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg1348// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1349// LP64D: entry:1350//1351void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}1352 1353// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky1_s1354// LP64-LP64F-SAME: () #[[ATTR0]] {1355// LP64-LP64F: entry:1356//1357// LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky1_s1358// LP64D-SAME: () #[[ATTR0]] {1359// LP64D: entry:1360//1361struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {1362 return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};1363}1364 1365struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; };1366 1367// LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg1368// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1369// LP64-LP64F: entry:1370//1371// LP64D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg1372// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1373// LP64D: entry:1374//1375void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}1376 1377// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky2_s1378// LP64-LP64F-SAME: () #[[ATTR0]] {1379// LP64-LP64F: entry:1380//1381// LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky2_s1382// LP64D-SAME: () #[[ATTR0]] {1383// LP64D: entry:1384//1385struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {1386 return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};1387}1388 1389struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; };1390 1391// LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg1392// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1393// LP64-LP64F: entry:1394//1395// LP64D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg1396// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1397// LP64D: entry:1398//1399void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}1400 1401// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky3_s1402// LP64-LP64F-SAME: () #[[ATTR0]] {1403// LP64-LP64F: entry:1404//1405// LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky3_s1406// LP64D-SAME: () #[[ATTR0]] {1407// LP64D: entry:1408//1409struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {1410 return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};1411}1412 1413struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; };1414 1415// LP64-LP64F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg1416// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1417// LP64-LP64F: entry:1418//1419// LP64D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg1420// LP64D-SAME: (double [[TMP0:%.*]], double [[TMP1:%.*]]) #[[ATTR0]] {1421// LP64D: entry:1422//1423void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}1424 1425// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_doublearr2_tricky4_s1426// LP64-LP64F-SAME: () #[[ATTR0]] {1427// LP64-LP64F: entry:1428//1429// LP64D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky4_s1430// LP64D-SAME: () #[[ATTR0]] {1431// LP64D: entry:1432//1433struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) {1434 return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};1435}1436 1437// Test structs that should be passed according to the normal integer calling1438// convention.1439 1440struct int_double_int_s { int a; double b; int c; };1441 1442// LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_double_int_s_arg1443// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] {1444// LP64-LP64F-LP64D: entry:1445//1446void f_int_double_int_s_arg(struct int_double_int_s a) {}1447 1448// LP64-LP64F-LP64D-LABEL: define dso_local void @f_ret_int_double_int_s1449// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] {1450// LP64-LP64F-LP64D: entry:1451//1452struct int_double_int_s f_ret_int_double_int_s(void) {1453 return (struct int_double_int_s){1, 2.0, 3};1454}1455 1456struct char_char_double_s { char a; char b; double c; };1457 1458// LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_double_s_arg1459// LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1460// LP64-LP64F-LP64D: entry:1461//1462void f_char_char_double_s_arg(struct char_char_double_s a) {}1463 1464// LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_char_char_double_s1465// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {1466// LP64-LP64F-LP64D: entry:1467//1468struct char_char_double_s f_ret_char_char_double_s(void) {1469 return (struct char_char_double_s){1, 2, 3.0};1470}1471 1472// Unions are always passed according to the integer calling convention, even1473// if they can only contain a double.1474 1475union double_u { double a; };1476 1477// LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_u_arg1478// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1479// LP64-LP64F-LP64D: entry:1480//1481void f_double_u_arg(union double_u a) {}1482 1483// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_double_u1484// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {1485// LP64-LP64F-LP64D: entry:1486//1487union double_u f_ret_double_u(void) {1488 return (union double_u){1.0};1489}1490 1491// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will1492// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are1493// available the widths are <= XLEN and FLEN, and should be expanded to1494// separate arguments in IR. They are passed by the same rules for returns,1495// but will be lowered to simple two-element structs if necessary (as LLVM IR1496// functions cannot return multiple values).1497 1498struct float16_s { _Float16 f; };1499 1500// A struct containing just one floating-point real is passed as though it1501// were a standalone floating-point real.1502 1503// LP64-LABEL: define dso_local void @f_float16_s_arg1504// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1505// LP64: entry:1506//1507// LP64F-LP64D-LABEL: define dso_local void @f_float16_s_arg1508// LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1509// LP64F-LP64D: entry:1510//1511void f_float16_s_arg(struct float16_s a) {}1512 1513// LP64-LABEL: define dso_local i64 @f_ret_float16_s1514// LP64-SAME: () #[[ATTR0]] {1515// LP64: entry:1516//1517// LP64F-LP64D-LABEL: define dso_local half @f_ret_float16_s1518// LP64F-LP64D-SAME: () #[[ATTR0]] {1519// LP64F-LP64D: entry:1520//1521struct float16_s f_ret_float16_s(void) {1522 return (struct float16_s){1.0};1523}1524 1525// A struct containing a double and any number of zero-width bitfields is1526// passed as though it were a standalone floating-point real.1527 1528struct zbf_float16_s { int : 0; _Float16 f; };1529struct zbf_float16_zbf_s { int : 0; _Float16 f; int : 0; };1530 1531// LP64-LABEL: define dso_local void @f_zbf_float16_s_arg1532// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1533// LP64: entry:1534//1535// LP64F-LP64D-LABEL: define dso_local void @f_zbf_float16_s_arg1536// LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1537// LP64F-LP64D: entry:1538//1539void f_zbf_float16_s_arg(struct zbf_float16_s a) {}1540 1541// LP64-LABEL: define dso_local i64 @f_ret_zbf_float16_s1542// LP64-SAME: () #[[ATTR0]] {1543// LP64: entry:1544//1545// LP64F-LP64D-LABEL: define dso_local half @f_ret_zbf_float16_s1546// LP64F-LP64D-SAME: () #[[ATTR0]] {1547// LP64F-LP64D: entry:1548//1549struct zbf_float16_s f_ret_zbf_float16_s(void) {1550 return (struct zbf_float16_s){1.0};1551}1552 1553// LP64-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg1554// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1555// LP64: entry:1556//1557// LP64F-LP64D-LABEL: define dso_local void @f_zbf_float16_zbf_s_arg1558// LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1559// LP64F-LP64D: entry:1560//1561void f_zbf_float16_zbf_s_arg(struct zbf_float16_zbf_s a) {}1562 1563// LP64-LABEL: define dso_local i64 @f_ret_zbf_float16_zbf_s1564// LP64-SAME: () #[[ATTR0]] {1565// LP64: entry:1566//1567// LP64F-LP64D-LABEL: define dso_local half @f_ret_zbf_float16_zbf_s1568// LP64F-LP64D-SAME: () #[[ATTR0]] {1569// LP64F-LP64D: entry:1570//1571struct zbf_float16_zbf_s f_ret_zbf_float16_zbf_s(void) {1572 return (struct zbf_float16_zbf_s){1.0};1573}1574 1575// Check that structs containing two floating point values (FLEN <= width) are1576// expanded provided sufficient FPRs are available.1577 1578struct double_float16_s { double f; _Float16 g; };1579 1580// LP64-LP64F-LABEL: define dso_local void @f_double_float16_s_arg1581// LP64-LP64F-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1582// LP64-LP64F: entry:1583//1584// LP64D-LABEL: define dso_local void @f_double_float16_s_arg1585// LP64D-SAME: (double [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1586// LP64D: entry:1587//1588void f_double_float16_s_arg(struct double_float16_s a) {}1589 1590// LP64-LP64F-LABEL: define dso_local [2 x i64] @f_ret_double_float16_s1591// LP64-LP64F-SAME: () #[[ATTR0]] {1592// LP64-LP64F: entry:1593//1594// LP64D-LABEL: define dso_local { double, half } @f_ret_double_float16_s1595// LP64D-SAME: () #[[ATTR0]] {1596// LP64D: entry:1597//1598struct double_float16_s f_ret_double_float16_s(void) {1599 return (struct double_float16_s){1.0, 2.0};1600}1601 1602// LP64-LP64F-LP64D-LABEL: define dso_local void @f_double_float16_s_arg_insufficient_fprs1603// LP64-LP64F-LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], [2 x i64] [[H_COERCE:%.*]]) #[[ATTR0]] {1604// LP64-LP64F-LP64D: entry:1605//1606void f_double_float16_s_arg_insufficient_fprs(float a, double b, double c, double d,1607 double e, double f, double g, struct double_float16_s h) {}1608 1609// Check that structs containing int+_Float16 values are expanded, provided1610// sufficient FPRs and GPRs are available. The integer components are neither1611// sign or zero-extended.1612 1613struct float16_int8_s { _Float16 f; int8_t i; };1614struct float16_uint8_s { _Float16 f; uint8_t i; };1615struct float16_int32_s { _Float16 f; int32_t i; };1616struct float16_int64_s { _Float16 f; int64_t i; };1617struct float16_int64bf_s { _Float16 f; int64_t i : 32; };1618struct float16_int8_zbf_s { _Float16 f; int8_t i; int : 0; };1619 1620// LP64-LABEL: define dso_local void @f_float16_int8_s_arg1621// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1622// LP64: entry:1623//1624// LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_s_arg1625// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1626// LP64F-LP64D: entry:1627//1628void f_float16_int8_s_arg(struct float16_int8_s a) {}1629 1630// LP64-LABEL: define dso_local i64 @f_ret_float16_int8_s1631// LP64-SAME: () #[[ATTR0]] {1632// LP64: entry:1633//1634// LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_s1635// LP64F-LP64D-SAME: () #[[ATTR0]] {1636// LP64F-LP64D: entry:1637//1638struct float16_int8_s f_ret_float16_int8_s(void) {1639 return (struct float16_int8_s){1.0, 2};1640}1641 1642// LP64-LABEL: define dso_local void @f_float16_uint8_s_arg1643// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1644// LP64: entry:1645//1646// LP64F-LP64D-LABEL: define dso_local void @f_float16_uint8_s_arg1647// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1648// LP64F-LP64D: entry:1649//1650void f_float16_uint8_s_arg(struct float16_uint8_s a) {}1651 1652// LP64-LABEL: define dso_local i64 @f_ret_float16_uint8_s1653// LP64-SAME: () #[[ATTR0]] {1654// LP64: entry:1655//1656// LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_uint8_s1657// LP64F-LP64D-SAME: () #[[ATTR0]] {1658// LP64F-LP64D: entry:1659//1660struct float16_uint8_s f_ret_float16_uint8_s(void) {1661 return (struct float16_uint8_s){1.0, 2};1662}1663 1664// LP64-LABEL: define dso_local void @f_float16_int32_s_arg1665// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1666// LP64: entry:1667//1668// LP64F-LP64D-LABEL: define dso_local void @f_float16_int32_s_arg1669// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {1670// LP64F-LP64D: entry:1671//1672void f_float16_int32_s_arg(struct float16_int32_s a) {}1673 1674// LP64-LABEL: define dso_local i64 @f_ret_float16_int32_s1675// LP64-SAME: () #[[ATTR0]] {1676// LP64: entry:1677//1678// LP64F-LP64D-LABEL: define dso_local { half, i32 } @f_ret_float16_int32_s1679// LP64F-LP64D-SAME: () #[[ATTR0]] {1680// LP64F-LP64D: entry:1681//1682struct float16_int32_s f_ret_float16_int32_s(void) {1683 return (struct float16_int32_s){1.0, 2};1684}1685 1686// LP64-LABEL: define dso_local void @f_float16_int64_s_arg1687// LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1688// LP64: entry:1689//1690// LP64F-LP64D-LABEL: define dso_local void @f_float16_int64_s_arg1691// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {1692// LP64F-LP64D: entry:1693//1694void f_float16_int64_s_arg(struct float16_int64_s a) {}1695 1696// LP64-LABEL: define dso_local [2 x i64] @f_ret_float16_int64_s1697// LP64-SAME: () #[[ATTR0]] {1698// LP64: entry:1699//1700// LP64F-LP64D-LABEL: define dso_local { half, i64 } @f_ret_float16_int64_s1701// LP64F-LP64D-SAME: () #[[ATTR0]] {1702// LP64F-LP64D: entry:1703//1704struct float16_int64_s f_ret_float16_int64_s(void) {1705 return (struct float16_int64_s){1.0, 2};1706}1707 1708// LP64-LABEL: define dso_local void @f_float16_int64bf_s_arg1709// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1710// LP64: entry:1711//1712// LP64F-LP64D-LABEL: define dso_local void @f_float16_int64bf_s_arg1713// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {1714// LP64F-LP64D: entry:1715//1716void f_float16_int64bf_s_arg(struct float16_int64bf_s a) {}1717 1718// LP64-LABEL: define dso_local i64 @f_ret_float16_int64bf_s1719// LP64-SAME: () #[[ATTR0]] {1720// LP64: entry:1721//1722// LP64F-LP64D-LABEL: define dso_local <{ half, i64 }> @f_ret_float16_int64bf_s1723// LP64F-LP64D-SAME: () #[[ATTR0]] {1724// LP64F-LP64D: entry:1725//1726struct float16_int64bf_s f_ret_float16_int64bf_s(void) {1727 return (struct float16_int64bf_s){1.0, 2};1728}1729 1730// The zero-width bitfield means the struct can't be passed according to the1731// floating point calling convention.1732 1733// LP64-LABEL: define dso_local void @f_float16_int8_zbf_s1734// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1735// LP64: entry:1736//1737// LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_zbf_s1738// LP64F-LP64D-SAME: (half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1739// LP64F-LP64D: entry:1740//1741void f_float16_int8_zbf_s(struct float16_int8_zbf_s a) {}1742 1743// LP64-LABEL: define dso_local i64 @f_ret_float16_int8_zbf_s1744// LP64-SAME: () #[[ATTR0]] {1745// LP64: entry:1746//1747// LP64F-LP64D-LABEL: define dso_local { half, i8 } @f_ret_float16_int8_zbf_s1748// LP64F-LP64D-SAME: () #[[ATTR0]] {1749// LP64F-LP64D: entry:1750//1751struct float16_int8_zbf_s f_ret_float16_int8_zbf_s(void) {1752 return (struct float16_int8_zbf_s){1.0, 2};1753}1754 1755// LP64-LP64F-LP64D-LABEL: define dso_local void @f_float16_int8_s_arg_insufficient_gprs1756// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]], i32 noundef signext [[C:%.*]], i32 noundef signext [[D:%.*]], i32 noundef signext [[E:%.*]], i32 noundef signext [[F:%.*]], i32 noundef signext [[G:%.*]], i32 noundef signext [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {1757// LP64-LP64F-LP64D: entry:1758//1759void f_float16_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e,1760 int f, int g, int h, struct float16_int8_s i) {}1761 1762// LP64-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs1763// LP64-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {1764// LP64: entry:1765//1766// LP64F-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs1767// LP64F-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], half [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] {1768// LP64F: entry:1769//1770// LP64D-LABEL: define dso_local void @f_struct_float16_int8_insufficient_fprs1771// LP64D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], i64 [[I_COERCE:%.*]]) #[[ATTR0]] {1772// LP64D: entry:1773//1774void f_struct_float16_int8_insufficient_fprs(float a, double b, double c, double d,1775 double e, double f, double g, double h, struct float16_int8_s i) {}1776 1777// Complex floating-point values or structs containing a single complex1778// floating-point value should be passed as if it were an fp+fp struct.1779 1780// LP64-LABEL: define dso_local void @f_float16complex1781// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1782// LP64: entry:1783//1784// LP64F-LP64D-LABEL: define dso_local void @f_float16complex1785// LP64F-LP64D-SAME: (half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]]) #[[ATTR0]] {1786// LP64F-LP64D: entry:1787//1788void f_float16complex(_Float16 __complex__ a) {}1789 1790// LP64-LABEL: define dso_local i64 @f_ret_float16complex1791// LP64-SAME: () #[[ATTR0]] {1792// LP64: entry:1793//1794// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16complex1795// LP64F-LP64D-SAME: () #[[ATTR0]] {1796// LP64F-LP64D: entry:1797//1798_Float16 __complex__ f_ret_float16complex(void) {1799 return 1.0;1800}1801 1802struct float16complex_s { _Float16 __complex__ c; };1803 1804// LP64-LABEL: define dso_local void @f_float16complex_s_arg1805// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1806// LP64: entry:1807//1808// LP64F-LP64D-LABEL: define dso_local void @f_float16complex_s_arg1809// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1810// LP64F-LP64D: entry:1811//1812void f_float16complex_s_arg(struct float16complex_s a) {}1813 1814// LP64-LABEL: define dso_local i64 @f_ret_float16complex_s1815// LP64-SAME: () #[[ATTR0]] {1816// LP64: entry:1817//1818// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16complex_s1819// LP64F-LP64D-SAME: () #[[ATTR0]] {1820// LP64F-LP64D: entry:1821//1822struct float16complex_s f_ret_float16complex_s(void) {1823 return (struct float16complex_s){1.0};1824}1825 1826// Test single or two-element structs that need flattening. e.g. those1827// containing nested structs, _Float16 in small arrays, zero-length structs etc.1828 1829struct float16arr1_s { _Float16 a[1]; };1830 1831// LP64-LABEL: define dso_local void @f_float16arr1_s_arg1832// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1833// LP64: entry:1834//1835// LP64F-LP64D-LABEL: define dso_local void @f_float16arr1_s_arg1836// LP64F-LP64D-SAME: (half [[TMP0:%.*]]) #[[ATTR0]] {1837// LP64F-LP64D: entry:1838//1839void f_float16arr1_s_arg(struct float16arr1_s a) {}1840 1841// LP64-LABEL: define dso_local i64 @f_ret_float16arr1_s1842// LP64-SAME: () #[[ATTR0]] {1843// LP64: entry:1844//1845// LP64F-LP64D-LABEL: define dso_local half @f_ret_float16arr1_s1846// LP64F-LP64D-SAME: () #[[ATTR0]] {1847// LP64F-LP64D: entry:1848//1849struct float16arr1_s f_ret_float16arr1_s(void) {1850 return (struct float16arr1_s){{1.0}};1851}1852 1853struct float16arr2_s { _Float16 a[2]; };1854 1855// LP64-LABEL: define dso_local void @f_float16arr2_s_arg1856// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1857// LP64: entry:1858//1859// LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_s_arg1860// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1861// LP64F-LP64D: entry:1862//1863void f_float16arr2_s_arg(struct float16arr2_s a) {}1864 1865// LP64-LABEL: define dso_local i64 @f_ret_float16arr2_s1866// LP64-SAME: () #[[ATTR0]] {1867// LP64: entry:1868//1869// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_s1870// LP64F-LP64D-SAME: () #[[ATTR0]] {1871// LP64F-LP64D: entry:1872//1873struct float16arr2_s f_ret_float16arr2_s(void) {1874 return (struct float16arr2_s){{1.0, 2.0}};1875}1876 1877struct float16arr2_tricky1_s { struct { _Float16 f[1]; } g[2]; };1878 1879// LP64-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg1880// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1881// LP64: entry:1882//1883// LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky1_s_arg1884// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1885// LP64F-LP64D: entry:1886//1887void f_float16arr2_tricky1_s_arg(struct float16arr2_tricky1_s a) {}1888 1889// LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky1_s1890// LP64-SAME: () #[[ATTR0]] {1891// LP64: entry:1892//1893// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky1_s1894// LP64F-LP64D-SAME: () #[[ATTR0]] {1895// LP64F-LP64D: entry:1896//1897struct float16arr2_tricky1_s f_ret_float16arr2_tricky1_s(void) {1898 return (struct float16arr2_tricky1_s){{{{1.0}}, {{2.0}}}};1899}1900 1901struct float16arr2_tricky2_s { struct {}; struct { _Float16 f[1]; } g[2]; };1902 1903// LP64-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg1904// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1905// LP64: entry:1906//1907// LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky2_s_arg1908// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1909// LP64F-LP64D: entry:1910//1911void f_float16arr2_tricky2_s_arg(struct float16arr2_tricky2_s a) {}1912 1913// LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky2_s1914// LP64-SAME: () #[[ATTR0]] {1915// LP64: entry:1916//1917// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky2_s1918// LP64F-LP64D-SAME: () #[[ATTR0]] {1919// LP64F-LP64D: entry:1920//1921struct float16arr2_tricky2_s f_ret_float16arr2_tricky2_s(void) {1922 return (struct float16arr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};1923}1924 1925struct float16arr2_tricky3_s { union {}; struct { _Float16 f[1]; } g[2]; };1926 1927// LP64-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg1928// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1929// LP64: entry:1930//1931// LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky3_s_arg1932// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1933// LP64F-LP64D: entry:1934//1935void f_float16arr2_tricky3_s_arg(struct float16arr2_tricky3_s a) {}1936 1937// LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky3_s1938// LP64-SAME: () #[[ATTR0]] {1939// LP64: entry:1940//1941// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky3_s1942// LP64F-LP64D-SAME: () #[[ATTR0]] {1943// LP64F-LP64D: entry:1944//1945struct float16arr2_tricky3_s f_ret_float16arr2_tricky3_s(void) {1946 return (struct float16arr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};1947}1948 1949struct float16arr2_tricky4_s { union {}; struct { struct {}; _Float16 f[1]; } g[2]; };1950 1951// LP64-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg1952// LP64-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {1953// LP64: entry:1954//1955// LP64F-LP64D-LABEL: define dso_local void @f_float16arr2_tricky4_s_arg1956// LP64F-LP64D-SAME: (half [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {1957// LP64F-LP64D: entry:1958//1959void f_float16arr2_tricky4_s_arg(struct float16arr2_tricky4_s a) {}1960 1961// LP64-LABEL: define dso_local i64 @f_ret_float16arr2_tricky4_s1962// LP64-SAME: () #[[ATTR0]] {1963// LP64: entry:1964//1965// LP64F-LP64D-LABEL: define dso_local { half, half } @f_ret_float16arr2_tricky4_s1966// LP64F-LP64D-SAME: () #[[ATTR0]] {1967// LP64F-LP64D: entry:1968//1969struct float16arr2_tricky4_s f_ret_float16arr2_tricky4_s(void) {1970 return (struct float16arr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};1971}1972 1973// Test structs that should be passed according to the normal integer calling1974// convention.1975 1976struct int_float16_int_s { int a; _Float16 b; int c; };1977 1978// LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_float16_int_s_arg1979// LP64-LP64F-LP64D-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1980// LP64-LP64F-LP64D: entry:1981//1982void f_int_float16_int_s_arg(struct int_float16_int_s a) {}1983 1984// LP64-LP64F-LP64D-LABEL: define dso_local [2 x i64] @f_ret_int_float16_int_s1985// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {1986// LP64-LP64F-LP64D: entry:1987//1988struct int_float16_int_s f_ret_int_float16_int_s(void) {1989 return (struct int_float16_int_s){1, 2.0, 3};1990}1991 1992struct int64_float16_s { int64_t a; _Float16 b; };1993 1994// LP64-LABEL: define dso_local void @f_int64_float16_s_arg1995// LP64-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {1996// LP64: entry:1997//1998// LP64F-LP64D-LABEL: define dso_local void @f_int64_float16_s_arg1999// LP64F-LP64D-SAME: (i64 [[TMP0:%.*]], half [[TMP1:%.*]]) #[[ATTR0]] {2000// LP64F-LP64D: entry:2001//2002void f_int64_float16_s_arg(struct int64_float16_s a) {}2003 2004// LP64-LABEL: define dso_local [2 x i64] @f_ret_int64_float16_s2005// LP64-SAME: () #[[ATTR0]] {2006// LP64: entry:2007//2008// LP64F-LP64D-LABEL: define dso_local { i64, half } @f_ret_int64_float16_s2009// LP64F-LP64D-SAME: () #[[ATTR0]] {2010// LP64F-LP64D: entry:2011//2012struct int64_float16_s f_ret_int64_float16_s(void) {2013 return (struct int64_float16_s){1, 2.0};2014}2015 2016struct char_char_float16_s { char a; char b; _Float16 c; };2017 2018// LP64-LP64F-LP64D-LABEL: define dso_local void @f_char_char_float16_s_arg2019// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {2020// LP64-LP64F-LP64D: entry:2021//2022void f_char_char_float16_s_arg(struct char_char_float16_s a) {}2023 2024// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_char_char_float16_s2025// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {2026// LP64-LP64F-LP64D: entry:2027//2028struct char_char_float16_s f_ret_char_char_float16_s(void) {2029 return (struct char_char_float16_s){1, 2, 3.0};2030}2031 2032// Unions are always passed according to the integer calling convention, even2033// if they can only contain a double.2034 2035union float16_u { _Float16 a; };2036 2037// LP64-LP64F-LP64D-LABEL: define dso_local void @f_float16_u_arg2038// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {2039// LP64-LP64F-LP64D: entry:2040//2041void f_float16_u_arg(union float16_u a) {}2042 2043// LP64-LP64F-LP64D-LABEL: define dso_local i64 @f_ret_float16_u2044// LP64-LP64F-LP64D-SAME: () #[[ATTR0]] {2045// LP64-LP64F-LP64D: entry:2046//2047union float16_u f_ret_float16_u(void) {2048 return (union float16_u){1.0};2049}2050 2051//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:2052// LP64E: {{.*}}2053