diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1524,6 +1524,14 @@ if (isEmptyRecord(getContext(), RetTy, true)) return ABIArgInfo::getIgnore(); + // Return complex of _Float16 as <2 x half> so the backend will use xmm0. + if (const ComplexType *CT = RetTy->getAs()) { + QualType ET = getContext().getCanonicalType(CT->getElementType()); + if (ET->isFloat16Type()) + return ABIArgInfo::getDirect(llvm::FixedVectorType::get( + llvm::Type::getHalfTy(getVMContext()), 2)); + } + // Small structures which are register sized are generally returned // in a register. if (shouldReturnTypeInRegister(RetTy, getContext())) { diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1300,8 +1300,8 @@ if (!S.getLangOpts().CPlusPlus) S.Diag(TSTLoc, diag::ext_integer_complex); } else if (TypeSpecType != TST_float && TypeSpecType != TST_double && - TypeSpecType != TST_float128) { - // FIXME: _Float16, __fp16? + TypeSpecType != TST_float128 && TypeSpecType != TST_float16) { + // FIXME: __fp16? S.Diag(TSCLoc, diag::err_invalid_complex_spec) << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecComplex = TSC_unspecified; diff --git a/clang/test/CodeGen/X86/avx512fp16-complex-abi.c b/clang/test/CodeGen/X86/avx512fp16-complex-abi.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/X86/avx512fp16-complex-abi.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +avx512fp16 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK + +// Return value should be passed in <2 x half> so the backend will use xmm0 +_Complex _Float16 f16(_Complex _Float16 A, _Complex _Float16 B) { + // CHECK-LABEL: define{{.*}}<2 x half> @f16({ half, half }* byval({ half, half }) align 4 %{{.*}}, { half, half }* byval({ half, half }) align 4 %{{.*}}) + return A + B; +} diff --git a/clang/test/CodeGen/X86/avx512fp16-complex.c b/clang/test/CodeGen/X86/avx512fp16-complex.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/X86/avx512fp16-complex.c @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 %s -O0 -fno-experimental-new-pass-manager -emit-llvm -triple x86_64-unknown-unknown -target-feature +avx512fp16 -o - | FileCheck %s --check-prefix=X86 + +_Float16 _Complex add_half_rr(_Float16 a, _Float16 b) { + // X86-LABEL: @add_half_rr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +_Float16 _Complex add_half_cr(_Float16 _Complex a, _Float16 b) { + // X86-LABEL: @add_half_cr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +_Float16 _Complex add_half_rc(_Float16 a, _Float16 _Complex b) { + // X86-LABEL: @add_half_rc( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +_Float16 _Complex add_half_cc(_Float16 _Complex a, _Float16 _Complex b) { + // X86-LABEL: @add_half_cc( + // X86: fadd + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} + +_Float16 _Complex sub_half_rr(_Float16 a, _Float16 b) { + // X86-LABEL: @sub_half_rr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +_Float16 _Complex sub_half_cr(_Float16 _Complex a, _Float16 b) { + // X86-LABEL: @sub_half_cr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +_Float16 _Complex sub_half_rc(_Float16 a, _Float16 _Complex b) { + // X86-LABEL: @sub_half_rc( + // X86: fsub + // X86: fneg + // X86-NOT: fsub + // X86: ret + return a - b; +} +_Float16 _Complex sub_half_cc(_Float16 _Complex a, _Float16 _Complex b) { + // X86-LABEL: @sub_half_cc( + // X86: fsub + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} + +_Float16 _Complex mul_half_rr(_Float16 a, _Float16 b) { + // X86-LABEL: @mul_half_rr( + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +_Float16 _Complex mul_half_cr(_Float16 _Complex a, _Float16 b) { + // X86-LABEL: @mul_half_cr( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +_Float16 _Complex mul_half_rc(_Float16 a, _Float16 _Complex b) { + // X86-LABEL: @mul_half_rc( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +_Float16 _Complex mul_half_cc(_Float16 _Complex a, _Float16 _Complex b) { + // X86-LABEL: @mul_half_cc( + // X86: %[[AC:[^ ]+]] = fmul + // X86: %[[BD:[^ ]+]] = fmul + // X86: %[[AD:[^ ]+]] = fmul + // X86: %[[BC:[^ ]+]] = fmul + // X86: %[[RR:[^ ]+]] = fsub half %[[AC]], %[[BD]] + // X86: %[[RI:[^ ]+]] = fadd half + // X86-DAG: %[[AD]] + // X86-DAG: , + // X86-DAG: %[[BC]] + // X86: fcmp uno half %[[RR]] + // X86: fcmp uno half %[[RI]] + // X86: call {{.*}} @__mulhc3( + // X86: ret + return a * b; +} + +_Float16 _Complex div_half_rr(_Float16 a, _Float16 b) { + // X86-LABEL: @div_half_rr( + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +_Float16 _Complex div_half_cr(_Float16 _Complex a, _Float16 b) { + // X86-LABEL: @div_half_cr( + // X86: fdiv + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +_Float16 _Complex div_half_rc(_Float16 a, _Float16 _Complex b) { + // X86-LABEL: @div_half_rc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divhc3( + // X86: ret + return a / b; +} +_Float16 _Complex div_half_cc(_Float16 _Complex a, _Float16 _Complex b) { + // X86-LABEL: @div_half_cc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divhc3( + // X86: ret + return a / b; +} diff --git a/clang/test/Sema/Float16.c b/clang/test/Sema/Float16.c --- a/clang/test/Sema/Float16.c +++ b/clang/test/Sema/Float16.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc -target-feature +avx512fp16 %s -DHAVE // RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE // RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE // RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE @@ -9,8 +10,7 @@ _Float16 f; #ifdef HAVE -// FIXME: Should this be valid? -_Complex _Float16 a; // expected-error {{'_Complex _Float16' is invalid}} +_Complex _Float16 a; void builtin_complex() { _Float16 a = 0; (void)__builtin_complex(a, a); // expected-error {{'_Complex _Float16' is invalid}}