diff --git a/clang/test/CodeGen/RISCV/Float16.c b/clang/test/CodeGen/RISCV/Float16.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/Float16.c @@ -0,0 +1,375 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -O0 -target-abi ilp32 -emit-llvm %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-NOZFH-ILP32 %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-zfh -O0 -target-abi ilp32 -emit-llvm %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZFH-ILP32 %s +// RUN: %clang_cc1 -triple riscv32 -O0 -target-abi ilp32f -emit-llvm %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-NOZFH-ILP32F %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-zfh -O0 -target-abi ilp32f -emit-llvm %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZFH-ILP32F %s + +#include + +_Float16 varg(int num, ...); + +// CHECK-NOZFH-ILP32-LABEL: @foo( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: store half [[B:%.*]], half* [[B_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[TMP1:%.*]] = load half, half* [[B_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] +// CHECK-NOZFH-ILP32-NEXT: ret half [[ADD]] +// +// CHECK-ZFH-ILP32-LABEL: @foo( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: store half [[B:%.*]], half* [[B_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[TMP1:%.*]] = load half, half* [[B_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] +// CHECK-ZFH-ILP32-NEXT: ret half [[ADD]] +// +// CHECK-NOZFH-ILP32F-LABEL: @foo( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32F-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: store half [[B:%.*]], half* [[B_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP1:%.*]] = load half, half* [[B_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] +// CHECK-NOZFH-ILP32F-NEXT: ret half [[ADD]] +// +// CHECK-ZFH-ILP32F-LABEL: @foo( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32F-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32F-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: store half [[B:%.*]], half* [[B_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[TMP1:%.*]] = load half, half* [[B_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] +// CHECK-ZFH-ILP32F-NEXT: ret half [[ADD]] +// +_Float16 foo(_Float16 a, _Float16 b) { + return a + b; +} + +// CHECK-NOZFH-ILP32-LABEL: @foo1( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[CALL:%.*]] = call half (i32, ...) @varg(i32 1, half [[TMP0]]) +// CHECK-NOZFH-ILP32-NEXT: ret half [[CALL]] +// +// CHECK-ZFH-ILP32-LABEL: @foo1( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[CALL:%.*]] = call half (i32, ...) @varg(i32 1, half [[TMP0]]) +// CHECK-ZFH-ILP32-NEXT: ret half [[CALL]] +// +// CHECK-NOZFH-ILP32F-LABEL: @foo1( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32F-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[CALL:%.*]] = call half (i32, ...) @varg(i32 1, half [[TMP0]]) +// CHECK-NOZFH-ILP32F-NEXT: ret half [[CALL]] +// +// CHECK-ZFH-ILP32F-LABEL: @foo1( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32F-NEXT: store half [[A:%.*]], half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[A_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[CALL:%.*]] = call half (i32, ...) @varg(i32 1, half [[TMP0]]) +// CHECK-ZFH-ILP32F-NEXT: ret half [[CALL]] +// +_Float16 foo1(_Float16 a) { + return varg(1, a); +} + +struct f16_agg { + _Float16 a, b; +}; + +// CHECK-NOZFH-ILP32-LABEL: @test_f16_agg_1( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[X:%.*]] = alloca [[STRUCT_F16_AGG:%.*]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_agg* [[X]] to i32* +// CHECK-NOZFH-ILP32-NEXT: store i32 [[X_COERCE:%.*]], i32* [[TMP0]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 1 +// CHECK-NOZFH-ILP32-NEXT: [[TMP1:%.*]] = load half, half* [[B]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 0 +// CHECK-NOZFH-ILP32-NEXT: [[TMP2:%.*]] = load half, half* [[A]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[ADD:%.*]] = fadd half [[TMP2]], [[TMP1]] +// CHECK-NOZFH-ILP32-NEXT: store half [[ADD]], half* [[A]], align 2 +// CHECK-NOZFH-ILP32-NEXT: ret void +// +// CHECK-ZFH-ILP32-LABEL: @test_f16_agg_1( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[X:%.*]] = alloca [[STRUCT_F16_AGG:%.*]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_agg* [[X]] to i32* +// CHECK-ZFH-ILP32-NEXT: store i32 [[X_COERCE:%.*]], i32* [[TMP0]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 1 +// CHECK-ZFH-ILP32-NEXT: [[TMP1:%.*]] = load half, half* [[B]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 0 +// CHECK-ZFH-ILP32-NEXT: [[TMP2:%.*]] = load half, half* [[A]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[ADD:%.*]] = fadd half [[TMP2]], [[TMP1]] +// CHECK-ZFH-ILP32-NEXT: store half [[ADD]], half* [[A]], align 2 +// CHECK-ZFH-ILP32-NEXT: ret void +// +// CHECK-NOZFH-ILP32F-LABEL: @test_f16_agg_1( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[X:%.*]] = alloca [[STRUCT_F16_AGG:%.*]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_agg* [[X]] to i32* +// CHECK-NOZFH-ILP32F-NEXT: store i32 [[X_COERCE:%.*]], i32* [[TMP0]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 1 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP1:%.*]] = load half, half* [[B]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 0 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP2:%.*]] = load half, half* [[A]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[ADD:%.*]] = fadd half [[TMP2]], [[TMP1]] +// CHECK-NOZFH-ILP32F-NEXT: store half [[ADD]], half* [[A]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: ret void +// +// CHECK-ZFH-ILP32F-LABEL: @test_f16_agg_1( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[X:%.*]] = alloca [[STRUCT_F16_AGG:%.*]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_agg* [[X]] to i32* +// CHECK-ZFH-ILP32F-NEXT: store i32 [[X_COERCE:%.*]], i32* [[TMP0]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 1 +// CHECK-ZFH-ILP32F-NEXT: [[TMP1:%.*]] = load half, half* [[B]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_AGG]], %struct.f16_agg* [[X]], i32 0, i32 0 +// CHECK-ZFH-ILP32F-NEXT: [[TMP2:%.*]] = load half, half* [[A]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[ADD:%.*]] = fadd half [[TMP2]], [[TMP1]] +// CHECK-ZFH-ILP32F-NEXT: store half [[ADD]], half* [[A]], align 2 +// CHECK-ZFH-ILP32F-NEXT: ret void +// +void test_f16_agg_1(struct f16_agg x) { + x.a += x.b; +} + +struct f16_float_agg { + _Float16 a; + float b; +}; + +// CHECK-NOZFH-ILP32-LABEL: @test_f16_agg_2( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[A]] to [2 x i32]* +// CHECK-NOZFH-ILP32-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32-NEXT: ret void +// +// CHECK-ZFH-ILP32-LABEL: @test_f16_agg_2( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[A]] to [2 x i32]* +// CHECK-ZFH-ILP32-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32-NEXT: ret void +// +// CHECK-NOZFH-ILP32F-LABEL: @test_f16_agg_2( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[A]] to [2 x i32]* +// CHECK-NOZFH-ILP32F-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: ret void +// +// CHECK-ZFH-ILP32F-LABEL: @test_f16_agg_2( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[A]] to [2 x i32]* +// CHECK-ZFH-ILP32F-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32F-NEXT: ret void +// +void test_f16_agg_2(struct f16_float_agg a) {} + +// CHECK-NOZFH-ILP32-LABEL: @test_f16_agg_3( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-NOZFH-ILP32-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-NOZFH-ILP32-NEXT: store float 2.000000e+00, float* [[B]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[RETVAL]] to [2 x i32]* +// CHECK-NOZFH-ILP32-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-ZFH-ILP32-LABEL: @test_f16_agg_3( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-ZFH-ILP32-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-ZFH-ILP32-NEXT: store float 2.000000e+00, float* [[B]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[RETVAL]] to [2 x i32]* +// CHECK-ZFH-ILP32-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-NOZFH-ILP32F-LABEL: @test_f16_agg_3( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-NOZFH-ILP32F-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-NOZFH-ILP32F-NEXT: store float 2.000000e+00, float* [[B]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[RETVAL]] to [2 x i32]* +// CHECK-NOZFH-ILP32F-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-ZFH-ILP32F-LABEL: @test_f16_agg_3( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_FLOAT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-ZFH-ILP32F-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_FLOAT_AGG]], %struct.f16_float_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-ZFH-ILP32F-NEXT: store float 2.000000e+00, float* [[B]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_float_agg* [[RETVAL]] to [2 x i32]* +// CHECK-ZFH-ILP32F-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32F-NEXT: ret [2 x i32] [[TMP1]] +// +struct f16_float_agg test_f16_agg_3() { return (struct f16_float_agg){1.0, 2.0}; } + +struct f16_int_agg { + _Float16 a; + int32_t b; +}; + +// CHECK-NOZFH-ILP32-LABEL: @test_f16_agg_4( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[A]] to [2 x i32]* +// CHECK-NOZFH-ILP32-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32-NEXT: ret void +// +// CHECK-ZFH-ILP32-LABEL: @test_f16_agg_4( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[A]] to [2 x i32]* +// CHECK-ZFH-ILP32-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32-NEXT: ret void +// +// CHECK-NOZFH-ILP32F-LABEL: @test_f16_agg_4( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[A]] to [2 x i32]* +// CHECK-NOZFH-ILP32F-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: ret void +// +// CHECK-ZFH-ILP32F-LABEL: @test_f16_agg_4( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[A:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[A]] to [2 x i32]* +// CHECK-ZFH-ILP32F-NEXT: store [2 x i32] [[A_COERCE:%.*]], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32F-NEXT: ret void +// +void test_f16_agg_4(struct f16_int_agg a) {} + +// CHECK-NOZFH-ILP32-LABEL: @test_f16_agg_5( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-NOZFH-ILP32-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-NOZFH-ILP32-NEXT: store i32 2, i32* [[B]], align 4 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[RETVAL]] to [2 x i32]* +// CHECK-NOZFH-ILP32-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-ZFH-ILP32-LABEL: @test_f16_agg_5( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-ZFH-ILP32-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-ZFH-ILP32-NEXT: store i32 2, i32* [[B]], align 4 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[RETVAL]] to [2 x i32]* +// CHECK-ZFH-ILP32-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-NOZFH-ILP32F-LABEL: @test_f16_agg_5( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-NOZFH-ILP32F-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-NOZFH-ILP32F-NEXT: store i32 2, i32* [[B]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[RETVAL]] to [2 x i32]* +// CHECK-NOZFH-ILP32F-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: ret [2 x i32] [[TMP1]] +// +// CHECK-ZFH-ILP32F-LABEL: @test_f16_agg_5( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_F16_INT_AGG:%.*]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 0 +// CHECK-ZFH-ILP32F-NEXT: store half 0xH3C00, half* [[A]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_F16_INT_AGG]], %struct.f16_int_agg* [[RETVAL]], i32 0, i32 1 +// CHECK-ZFH-ILP32F-NEXT: store i32 2, i32* [[B]], align 4 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = bitcast %struct.f16_int_agg* [[RETVAL]] to [2 x i32]* +// CHECK-ZFH-ILP32F-NEXT: [[TMP1:%.*]] = load [2 x i32], [2 x i32]* [[TMP0]], align 4 +// CHECK-ZFH-ILP32F-NEXT: ret [2 x i32] [[TMP1]] +// +struct f16_int_agg test_f16_agg_5() { return (struct f16_int_agg){1.0, 2}; } + +// CHECK-NOZFH-ILP32-LABEL: @f16_scalar_stack_1( +// CHECK-NOZFH-ILP32-NEXT: entry: +// CHECK-NOZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NOZFH-ILP32-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NOZFH-ILP32-NEXT: [[C_ADDR:%.*]] = alloca float, align 4 +// CHECK-NOZFH-ILP32-NEXT: [[D_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NOZFH-ILP32-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NOZFH-ILP32-NEXT: store float [[C:%.*]], float* [[C_ADDR]], align 4 +// CHECK-NOZFH-ILP32-NEXT: store half [[D:%.*]], half* [[D_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[D_ADDR]], align 2 +// CHECK-NOZFH-ILP32-NEXT: ret half [[TMP0]] +// +// CHECK-ZFH-ILP32-LABEL: @f16_scalar_stack_1( +// CHECK-ZFH-ILP32-NEXT: entry: +// CHECK-ZFH-ILP32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-ZFH-ILP32-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-ZFH-ILP32-NEXT: [[C_ADDR:%.*]] = alloca float, align 4 +// CHECK-ZFH-ILP32-NEXT: [[D_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-ZFH-ILP32-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-ZFH-ILP32-NEXT: store float [[C:%.*]], float* [[C_ADDR]], align 4 +// CHECK-ZFH-ILP32-NEXT: store half [[D:%.*]], half* [[D_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: [[TMP0:%.*]] = load half, half* [[D_ADDR]], align 2 +// CHECK-ZFH-ILP32-NEXT: ret half [[TMP0]] +// +// CHECK-NOZFH-ILP32F-LABEL: @f16_scalar_stack_1( +// CHECK-NOZFH-ILP32F-NEXT: entry: +// CHECK-NOZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NOZFH-ILP32F-NEXT: [[C_ADDR:%.*]] = alloca float, align 4 +// CHECK-NOZFH-ILP32F-NEXT: [[D_ADDR:%.*]] = alloca half, align 2 +// CHECK-NOZFH-ILP32F-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NOZFH-ILP32F-NEXT: store float [[C:%.*]], float* [[C_ADDR]], align 4 +// CHECK-NOZFH-ILP32F-NEXT: store half [[D:%.*]], half* [[D_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[D_ADDR]], align 2 +// CHECK-NOZFH-ILP32F-NEXT: ret half [[TMP0]] +// +// CHECK-ZFH-ILP32F-LABEL: @f16_scalar_stack_1( +// CHECK-ZFH-ILP32F-NEXT: entry: +// CHECK-ZFH-ILP32F-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-ZFH-ILP32F-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-ZFH-ILP32F-NEXT: [[C_ADDR:%.*]] = alloca float, align 4 +// CHECK-ZFH-ILP32F-NEXT: [[D_ADDR:%.*]] = alloca half, align 2 +// CHECK-ZFH-ILP32F-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-ZFH-ILP32F-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-ZFH-ILP32F-NEXT: store float [[C:%.*]], float* [[C_ADDR]], align 4 +// CHECK-ZFH-ILP32F-NEXT: store half [[D:%.*]], half* [[D_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: [[TMP0:%.*]] = load half, half* [[D_ADDR]], align 2 +// CHECK-ZFH-ILP32F-NEXT: ret half [[TMP0]] +// +_Float16 f16_scalar_stack_1(int32_t a, int64_t b, float c, _Float16 d) { + return d; +}