@@ -52,6 +52,9 @@ long long pass_longlong(long long arg) { return arg; }
5252__int128 pass_int128 (__int128 arg ) { return arg ; }
5353// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0)
5454
55+ _Float16 pass__Float16 (_Float16 arg ) { return arg ; }
56+ // CHECK-LABEL: define{{.*}} half @pass__Float16(half %{{.*}})
57+
5558float pass_float (float arg ) { return arg ; }
5659// CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}})
5760
@@ -79,6 +82,9 @@ _Complex long pass_complex_long(_Complex long arg) { return arg; }
7982_Complex long long pass_complex_longlong (_Complex long long arg ) { return arg ; }
8083// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg)
8184
85+ _Complex _Float16 pass_complex__Float16 (_Complex _Float16 arg ) { return arg ; }
86+ // CHECK-LABEL: define{{.*}} void @pass_complex__Float16(ptr dead_on_unwind noalias writable sret({ half, half }) align 2 %{{.*}}, ptr %{{.*}}arg)
87+
8288_Complex float pass_complex_float (_Complex float arg ) { return arg ; }
8389// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg)
8490
@@ -130,6 +136,11 @@ struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
130136
131137// Float-like aggregate types
132138
139+ struct agg__Float16 { _Float16 a ; };
140+ struct agg__Float16 pass_agg__Float16 (struct agg__Float16 arg ) { return arg ; }
141+ // HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, half %{{.*}})
142+ // SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
143+
133144struct agg_float { float a ; };
134145struct agg_float pass_agg_float (struct agg_float arg ) { return arg ; }
135146// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}})
@@ -144,6 +155,20 @@ struct agg_longdouble { long double a; };
144155struct agg_longdouble pass_agg_longdouble (struct agg_longdouble arg ) { return arg ; }
145156// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}})
146157
158+ struct agg__Float16_a4 { _Float16 a __attribute__((aligned (4 ))); };
159+ struct agg__Float16_a4 pass_agg__Float16_a4 (struct agg__Float16_a4 arg ) { return arg ; }
160+ // HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a4(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a4) align 4 %{{.*}}, float %{{.*}})
161+ // SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a4(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a4) align 4 %{{.*}}, i32 noext %{{.*}})
162+
163+ struct agg__Float16_a8 { _Float16 a __attribute__((aligned (8 ))); };
164+ struct agg__Float16_a8 pass_agg__Float16_a8 (struct agg__Float16_a8 arg ) { return arg ; }
165+ // HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, double %{{.*}})
166+ // SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, i64 %{{.*}})
167+
168+ struct agg__Float16_a16 { _Float16 a __attribute__((aligned (16 ))); };
169+ struct agg__Float16_a16 pass_agg__Float16_a16 (struct agg__Float16_a16 arg ) { return arg ; }
170+ // CHECK-LABEL: define{{.*}} void @pass_agg__Float16_a16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a16) align 16 %{{.*}}, ptr %{{.*}})
171+
147172struct agg_float_a8 { float a __attribute__((aligned (8 ))); };
148173struct agg_float_a8 pass_agg_float_a8 (struct agg_float_a8 arg ) { return arg ; }
149174// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}})
@@ -171,6 +196,10 @@ struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
171196
172197// Union types likewise are *not* float-like aggregate types
173198
199+ union union__Float16 { _Float16 a ; };
200+ union union__Float16 pass_union__Float16 (union union__Float16 arg ) { return arg ; }
201+ // CHECK-LABEL: define{{.*}} void @pass_union__Float16(ptr dead_on_unwind noalias writable sret(%union.union__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
202+
174203union union_float { float a ; };
175204union union_float pass_union_float (union union_float arg ) { return arg ; }
176205// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 noext %{{.*}})
@@ -448,6 +477,30 @@ struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l,
448477// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
449478// CHECK: ret void
450479
480+ struct agg__Float16 va_agg__Float16 (__builtin_va_list l ) { return __builtin_va_arg (l , struct agg__Float16 ); }
481+ // CHECK-LABEL: define{{.*}} void @va_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, ptr %{{.*}}
482+ // HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
483+ // SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0
484+ // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]]
485+ // HARD-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 4
486+ // SOFT-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5
487+ // CHECK: br i1 [[FITS_IN_REGS]],
488+ // CHECK: [[SCALED_REG_COUNT:%[^ ]+]] = mul i64 [[REG_COUNT]], 8
489+ // HARD-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 128
490+ // SOFT-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 22
491+ // CHECK: [[REG_SAVE_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 3
492+ // CHECK: [[REG_SAVE_AREA:%[^ ]+]] = load ptr, ptr [[REG_SAVE_AREA_PTR:[^ ]+]]
493+ // CHECK: [[RAW_REG_ADDR:%[^ ]+]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i64 [[REG_OFFSET]]
494+ // CHECK: [[REG_COUNT1:%[^ ]+]] = add i64 [[REG_COUNT]], 1
495+ // CHECK: store i64 [[REG_COUNT1]], ptr [[REG_COUNT_PTR]]
496+ // CHECK: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2
497+ // CHECK: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]]
498+ // CHECK: [[RAW_MEM_ADDR:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 6
499+ // CHECK: [[OVERFLOW_ARG_AREA2:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8
500+ // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]]
501+ // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
502+ // CHECK: ret void
503+
451504struct agg_float va_agg_float (__builtin_va_list l ) { return __builtin_va_arg (l , struct agg_float ); }
452505// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}}
453506// HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
0 commit comments