@@ -50,6 +50,9 @@ long long pass_longlong(long long arg) { return arg; }
5050__int128 pass_int128 (__int128 arg ) { return arg ; }
5151// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0)
5252
53+ _Float16 pass__Float16 (_Float16 arg ) { return arg ; }
54+ // CHECK-LABEL: define{{.*}} half @pass__Float16(half %{{.*}})
55+
5356float pass_float (float arg ) { return arg ; }
5457// CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}})
5558
@@ -77,6 +80,9 @@ _Complex long pass_complex_long(_Complex long arg) { return arg; }
7780_Complex long long pass_complex_longlong (_Complex long long arg ) { return arg ; }
7881// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg)
7982
83+ _Complex _Float16 pass_complex__Float16 (_Complex _Float16 arg ) { return arg ; }
84+ // CHECK-LABEL: define{{.*}} void @pass_complex__Float16(ptr dead_on_unwind noalias writable sret({ half, half }) align 2 %{{.*}}, ptr %{{.*}}arg)
85+
8086_Complex float pass_complex_float (_Complex float arg ) { return arg ; }
8187// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg)
8288
@@ -128,6 +134,11 @@ struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
128134
129135// Float-like aggregate types
130136
137+ struct agg__Float16 { _Float16 a ; };
138+ struct agg__Float16 pass_agg__Float16 (struct agg__Float16 arg ) { return arg ; }
139+ // HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, half %{{.*}})
140+ // SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
141+
131142struct agg_float { float a ; };
132143struct agg_float pass_agg_float (struct agg_float arg ) { return arg ; }
133144// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}})
@@ -142,6 +153,11 @@ struct agg_longdouble { long double a; };
142153struct agg_longdouble pass_agg_longdouble (struct agg_longdouble arg ) { return arg ; }
143154// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}})
144155
156+ struct agg__Float16_a8 { _Float16 a __attribute__((aligned (8 ))); };
157+ struct agg__Float16_a8 pass_agg__Float16_a8 (struct agg__Float16_a8 arg ) { return arg ; }
158+ // HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, double %{{.*}})
159+ // SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, i64 %{{.*}})
160+
145161struct agg_float_a8 { float a __attribute__((aligned (8 ))); };
146162struct agg_float_a8 pass_agg_float_a8 (struct agg_float_a8 arg ) { return arg ; }
147163// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}})
@@ -169,6 +185,10 @@ struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
169185
170186// Union types likewise are *not* float-like aggregate types
171187
188+ union union__Float16 { _Float16 a ; };
189+ union union__Float16 pass_union__Float16 (union union__Float16 arg ) { return arg ; }
190+ // CHECK-LABEL: define{{.*}} void @pass_union__Float16(ptr dead_on_unwind noalias writable sret(%union.union__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
191+
172192union union_float { float a ; };
173193union union_float pass_union_float (union union_float arg ) { return arg ; }
174194// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 noext %{{.*}})
@@ -446,6 +466,30 @@ struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l,
446466// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
447467// CHECK: ret void
448468
469+ struct agg__Float16 va_agg__Float16 (__builtin_va_list l ) { return __builtin_va_arg (l , struct agg__Float16 ); }
470+ // CHECK-LABEL: define{{.*}} void @va_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, ptr %{{.*}}
471+ // HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
472+ // SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0
473+ // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]]
474+ // HARD-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 4
475+ // SOFT-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5
476+ // CHECK: br i1 [[FITS_IN_REGS]],
477+ // CHECK: [[SCALED_REG_COUNT:%[^ ]+]] = mul i64 [[REG_COUNT]], 8
478+ // HARD-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 128
479+ // SOFT-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 22
480+ // CHECK: [[REG_SAVE_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 3
481+ // CHECK: [[REG_SAVE_AREA:%[^ ]+]] = load ptr, ptr [[REG_SAVE_AREA_PTR:[^ ]+]]
482+ // CHECK: [[RAW_REG_ADDR:%[^ ]+]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i64 [[REG_OFFSET]]
483+ // CHECK: [[REG_COUNT1:%[^ ]+]] = add i64 [[REG_COUNT]], 1
484+ // CHECK: store i64 [[REG_COUNT1]], ptr [[REG_COUNT_PTR]]
485+ // CHECK: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2
486+ // CHECK: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]]
487+ // CHECK: [[RAW_MEM_ADDR:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 6
488+ // CHECK: [[OVERFLOW_ARG_AREA2:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8
489+ // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]]
490+ // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
491+ // CHECK: ret void
492+
449493struct agg_float va_agg_float (__builtin_va_list l ) { return __builtin_va_arg (l , struct agg_float ); }
450494// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}}
451495// HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
0 commit comments